• [技术干货] ARM Linux 环境 c程序设计
    正所谓:工欲善其事必先利其器   开发环境ip地址配置如下:windows工作主机地址为:192.168.1.101 linux宿主机 eth0 ip地址为192.168.1.102   tap0 ip地址 10.0.0.1 arm虚拟机ip地址为 10.0.0.101:编辑源码在windows主机上编辑以下的c语言源代码#include <stdio.h>int func(int n){int sum=0; for(i=0;i<n;i++){sum+=i;}return sum;}main(){int i;long result=0; for(i=1;i<=100;i++){result+=i;}printf("result[1-100]=%d\n",result);printf("result[1-250]=%d\n",func(250));保存文件为test.c通过Samba服务将服务文件复制到linux宿主机中  设置/opt/work目录为共享目录  编辑/etc/samba/smb.conf配置文件  在最后加入内容{root}path=/opt/workvalid users=rootwritable=yes添加root用户smbpasswd - arootNew Smb passwordRetype new SMB password修改好配置文件重启服务   在windows工作主机访问共享目录  可以设置映射网络驱动器  这样就可以像访问本地磁盘一样访问共享目录了2:交叉编译源程序 test.c已经编译完成并赋值到了linux宿主机的/opt/work中 下面进行交叉编译# arm-linux-gcc-g test.c- o test在编译之前需要检查gcc版本3:下载程序到arm虚拟机中去交叉编译完成后需要将test程序赋值到arm虚拟中去  打开arm虚拟机 使用ftp登录到arm虚拟机上#fp 10.0.0.10Connected to 10.0.0.10220 Friendly  Arm  ftp  server  verstion 6.4/OpenBsd/linux-ftpd-0.17 readyname(10.0.010:root):plg331Passwird required for plgpassword:230 User plg logged in.Remote system type is  UNixusing binary mode to transfer filesfip>登录用户名  密码为plg 使用put命令上传文件ftp>put(local-file)/opt/work/test(remote-file)testlocal:/opt/work/test remote:test200 PORT command successful150 opening binary mode data connection for  test   226transfer complete  9250 bytes sent in 0.00 secs(19057.4kb/s)上传的文件在arm虚拟机的/home/plg目录下使用gdb进行远程调试修改test程序属性{root@friendlyarm/opt}#chmod a+ x test在arm虚拟机中运行 gdbserver  设置调试端口9000# ./gdvsever 10.0.01:9000 testProcess test created;pid=792listening on port 9000在linux宿主机上运行gdb 链接在arm虚拟机中的gdbserver进行远程调试#./arm-linux-gdb/opt/work/testGNU  gdb (GDB)7.2license gplv3+:gnu gpl version 3 or later<http://gnu。org/licenses/gpl。html>this is free softwate :you are free to change and redistribute it......................warning unable to find dynameic linker breakpoint  function GDB will be  unable to debug shared library initalizersand track explicitly loaded dynameic code.(gdb)1cannot access memory at address 0x06{sum+=i;} return sum;}12main()13{14int i;15int result=0;(gdb)在arm虚拟机中将显示连接成功#./gdbserver 10.0.0.1;9000 testProcess test created pid=792listening on port 9000remote debugging from host 10.0.0.1;
  • [已解决问题归档] 【AICC产品】【IVR】能否提供vxml脚本调用linux动态库的demo
    【问题来源】【必填】      北京**局点    【问题简要】【必填】  业务开发需要利用ivr流程获取呼叫信息,再通过动态库传递给业务系统,ISV希望提供vxml脚本调用linux动态库传递数据的demo【问题类别】【必填】     CTI【AICC解决方案版本】【必填】    【UAP版本:UAP9600 V100R005C00SPC016】    【CTI版本:ICD V300R008C21】【期望解决时间】【选填】     尽快【问题现象描述】【必填】    【日志或错误截图】【可选】        无 【附件】【可选】
  • [AC专区] Agile Controller -IoT R20C10SPC100的部署前 安装RPM依赖包
    安装Agile Controller-IoT_Lite_V300R020C10SPC100、Agile Controller-IoT_SGCC_V300R020C10SPC100、Agile Controller-IoT_Standard_V300R020C10SPC100版本,若安装使用的是SUSE系统,则安装前,必须安装SUSE服务器依赖软件包,否则会导致Agile Controller-IoT安装失败。SUSE服务器依赖软件包请用户参考产品文档自行安装。也可以使用附件一键式部署。
  • [应用开发] aarch64-linux-gnu-g++ 编译华为代码报错
    【功能模块】    感知、规划、控制、通信代码都编译不过,华为自带的ara软件【操作步骤&问题现象】1、电脑安装g++ multib后,用aarch64-linux-g++编译就通不过了,然后卸掉g++ multib,重新安装了华为带的交叉编译环境还是编译不过2、华为自带的ara软件也编译不过,请华为专家帮忙解决一下这问题【截图信息】/usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/hwcommon/log/LogStreamBuffer.h:34:22: note: candidate: ara::godel::common::log::LogStreamBuffer& ara::godel::common::log::LogStreamBuffer::operator<<(double)     LogStreamBuffer& operator<<(double num);                      ^In file included from /usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/log/logger.h:55:0,                 from /usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/log/logging.h:58,                 from /home/china-conch/AAAA/git_project/conchpilot/include/fsm/fsm_rxserviceprovider.h:14,                 from /home/china-conch/AAAA/git_project/conchpilot/include/driver/lidar/robosensor/robosensor_driver_application.h:23,                 from /home/china-conch/AAAA/git_project/conchpilot/src/driver/lidar/robosensor/robosensor_driver_application.cpp:10:/usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/log/logstream.h: In function ‘ara::log::LogStream& ara::log::operator<<(ara::log::LogStream&, const void*)’:/usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/log/logstream.h:410:65: error: cast from ‘const void*’ to ‘uintptr_t {aka unsigned int}’ loses precision [-fpermissive]     return (out << loghex(reinterpret_cast<std::uintptr_t>(value)));                                                                 ^In file included from /usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/com/types.h:9:0,                 from /home/china-conch/AAAA/git_project/conchpilot/generated/includes/mdc/sensor/canrxserviceinterface_common.h:9,                 from /home/china-conch/AAAA/git_project/conchpilot/generated/canrxserviceinterface_common.cpp:6:/usr/aarch64-linux-gnu/include/c++/5/memory: In function ‘void* std::align(std::size_t, std::size_t, void*&, std::size_t&)’:/usr/aarch64-linux-gnu/include/c++/5/memory:117:58: error: cast from ‘void*’ to ‘uintptr_t {aka unsigned int}’ loses precision [-fpermissive]   const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);                                                          ^src/driver/can/CMakeFiles/can.dir/build.make:62: recipe for target 'src/driver/can/CMakeFiles/can.dir/can.cpp.o' failedmake[2]: *** [src/driver/can/CMakeFiles/can.dir/can.cpp.o] Error 1make[2]: *** 正在等待未完成的任务....[ 15%] Building CXX object src/driver/lidar/robosensor/CMakeFiles/driver_lidar_robosensor.dir/__/__/__/__/generated/driverlidarserviceinterface_common.cpp.osrc/driver/can/CMakeFiles/can.dir/build.make:86: recipe for target 'src/driver/can/CMakeFiles/can.dir/__/__/__/generated/canrxserviceinterface_common.cpp.o' failedmake[2]: *** [src/driver/can/CMakeFiles/can.dir/__/__/__/generated/canrxserviceinterface_common.cpp.o] Error 1CMakeFiles/Makefile2:621: recipe for target 'src/driver/can/CMakeFiles/can.dir/all' failedmake[1]: *** [src/driver/can/CMakeFiles/can.dir/all] Error 2[ 16%] Building CXX object src/driver/lidar/robosensor/CMakeFiles/driver_lidar_robosensor.dir/__/__/__/fsm/fsm_rxserviceprovider.cpp.oIn file included from /usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/com/types.h:9:0,                 from /home/china-conch/AAAA/git_project/conchpilot/generated/includes/conch/driver/lidar/driverlidarserviceinterface_common.h:9,                 from /home/china-conch/AAAA/git_project/conchpilot/generated/driverlidarserviceinterface_common.cpp:6:/usr/aarch64-linux-gnu/include/c++/5/memory: In function ‘void* std::align(std::size_t, std::size_t, void*&, std::size_t&)’:/usr/aarch64-linux-gnu/include/c++/5/memory:117:58: error: cast from ‘void*’ to ‘uintptr_t {aka unsigned int}’ loses precision [-fpermissive]   const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);                                                          ^In file included from /usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/com/types.h:9:0,                 from /usr/ubuntu_crossbuild_devkit/mdc_crossbuild_sysroot/usr/local/include/ara/com/internal/skeleton/SkeletonAdapter.h:11,                 from /home/china-conch/AAAA/git_project/conchpilot/generated/includes/conch/fsmrx/fsmrxserviceinterface_skeleton.h:9,                 from /home/china-conch/AAAA/git_project/conchpilot/include/fsm/fsm_rxserviceprovider.h:11,                 from /home/china-conch/AAAA/git_project/conchpilot/src/fsm/fsm_rxserviceprovider.cpp:13:/usr/aarch64-linux-gnu/include/c++/5/memory: In function ‘void* std::align(std::size_t, std::size_t, void*&, std::size_t&)’:/usr/aarch64-linux-gnu/include/c++/5/memory:117:58: error: cast from ‘void*’ to ‘uintptr_t {aka unsigned int}’ loses precision [-fpermissive]   const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);                                                          ^
  • [技术干货] 嵌入式Linux串口基本编程
    嵌入式Linux串口编程Linux下的串口设备主要在dev目录下,比如ttySx或者ttySUx或者ttyOx。比am1808 是ttyS0-S2SU0-SU7,而am335x是ttyO0-O5。一、基本编程API介绍最基本的设置串口包括波特率设置,效验位和停止位设置。1、串口的设置主要是设置 structtermios结构体的各成员值。struct termios   {     unsigned short  c_iflag; /* 输入模式标志 */     unsigned short  c_oflag; /* 输出模式标志 */     unsigned short  c_cflag; /* 控制模式标志*/     unsigned short  c_lflag; /* 本地模式标志 */     unsigned char  c_line; /* 控制协议 */     unsigned char  c_cc[NCC]; /* 控制模式字符*/};所有对串口的操作都是通过结构体 struct  termios和几个函数实现的,其中两个最常用的函数是tcgetattr()和tcsetattr()几乎在所有情况下,程序都是通过tcgetattr()函数获取设备当前的设置,然后修改这些设置,最后用tcsetattr()使这些设置生效。许多程序会保存终端初始的设置并在终止运行前恢复这些设置。函数返回0表示成功。2、tcgetattr和tcsetattr函数int tcgetattr (int  fd ,struct termios *t)   用于获得文件描述符fd所表示设备的当前设置值,并写入指针t内int tcsetattr    (int fd, int options,struct termios *t)用来将termios结构指针t内的设置值赋给当前用文件描述符fd表示的设备终端参数options决定什么时候改变才生效     TCSANOW———修改立即生效     TCSADRAIN——所有已经发送的输出写入fd后生效     TCSAFLUSH——输出队列为空时生效例如:下面是修改波特率的代码:struct termios  Opt;tcgetattr(fd, &Opt);cfsetispeed(&Opt,B19200); /*设置为19200Bps*/cfsetospeed(&Opt,B19200);tcsetattr(fd,TCANOW,&Opt);3、波特率设定cfsetispeed()和cfsetospeed()函数分别用来设置设备的输入输出速度。int cfsetispeed(struct termios *t,speed_t speed)    int cfsetospeed(struct termios *t ,speed_t speed)通过结构体t分别将设备的输入输出速度设为speed。它们只是设置了termios结构体的速度,若要修改设备的速度还需要调用tcsetattr()函数下面看一个设置波特率的例子int speed_arr[] = { B38400, B19200,B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200,B300, };    int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,19200, 9600, 4800, 2400, 1200, 300, };void set_speed(int fd, int speed)  { int i; int status;     struct termios Opt;     tcgetattr(fd, &Opt);     for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)        { if (speed == name_arr)              { tcflush(fd, TCIOFLUSH);                 cfsetispeed(&Opt,speed_arr);                                      cfsetospeed(&Opt, speed_arr);                 status = tcsetattr(fd1,TCSANOW, &Opt);                   if (status != 0)                          {perror("tcsetattr fd1");                             return; }              tcflush(fd,TCIOFLUSH); } } }4、tcflush()函数用于丢弃设备上的一些数据 ,丢弃的数据取决于第二个参数queue_selector原型为:int tcflush(int fd,int queue_selector)TCIFLUSH——丢弃接口上已经接收到但还没读入的所有数据TCOFLUSH——丢弃所有已经写入接口但还没发送的数据TCIOFLUSH——丢弃所有输入输出队列上还没有读取或发送的数据5、校验位和停止位的设置No parity (8N1):options.c_cflag &= ~PARENB;//无校验options.c_cflag &= ~CSTOPB;//1位停止位options.c_cflag &= ~CSIZE;       //无位掩码options.c_cflag |= CS8;            //8数据位Even parity (7E1):options.c_cflag |= PARENB ;//有校验options.c_cflag &= ~PARODD ;//偶校验options.c_cflag &= ~CSTOPB;//一位停止位options.c_cflag &= ~CSIZE;      //无位掩码options.c_cflag |= CS7;              //7数据位Odd parity (7O1):options.c_cflag |= PARENB ;//有校验options.c_cflag |= PARODD;//奇校验options.c_cflag &= ~CSTOPB ; //一位停止位options.c_cflag &= ~CSIZE;   //无位掩码options.c_cflag |= CS7;    //7数据位CSIZE ——bit mask for data bitsCS7——7 data bitsCS8——8 data bitsCSTOPB——2 stop bits (1 otherwise)PARENB——enable parityPARODD——use odd parity instead of even6、读写串口设置好串口之后,读写串口就很容易了,可以把串口当作文件读写发送数据:char  buffer[1024];int    Length=1024;int    nByte;nByte = write(fd, buffer,Length)使用文件操作read函数读取,如果设置为原始模式(Raw Mode)传输数据,那么read函数返回的字符数是实际串口收到的字符数。char  buff[1024];int    Len=1024;int  readByte = read(fd, buff, Len);二、具体编程具体的程序在code目录下,以下有几个需要特别注意的地方需要说明的。options.c_iflag&= ~ (IXON | IXOFF | IXANY);c_cc数组的VSTART和VSTOP元素被设定成DC1和DC3,代表ASCII标准的XON和XOFF字符,如果在传输这两个字符的时候就传不过去,需要把软件流控制屏蔽,options.c_lflag&= ~ (ICANON | ECHO | ECHOE | ISIG);有时候,在用write发送数据时没有键入回车,信息就发送不出去,这主要是因为我们在输入输出时是按照规范模式接收到回车或换行才发送,而更多情况下我们是不必键入回车或换行的。此时应转换到行方式输入,不经处理直接发送options.c_iflag&= ~ (INLCR | ICRNL | IGNCR);options.c_oflag&= ~(ONLCR | OCRNL);还存在这样的情况:发送字符0X0d的时候,往往接收端得到的字符是0X0a,原因是因为在串口设置中c_iflag和c_oflag中存在从NL-CR和CR-NL的映射,即串口能把回车和换行当成同一个字符,可以进行如下设置屏蔽之:
  • Jmeter系列(38)- 详解性能监控工具 nmon
     nmon 官方介绍nmon是一种在 AIX 与各种 Linux 操作系统上广泛使用的监控与分析工具它能在系统运行过程中实时地捕捉系统资源的使用情况,记录的信息比较全面它可将服务器系统资源耗用情况收集起来并输出一个特定的文件,并可利用 excel 分析工具(nmon analyser)进行数据的统计分析 nmon 可监控的数据类型CPU使用率内存使用情况磁盘适配器文件系统中的可用空间页面空间和页面速度异步I/O,仅适用于AIX网络文件系统(NFS)磁盘 I/O 速度、传输和读/写比率服务器详细信息和资源内核统计信息消耗资源最多的进程运行队列信息 nmon 特点nmon 运行不会占用过多的系统资源,通常情况下CPU利用率不会超过 2%功能强大,监控数据类型全面结合grafana之类的仪表图,可以更直观的实时展示所监控的数据移植性、兼容性较好无人值守监控可以实时查看监控结果,也可以测试结束后本地查看监控结果 nmon 在做性能测试时的劣势不能像 ServerAgent 一样集成到 Jmeter 中查看监控结果 Linux 下安装并运行 nmon检查安装环境# 查看操作系统的信息 uname -a # 查看linux发行版本 lsb_release -a 下载 nmon通过 FTP 上传到服务器目录下 方式二服务器直接敲命令行wget http://sourceforge.net/projects/nmon/files/nmon16e_mpginc.tar.gz这种方式无法下最新版的  解压tar -zxvf nmon16m_helpsystems.tar.gz 查看解压后的文件 运行 nmon我的系统是 x86_64 centos8,敲./nmon_x86_64_centos8
  • Jmeter系列(33)- 跨平台运行 Jmeter,CSV 文件路径如何设置?
    具体方法CSV 数据文件设置直接按下面的格式写这样就可以了,只要把 CSV 文件上传到 Linux 系统 Jmeter 下的 bin 目录,这个脚本就可以跨平台执行了 实现跨平台的原理__P() 函数用来获取 Jmeter 的属性,那我们怎么知道 Jmeter 有什么属性呢? 如何查看 Jmeter 属性测试计划右键添加 Window 下查看属性 user.dir,file.separator可以看到 file.separator 的值是 \ ,这也是 Window 特有的路径分隔符 user.dir 的值是 Jmeter 安装路径下的 bin 目录 如果通过 cmd 运行 Jmeter,那么  user.dir 又会显示什么呢?看到并不是显示 Jmeter 的 bin 目录,这不是我们想要的结果;所以请记住需要在 bin 目录下启动 Jmeter Linux 下查看属性 user.dir,file.separator可以看到 file.separator  的值是 / ,这也是 Linux 的路径分隔符 user.dir  的值是 Jmeter 安装路径下的 bin 目录,和 Window 的截然不同 __EOF__
  • [技术干货] 【PyTorch】多GPU并行训练DistributeDataParallel(Linux版)
    前言常见的多GPU并行的方法有model parallel 和 data parallel两种,这里主要讲的是data parallel:并行训练数据,相当于增大了batch_size.主要需要注意的几点:    数据集如何在不同的设备间分配    误差梯度如何在不同的设备间通信    BatchNormalization如何在不同的设备间同步(使用会提升一点,但是会降低一点并行速度)一、DataParalled和DistributeDataParallel    DataParalled只能用于单机多卡,而DistributeDataParallel可以用于单机多卡,多机多卡    单机情况下通常DataParalled要慢于DistributeDataParallel二、多GPU训练常见启动方式    torch.distributed.launch: 代码少,启动速度快(用的多)    注意: 如果开始训练后,手动强制终止程序,有小概率会出现进程没有杀掉的情况,最好看下GPU占用情况。# 其中nproc_per_node为并行GPU的数量python -m torch.distributed.launch --nproc_per_node=2 --use_env train_multi_gpu_using_launch.py    torch.multiprocessing: 代码多点,速度慢点,但是拥有更好的控制和灵活性(这里不讲)三、torch.distributed.launch代码讲解3.1、main中添加了几个新的变量注意: 这里一般只需要手动选择syncBN即可,后面三个参数不要动,系统会自动选择    # 是否启用SyncBatchNorm BN在多个GPU上同步    parser.add_argument('--syncBN', type=bool, default=True, help="同步BatchNormalization")    # 不要改该参数,系统会自动分配    parser.add_argument('--device', default='cuda', help='device id (i.e. 0 or 0,1 or cpu)')    # 开启的进程数(注意不是线程),不用设置该参数,会根据nproc_per_node自动设置    parser.add_argument('--world-size', default=4, type=int,                        help='number of distributed processes')    parser.add_argument('--dist-url', default='env://', help='url used to set up distributed training')3.2、初始化各进程环境# 初始化各进程环境init_distributed_mode(args=args) def init_distributed_mode(args):    # 使用python -m torch.distributed.launch --nproc_per_node=2 --use_env train_multi_gpu_using_launch.py指令    # --use_env这个参数,他就会在我们os环境中(os.environ)存入RANK、WORLD_SIZE、LOCAL_RANK    if 'RANK' in os.environ and 'WORLD_SIZE' in os.environ:        # 多机多卡:WORLD_SIZE代表使用几台机器,RANK代表第几台机器,LOCAL_RANK代表某台机器上第几块GPU设备        # 单机多卡:WORLD_SIZE代表有几块GPU,RANK=LOCAL_RANK代表哪块GPU        args.rank = int(os.environ["RANK"])        args.world_size = int(os.environ['WORLD_SIZE'])        args.gpu = int(os.environ['LOCAL_RANK'])    elif 'SLURM_PROCID' in os.environ:  # 一般不执行        args.rank = int(os.environ['SLURM_PROCID'])        args.gpu = args.rank % torch.cuda.device_count()    else:  # 一般不执行        print('Not using distributed mode')        args.distributed = False        return    args.distributed = True    torch.cuda.set_device(args.gpu)    args.dist_backend = 'nccl'  # 通信后端,nvidia GPU推荐使用NCCL    print('| distributed init (rank {}): {}'.format(        args.rank, args.dist_url), flush=True)    # 创建进程组(重要)    # backend:通信后端  init_method:使用默认(env://) world_size:几块GPU  rank:当前进程处于哪块GPU    # 注意:对于不同的进程而言,它的world_size是相同的,但是rank是不相同的    dist.init_process_group(backend=args.dist_backend, init_method=args.dist_url,                            world_size=args.world_size, rank=args.rank)    dist.barrier()  # 等待每一块GPU都运行到这个地方之后再接着往下走  3.3、调整学习率学习率要根据并行GPU的数量进行倍增,这里方法不一定,有很多种这里暴力增加,直接乘以GPU个数# 学习率要根据并行GPU的数量进行倍增  world_size = GPU数量args.lr *= args.world_size # 也可以写成这样args.lr *= max(1., args.world_size * args.batch_size / 64)3.4、在第一个进程中进行打印和保存等操作 if rank == 0:  # 在第一个进程中打印信息,并实例化tensorboard        print(args)        print('Start Tensorboard with "tensorboard --logdir=runs", view at http://localhost:6006/')        tb_writer = SummaryWriter()        if os.path.exists("./weights") is False:            os.makedirs("./weights")     3.5、DistributedSamplerDistributedSampler: 给每个rank(gpu)对应的进程分配训练的样本索引 train_sampler = torch.utils.data.distributed.DistributedSampler(train_data_set) val_sampler = torch.utils.data.distributed.DistributedSampler(val_data_set) 
  • [技术干货] Linux台式机搭建FTP服务器
    首先换源:    sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak         sudo gedit /etc/apt/sources.list    deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse    deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse    deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse    deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse    deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse    deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse    deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse    deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse    deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse    deb-src http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse         deb http://cn.archive.ubuntu.com/ubuntu bionic main multiverse restricted universe    deb http://cn.archive.ubuntu.com/ubuntu bionic-updates main multiverse restricted universe    deb http://cn.archive.ubuntu.com/ubuntu bionic-security main multiverse restricted universe    deb http://cn.archive.ubuntu.com/ubuntu bionic main multiverse restricted universe更新源sudo apt-get update安装vsftpdsudo apt-get install vsftpd修改文件sudo gedit /etc/vsftpd.conf修改内容为,直接复制,覆盖原有代码    # 禁止匿名用户登录    anonymous_enable=NO    # 允许系统用户登录    local_enable=YES    # 启用可以修改文件的 FTP 命令    write_enable=YES    # 本地用户创建文件的 umask 值    local_umask=022    # 允许为目录配置显示信息,显示每个目录下面的message_file文件的内容    dirmessage_enable=YES    # 开启日记功能     xferlog_enable=YES    # 使用标准的20端口来连接ftp     connect_from_port_20=YES    # 使用标准日志格式     xferlog_std_format=YES    # 如果启动这项功能,则所有列在chroot_list_file之中的使用者不能更改根目录    chroot_list_enable=YES    # 指定限制的用户文件    chroot_list_file=/etc/vsftpd/chroot_list    # ftp服务器将处于独立启动模式    listen=YES    # 设置一个本地用户登录后进入到的目录    local_root=/home/ftp    # 设置PAM认证服务的配置文件名称,该文件保存在“/etc/pam.d/”目录下    pam_service_name=vsftpd    # ftp将检查userlist_file设置文件中指定的用户是否可以访问vsftpd服务器    userlist_enable=YES    # 只允许user_list文件中记录的ftp用户能登录vsftp服务,其他的ftp用户都不可以登录。    userlist_deny=NO    # 定义限制/允许用户登录的文件    userlist_file=/etc/vsftpd/allowed_users      # ftp服务器将使用tcp_wrappers作为主机访问控制模式    tcp_wrappers=YES    # 连接ftp服务费使用的端口    listen_port=21创建文件夹和文件    sudo mkdir /etc/vsftpd         cd /etc/vsftpd         sudo touch chroot_list         sudo touch allowed_users创建FTP根目录,并添加目录权限    sudo mkdir /home/ftp         sudo chmod -R 777 /home/ftp添加用户,密码    sudo useradd -d /home/ftp -s /sbin/nologin chuangxin         sudo passwd chuangxin在/etc/shells文件末尾添加sudo gedit /etc/shells添加到末尾/sbin/nologin添加用户到/etc/vsftpd/allowed_users    sudo gedit /etc/vsftpd/allowed_users         chuangxin重启vsftpd服务service vsftpd restart查看vsftpd服务状态,绿灯表示正常连接service vsftpd status查看本机局域网ipifconfig测试ftp连接ftp 19.168.x.x连接成功返回:230 Login successful
  • [openEuler] SPEC文件介绍
    1     SPEC简介想制作一个RPM软件包就必须写一个软件包描述文件,即SPEC文件。这个文件中包含了软件包的诸多信息,如软件包的名字、版本、类别、说明摘要、创建时要执行什么命令、安装时要执行什么操作、以及软件包所要包含的文件列表等。1.1   RPM 的宏命令宏(Macros)是使用变量和功能来控制rpm和build的自定义的行为,宏指令一般定义在SPEC文件中。语法:%define macro value. 宏指定也可以事先在配置文件中调整,即下面的文件。默认设置为: /usr/lib/rpm/macros or /etc/rpm/macros用户设置: ~/.rpmmacros在打包的过程中,spec files 和build 能使用RPM 的宏命令中的变量,在SPEC文件中建议尽量使用宏定义。1.2   SPEC文件内容组成SPEC文件主要有以下几个部分组成:文件头预处理阶段:%prep编译阶段:%build安装阶段:%install定义文件阶段:%files修改日志:%changelog2     文件內容2.1     文件头一般文件头包含以下几个域:%define name foo %define version 1.2 Name:%{name} Version:%{version} Release:1 Summary:xxxx License:GPLv2+ Url:www.foo.org Source0:www.xxx%{name}-%{version}.tar.gz Patch0:xxx.patch BuildRequires: Requires: %description:参数释义%define name foo宏定义名字%define version 1.2宏定义版本号Name:%{name}软件包的名字,最终RPM软件包是用该名字,版本号、释出号及体系号来命名的Version:%{version}软件版本号。仅当软件包比以前有较大的改变时才增加版本号Release:1软件包释出号。一般我们对该软件包做了一些小的补丁的时候就应该把release+1Summary:xxxx用一句话描述该软件包尽量多的信息License:GPLv2+软件包所采用的版权规则Url:www.foo.org软件的主页Source0:www.xxx%{name}-%{version}.tar.gz软件包源码对应地址Patch0:xxx.patchpatch,多个patch往下递增BuildRequires软件包编译依赖,可指明≥版本号Requires安装依赖%description软件包详细说明,可写在多个行上 2.2     %prep%prep这部分是预处理阶段,通常用来执行一些解开源程序包的命令,为下一步的编译安装做准备,可以执行shell命令。2.2.1     %autosetup            解压源代码,将当前目录改为源代码解压之后产生的目录,一般为.../rpmbuild/BUILD下的子目录,并且会自动应用补丁。这个宏还有一些选项可以用。%prep %autosetup -n %{name}-xxx -q参数释义-q-q 指不显示输出-n %{name}-xxx解压源码后切换到该目录,用于tar打包的目录与文件目录不一样的情况 2.3     %build%build是编译和准备软件,运行shell命令,执行源代码的configure。%build %configure --enable-shared make2.4     %install%install是用来做rpm安装所有需要的文件。%install make install2.5     %files%files用于定义软件包所包含的文件,分为三类:说明文档(doc),配置文件(config)及执行程序,还可以定义文件读取权限,拥有者以及所属组,路径需使用宏变量。%files %doc README.md %attr(0755,root,root) %config %{_sysconfdir}/foo.conf #指定配置文件, %{_bindir}/foo2.6     %changelog本段是修改日志段,可以将软件的每次修改记录到这里。格式为“*星期 月 日 年 修改人电子信箱 - 版本号-release号”,接下来是换行- 修改信息。%changelog * Tue Mar 16 2021 user <user@xxx.com> - 1.2-3 - example
  • [openEuler] RPM软件包简介
    1      RPM软件包简介软件包引入即引入RPM软件包,RPM软件包是Linux下的一种软件的可执行程序,是类似于Windows上的exe文件。特点如下:安装的软件需要先编译成功,之后将软件打包成为按RPM机制生成的软件包。RPM软件包中会记录并检查软件安装所需要的依赖包,若系统中已安装所需依赖,则成功安装,否则会安装失败。(若需要提前安装所需依赖,可通过rpm –ivh或者dnf install等方式将所依赖的RPM包安装至系统中。两种命令的使用方法在后续有展开说明。)安装RPM软件包时会就将该软件的信息全部写入 RPM 所属的数据库中,以便后续的查询、升级和卸载。这种软件安装包通常是一个后缀为“.rpm”的文件,通过它能够更加轻松容易地实现Linux环境上软件的安装。RPM软件包主要用的有二进制包(binary)和源代码包(source),二进制包可以直接安装在计算机中,而源代码包(SRPM)中包含未编译的源码以及SPEC文件、Patch补丁文件、配置文件等,可在具体的安装环境下编译成RPM包再进行安装。源代码包以“src.rpm”作为后缀名。文件格式文件名安装后能否直接使用内含程序类型能否修改内置参数并编译RPMxxx.rpm是已编译的二进制安装包否SRPMxxx.src.rpm否未编译的源码以及spec文件、patch、配置文件等是 1.1     RPM的命名规则RPM包名结构一般为name-version-release.architecture.rpm,依次为软件名、版本号、编译次数、硬件平台以及扩展名。例如:pkgship-2.1.0-8.oe1.noarch.rpm 为二进制包,pkgship-2.1.0-8.oe1.src.rpm为源码包。1.2     软件包的依赖RPM软件包的依赖主要分为编译依赖和安装依赖,编译依赖是指源码RPM包编译生成二进制RPM包的时候所需要依赖的其他RPM二进制包;而安装依赖则是指在安装二进制RPM包的过程中,需要依赖到的其他的RPM二进制包。编译、安装依赖的指定,主要是在SPEC文件中呈现,SPEC文件的介绍和编写规范,会在后续的文档中呈现。2      RPM包的使用2.1     RPM软件管理器的使用RPM软件包管理器主要是通过使用rpm命令来实现,该工具需要root权限:安装软件执行rpm -ivh rpm包名rpm -ivh apache-1.3.6.i386.rpm-i: install-v: 显示指令的执行过程-h: 显示安装进度  2. 升级软件执行rpm –Uvh rpm包名rpm -Uvh apache-1.3.6.i386.rpm-Uvh:无论软件有没有安装过旧版本,都会安装到更新版本。-Fvh:若已经安装过旧版软件才会更新到新版本,否则不安装新版本软件     3.  卸载软件执行rpm -e rpm包名rpm –e apache-1.3.6包名可以包含版本号等信息,但是不可以有后缀.rpm     4.  回退软件执行rpm -Uvh xxx.rpm –oldpackagerpm –Uvh apache-1.3.6 –oldpackage指定旧版本的RPM包,作版本回退  5. 查询软件包的信息查询本机上的软件包相关信息,不必要加上完整的版本名称,只需要加软件名即可。命令格式:[rpm -qa 软件名]查询某个具体的RPM文件,则需要加完整的文件名称。命令格式:[rpm -qf 文件名]查询已安装软件的信息:-q :仅查询,后面接的软件名称是否有安装。-qa :列出所有的,已经安装在本机 Linux 系统上面的所有软件名,用grep +软件名筛选所需软件是否安装。-qi :列出该软件的详绅信息 (information),包括开发商、版本和说明。-ql :列出该软件所有的文件和目录所在完整文件名 (list)。-qc :列出该软件的所有配置文件 (找出在 /etc/ 底下的文件名而已)。-qd :列出该软件的所有说明文件 (找出不 man 有关的文件而已)。-qR :列出与该软件有关的相依软件所含的文件 (Required 的意思)。-qf :由后面接的文件名,找出该文件属于哪一个已安装的软件。查询某个 RPM 文件内含有的信息:-qp[icdlR]:注意 -qp 后面接的所有参数以上面的说明一致。但用途仅在于找出某个 RPM 档案内的信息,而非已安装的软件信息。2.2     DNF软件管理器的使用DNF工具同样也是运行在Linux系统上的RPM包管理工具,优于RPM软件包管理器的是,yum基于 RPM包管理上,能够从指定的服务器自动下载 RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。DNF通过软件仓库(repository)进行软件的下载、安装等,软件仓库可以是一个 HTTP 或 FTP 站点,也可以是一个本软件池,资源仓库也可以是多个,在 /etc/yum.conf 文件中进行相关配置即可。在DNF的资源库中,会包括 RPM的头信息(header),头信息中包括了软件的功能描述、依赖关系等。通过分析这些信息,DNF计算出依赖关系并进行相关的升级、安装、删除等操作。openEuler提供了多种repo源供用户在线使用,使用root权限添加openEuler repo源,用户可直接基于这些repo源直接使用dnf下载所需要的RPM软件包。  1. 安装RPM包dnf install [-y] [rpm包名]  2. 卸载同时把依赖包卸载dnf remove [-y][rpm包名]  3. 更新dnf update [-y][包名] 不加包名整个系统都会更新  4. 查询dnf provides "/*/vim" 使用这种通配的格式查找到底vim是使用哪个包如果需要额外挂载repo源,可以按照如下方法添加repo源:    1. 打开repo源文件。vim /etc/yum.repos.d/openEuler.repo    2. 添加所需要的repo镜像源。在文件中添加以下内容:[repository] name=repository_name baseurl=repository_url参数说明name=repository_name软件仓库(repository )描述的字符串。baseurl=repository_url软件仓库(repository )的地址。·         使用http协议的网络位置:例如 http://path/to/repo·         使用ftp协议的网络位置:例如 ftp://path/to/repo·         本地位置:例如 file:///path/to/local/repo DNF详细使用方法请参考openEuler文档。3      rpmbuild的使用当获取到上游社区的源码tar包和编写好的SPEC文件后,需要使用rpmbuild命令打包RPM软件。安装该软件包。dnf install rpm-build      2. 建立工作目录。rpmdev-setuptree执行之后,会在用户家目录下生成一下几个目录。/root/rpmbuild/目录结构如下:BUILD          #源码包解压至此并完成编译RPMS           #生成/保存二进制 RPM 包SOURCES       #保存源码包(如 .tar 包)和所有 patch 补丁SPECS          #保存rpm包配置文件(.spec)SRPMS         #生成/保存源码 RPM 包(SRPM)BUILDROOT    #保存 %install 阶段安装的文件将源码包(和补丁文件,如果有的话)放在SOURCES目录下,spec文件放在SPECS目录下后即可开始尝试rpm打包。      3. 执行编译生成RPM包。                 执行编译前需要将spec文件放到/root/rpmbuild/SPECS/ 目录下,将软件的源码(tar.gz等形式的压缩包以及patch等)放在/root/rpmbuild/SOURCES/目录下。rpmbuild -ba **.spec如果编译时报错说缺少依赖,需要提前安装编译依赖dnf builddep **.spec#若dnf安装显示没有此包,说明该包暂未引入进openEuler发行版本中,请到https://gitee.com/organizations/src-openeuler/projects 中确认是否有引入该包,若没有,则需要先引入该包。      4. 验证RPM包。                     经过编译之后,并且顺利编译成功之后,打包完成的文件放在/root/rpmbuild/RPMS/目录中,包含了 x86_64,noarch... 等的次要目录。编译完成后到RPMS目录下去拿到编译生成的RPM包进行验证。若是编译报错,可以根据报错日志或者分步编译去进行调试。在调试过程中可以不用执行全部的编译步骤,可以针对日志中报错的部分(比如%prep或者%check),使用rpmbuild命令只去执行到报错阶段,各阶段意义可以在spec文件介绍.doc中查看。rpmbuild -ba 可以分别拆解成如下几个阶段去分步编译:bp   %prep 阶段bc   %build 阶段bi    %install阶段bb   %file阶段一般先rpmbuild -bp ,再-bc 再-bi 如果没问题,rpmbuild -bb制作rpm包。
  • [技术干货] linux的异步事件处理
    在socket网络编程中,如果当前已经有连接了,那么另外一个请求想连接服务器,只能等待了
  • 当 CPU 摸鱼时,它到底在干什么?
    人空闲时会发呆会无聊,计算机呢?假设你正在用计算机浏览网页,当网页加载完成后你开始阅读,此时你没有移动鼠标,没有敲击键盘,也没有网络通信,那么你的计算机此时在干嘛?有的同学可能会觉得这个问题很简单,但实际上,这个问题涉及从硬件到软件、从 CPU 到操作系统等一系列环节,理解了这个问题你就能明白操作系统是如何工作的了。你的计算机 CPU 使用率是多少?如果此时你正在计算机旁,并且安装有 Windows 或者 Linux ,你可以立刻看到自己的计算机 CPU 使用率是多少。这是博主的一台安装有 Win10 的笔记本:可以看到大部分情况下 CPU 利用率很低,也就在 8% 左右,而且开启了 283 个进程,这么多进程基本上无所事事,都在等待某个特定事件来唤醒自己,就好比你写了一个打印用户输入的程序,如果用户一直不按键盘,那么你的进程就处于这种状态。有的同学可能会想也就你的比较空闲吧,实际上大部分个人计算机 CPU 使用率都差不多这样(排除掉看电影、玩游戏等场景),如果你的使用率总是很高,风扇一直在嗡嗡的转,那么不是软件 bug 就有可能是病毒。。。那么有的同学可能会问,剩下的 CPU 时间都去哪里了?剩下的 CPU 时间去哪里了?这个问题也很简单,还是以 Win10 为例,打开任务管理器,找到 “详细信息” 这一栏,你会发现有一个 “系统空闲进程”,其 CPU 使用率达到了 99%,正是这个进程消耗了几乎所有的 CPU 时间。那么为什么存在这样一个进程呢?以及这个进程什么时候开始运行呢?这就要从操作系统说起了。程序、进程与操作系统当你用最喜欢的代码编辑器编写代码时,这时的代码不过就是磁盘上的普通文件,此时的程序和操作系统没有半毛钱关系,操作系统也不认知这种文本文件。程序员写完代码后开始编译,这时编译器将普通的文本文件翻译成二进制可执行文件,此时的程序依然是保存在磁盘上的文件,和普通没有本质区别。但此时不一样的是,该文件是可执行文件,也就是说操作系统开始 “懂得” 这种文件,所谓 “懂得” 是指操作系统可以识别、解析、加载,因此必定有某种类似协议的规范,这样编译器按照这种协议生成可执行文件,操作系统就能加载了。在 Linux 下可执行文件格式为 ELF ,在 Windows 下是 EXE 。此时虽然操作系统可以识别可执行程序,但如果你不去双击一下(或者在Linux下运行相应命令)的依然和操作系统没有半毛钱关系。但是当你运行可执行程序时魔法就出现了。此时操作系统开始将可执行文件加载到内存,解析出代码段、数据段等,并为这个程序创建运行时需要的堆区栈区等内存区域,此时这个程序在内存中就是这样了:最后,根据可执行文件的内容,操作系统知道该程序应该执行的第一条机器指令是什么,并将其告诉 CPU ,CPU 从该程序的第一条指令开始执行,程序就这样运行起来了。一个在内存中运行起来的程序显然和保存在磁盘上的二进制文件是不一样的,总的有个名字吧,根据“弄不懂原则”,这个名字就叫进程,英文名叫做Process。我们把一个运行起来的程序叫做进程,这就是进程的由来。此时操作系统开始掌管进程,现在进程已经有了,那么操作系统是怎么管理进程的呢?调度器与进程管理银行想必大家都去过,实际上如果你仔细观察的话银行的办事大厅就能体现出操作系统最核心的进程管理与调度。首先大家去银行都要排队,类似的,进程在操作系统中也是通过队列来管理的。同时银行还按照客户的重要程度划分了优先级,大部分都是普通客户;但当你在这家银行存上几个亿时就能升级为 VIP 客户,优先级最高,每次去银行都不用排队,优先办理你的业务。类似的,操作系统也会为进程划分优先级,操作系统会根据进程优先级将其放到相应的队列中供调度器调度。这就是操作系统需要实现的最核心功能。现在准备工作已经就绪。接下来的问题就是操作系统如何确定是否还有进程需要运行。队列判空:一个更好的设计从上一节我们知道,实际上操作系统是用队列来管理进程的,那么很显然,如果队列已经为空,那么说明此时操作系统内部没有进程需要运行,这是 CPU 就空闲下来了,此时,我们需要做点什么,就像这样:if (queue.empty()) {  do_someting();}这些编写内核代码虽然简单,但内核中到处充斥着 if 这种异常处理的语句,这会让代码看起来一团糟,因此更好的设计是没有异常,那么怎样才能没有异常呢?很简单,那就是让队列永远不会空,这样调度器永远能从队列中找到一个可供运行的进程。而这也是为什么链表中通常会有哨兵节点的原因,就是为了避免各种判空,这样既容易出错也会让代码一团糟。就这样,内核设计者创建了一个叫做空闲任务的进程,这个进程就是Windows 下的我们最开始看到的“系统空闲进程”,在 Linux 下就是第 0号进程。当其它进程都处于不可运行状态时,调度器就从队列中取出空闲进程运行,显然,空闲进程永远处于就绪状态,且优先级最低。既然我们已经知道了,当系统无所事事后开始运行空闲进程,那么这个空闲进程到底在干嘛呢?这就需要硬件来帮忙了。一切都要归结到硬件在计算机系统中,一切最终都要靠 CPU 来驱动,CPU 才是那个真正干活的。原来,CPU 设计者早就考虑到系统会存在空闲的可能,因此设计了一条机器指令,这个机器指令就是 halt 指令,停止的意思。这条指令会让部分CPU进入休眠状态,从而极大减少对电力的消耗,通常这条指令也被放到循环中执行,原因也很简单,就是要维持这种休眠状态。值得注意的是,halt 指令是特权指令,也就是说只有在内核态下 CPU 才可以执行这条指令,程序员写的应用都运行在用户态,因此你没有办法在用户态让 CPU 去执行这条指令。此外,不要把进程挂起和 halt 指令混淆,当我们调用 sleep 之类函数时,暂停运行的只是进程,此时如果还有其它进程可以运行那么 CPU 是不会空闲下来的,当 CPU 开始执行halt指令时就意味着系统中所有进程都已经暂停运行。软件硬件结合现在我们有了 halt 机器指令,同时有一个循环来不停的执行 halt 指令,这样空闲任务进程的实际上就已经实现了,其本质上就是这个不断执行 halt 指令的循环,大功告成。这样,当调度器在没有其它进程可供调度时就开始运行空间进程,也就是在循环中不断的执行 halt 指令,此时 CPU 开始进入低功耗状态。在 Linux 内核中,这段代码是这样写的:while (1) {  while(!need_resched()) {      cpuidle_idle_call();  }}其中 cpuidle_idle_call函数最终会执行 halt 指令,注意,这里删掉了很多细节,只保留最核心代码,实际上 Linux 内核在实现空闲进程时还要考虑很多很多,不同类型的 CPU 可能会有深睡眠浅睡眠之类,操作系统必须要预测出系统可能的空闲时长并以此判断要进入哪种休眠等等,但这并不是我们关注的重点。总的来说,这就是计算机系统空闲时 CPU 在干嘛,就是在执行这一段代码,本质上就是 CPU 在执行 halt 指令。实际上,对于个人计算机来说,halt 可能是 CPU 执行最多的一条指令,全世界的 CPU 大部分时间都用在这条指令上了,是不是很奇怪。更奇怪的来了,有的同学可能已经注意到了,上面的循环可以是一个while(1) 死循环,而且这个循环里没有break语句,也没有return,那么操作系统是怎样跳出这个循环的呢?关于这个问题,我们将会在后续文章中讲解。总结CPU 空闲时执行特定的 halt 指令,这看上去是一个很简单的问题,但实际上由于 halt 是特权指令,只有操作系统才可以去执行,因此 CPU 空闲时执行 halt 指令就变成了软件和硬件相结合的问题。操作系统必须判断什么情况下系统是空闲的,这涉及到进程管理和进程调度,同时,halt 指令其实是放到了一个 while 死循环中,操作系统必须有办法能跳出循环,所以,CPU 空闲时执行 halt 指令并没有看上去那么简单。
  • [技术干货] linux系统日志分类
    linux系统日志的分类/var/log/messages这是Linux最核心的日志文件,假若某个服务没有定义日志文件,那么该服务产生的日志文件就会记录到这个文件中。该日志每周归档一次,默认只保留5次。归档的方法都是由"etc/logrotate.conf"这个文件来控制的。/var/log/wtmp查看用户的登录,注销信息,同时记录系统的启动,重启,关机等事件。不用能cat直接查看,必须用last查看/var/log/btmp和wtmp类似,也不能用cat直接查看,用lastb查看,记录用户登录无效的历史/var/log/maillog用来记录邮件相关的日志,比如发给哪个,是否发出去/var/log/cron记录了系统定时任务相关的日志/var/log/cpus/记录了cpu信息的日志/var/log/lastlog记录所有用户的最后一次登录时间,只可能通过lastlog命令查看/var/og/sudo.log记录使用sudo发出的命令,需要先配置/etc/sudoers的logfile=/var/log/sudo.log
  • 云享读书会活动分享《Linux系统管理》,5天搞定Linux系统管理,快来报名吧,学知识赢奖品
    云享读书会第十期《Linux系统管理》,5天搞定Linux系统管理,快来报名吧本期读书会亮点内容详尽 通俗易懂书籍原作者现身视频领读丰厚结业奖励招募期(即日起~5月9日)报名本期读书会 加入学习社群等待开启领读领读期(5月10日~5月14日)跟随领读专家阅读书籍 完成自测题 输出读书笔记结业期(5月15日~5月21日)与领读专家在线互动 交流答疑专属链接分享:https://developer.huaweicloud.com/signup/15096a0b940a44238084e7e116051cb2?invitation=df7ac2c758cf457a9a9ba4060fd58baf奖品详见活动页说明,本贴只是活动分享贴。
总条数:1204 到第 页
上滑加载中