1、system popen命令

  1. string tarpath = "tar -zxvf /opt/mt/update/" + compressedFile + " -C /opt/mt/";
  2. LOG("tar:::%s",tarpath.data()); // tar -zxvf /opt/mt/update/ctl.tar.gz -C /opt/mt/
  3. status = system(tarpath.c_str()); //调用tar 解压缩
  4. sleep(2);
  5. LOG("system:%d",status);
  6. if(status < 0) //如果status小于0,表明调用出错
  7. {
  8. perror("system函数调用date出现错误."); //调用出错
  9. exit(0);
  10. }
  11. else{
  12. string cm = "chmod 777 /opt/mt/" + file +"\/*";
  13. string rm = "rm /opt/mt/update/" + Compath;
  14. LOG("chmod::::%s",cm.data());
  15. LOG("rm::::%s",rm.data());
  16. system(cm.c_str()); //777权限
  17. system(rm.c_str());//删除ctl
  18. sleep(2);
  19. FILE *fc = NULL;
  20. fc = popen("reboot","r");//重启
  21. if(!fc)
  22. {
  23. LOG("reboot error");
  24. return -1;
  25. }
  26. pclose(fc);
  27. }

2、shutdown()

优雅地断开TCP连接
howto 在 Linux 下有以下取值:

SHUT_RD:断开输入流。套接字无法接收数据(即使输入缓冲区收到数据也被抹去),无法调用输入相关函数。
SHUT_WR:断开输出流。套接字无法发送数据,但如果输出缓冲区中还有未传输的数据,则将传递到目标主机。
SHUT_RDWR:同时断开 I/O 流。相当于分两次调用 shutdown(),其中一次以 SHUT_RD 为参数,另一次以 SHUT_WR 为参数。

howto 在 Windows 下有以下取值:

SD_RECEIVE:关闭接收操作,也就是断开输入流。
SD_SEND:关闭发送操作,也就是断开输出流。
SD_BOTH:同时关闭接收和发送操作。

  1. void Socket::shutdownWrite()
  2. {
  3. if (::shutdown(sockfd_, SHUT_WR) < 0)
  4. {
  5. perror("Socket::shutdownWrite");
  6. }
  7. }

3、linux 时间函数

计时函数,用于获得当前时间
time(2)/time_t (秒)
ftime(3)/struct timeb (毫秒)
gettimeofday(2)/struct timeval (微秒)
clock_gettime(2)/struct timespec (纳秒)
还有gmtime / localtime / timegm /mktime /strftime /struct tm等与当前时间无关的时间格式转换函数

定时函数,用于让程序等待一段时间或安排计划任务
sleep(3)
alarm(2)
usleep(3)
nanosleep(2)
clock_nanosleep(2)
getitimer(2) / setitimer(2)
timer_create(2) / timer_settime(2) / timer_gettime(2) / timer_delete(2)
timerfd_create(2) /timerfd_gettime(2) / timerfd_settime(2)

muduo取舍
(计时)只使用gettimeofday(2)来获取当前时间
(定时)只使用 timerfd_ * 系列函数来处理定时任务

gettimeofday(2)入选原因(这也是muduo::Timestamp class的主要设计考虑):

  1. time(2) 的精度太低,ftime(3)已被废弃;clock_gettime(2)精度最高,但是系统调用的开销比gettimeofday(2)大
  2. 在x86-64平台上,gettimeofday(2)不是系统调用,而是在用户态实现的,没有上下文切换和陷入内核的开销。
  3. gettimeofday(2)的分辨率(resolution)是1微秒,现在的实现确实能达到这个计数精度,足以满足日常计时的需要。muduo::Timestamp用一个 int64_t来表示产品能够Unix Epoch到现在的微秒数,其范围可达上下30万年

timerfd_*入选的原因:

  1. sleep(3) / alarm(2) / usleep(3) 在实现时有可能用了SIGALRM信号,在多线程程序中处理信号是个相当麻烦的事情,应当尽量避免。再说,如果主程序和程序库都使用SIGALRM,就糟糕了。
  2. nanosleep(2)和clock_nanosleep(2)是线程安全的,但是在非阻塞网络编程中,绝对不能用让线程挂起的方式来等待一段时间,这样一来程序会失去响应。正确的做法是注册一个时间回调函数。
  3. gettitimer(2)和timer_create(2)也是信号来deliver超时,在多线程程序中也会有麻烦。timer_create(2)可以指定信号的接收方是进程还是线程,算是一个进步,不过信号处理函数(signal handler)能做的事实在很受限。
  4. timerfd_create(2)把时间编程了一个文件描述符,该“文件”在定时器超时的那一刻变得可读,这样就能很方便地融入select(2)/poll(2)框架中,用统一的方式来处理IO事件和超时事件,这也是Reactor模式的长处。
  5. 传统的Reactor利用select(2) / poll(2) /epoll(4)的timeout来实现定时功能,但poll(2)和epoll_wait(2)的定时精度只有毫秒,远低于timerfd_settime(2)的定时精度。

必须要说明,在Linux这种非实时多任务操作系统中,在用户态实现完全精确可控的计时和定时是做不到的,因为当前任务可能会被随时切换出去,这在CPU负载大的时候尤为明显。但是,我们的程序可以尽量提高时间精度,必要的时候通过控制CPU负载来提高时间操作的可靠性,让程序在99.99%的时候都按照预期执行的。这或许比换用实时操作系统并重新编写及测试代码要经济一些

4、basename函数

BASENAME(3)
NAME
basename, dirname - parse pathname components
SYNOPSIS
#include
char dirname(char path);
char basename(char path);

字符串截取的时候 path 最好不要是 const,比如 #define
如果是const可以换个函数截取
#define GW_UP_LOG_NAME “/etc/galaxy/oam/datalog/gw_log/gw_up.log”
char file_name = GW_UP_LOG_NAME;
char cFileG[30] = {0},
p = NULL, *ped = NULL;
ped = strrchr(file_name, ‘.’);
p = strrchr(file_name, ‘/‘);
++p;
memcpy(cFileG, p, ped-p); //cFileG是 gw_up

5、source生效

解决linux环境变量每次要source问题

在/etc/profile里配置的环境变量只要退出后都需要再source /etc/profile才会生效。
vi /etc/profile
export NODE_HOME=/usr/local/node-v10.18.0
export NODE_PATH=$NODE_HOME/lib/node_modules
export PATH=$PATH:$NODE_HOME/bin

解决办法:
编辑vi ~/.bashrc 再最后面增加
if [ -f /etc/profile ]; then
. /etc/profile
fi