一个服务器的开始
后台运行
如何开启一个后台运行程序
参数处理
头文件 #include<unistd.h>
函数说明getopt( )用来分析[命令行参数]
getopt就是linux中常用的后面带个-a -b -c这种
char *optstring = “ab:c::”;
单个字符a 表示选项a没有参数 格式:-a即可,不加参数
单字符加冒号b: 表示选项b有且必须加参数 格式:-b 100或-b100,但-b=100错
单字符加2冒号c:: 表示选项c可以有,也可以无 格式:-c200,其它格式错误
optarg —— 指向当前选项参数(如果有)的指针。
optind —— 再次调用 getopt() 时的下一个 argv指针的索引。
optopt —— 最后一个未知选项。
opterr —— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。
信号处理
signal函数
signal(SIGCHLD, SIG_DFL); //SIG_DFL默认 signal(SIGPIPE, SIG_IGN); //SIG_IGN忽略信号
后台运行子进程
当后台运行子进程时
signal(SIGCHILD, SIG_IGN); //子进程结束时会给父进程发一个信号。我们把这个信号忽略掉,让内核去回收子进程
我们把子进程忽略掉,让系统来回收子进程。
#include<sys/types.h>
#include<fcntl.h>
fork() 产生进程
int pid = fork(); //fork()=0 表示子进程 //fork() > 0 返回的是子进程的id //fork() < 0 表示错误,比如内存不足
exit()表示结束进程
setsid()表示使进程成为会话组长
int dup(int oldfd) 复制文件描述符
int dup2(int oldfd, int newfd) 重定向文件描述符
int daemon() { signal(SIGCHLD, SIG_IGN); int pid = fork(); if(pid < 0) { cout << "fork call error, code is" << pid << "error code is" << errno << std::endl; exit(-1); } if(pid > 0) //主进程在此结束 { exit(0); } //下面是子进程的代码 //这里可以避免父进程所在的会话结束时,把子进程带走 //不让前台影响后台,setsid是设置进程为会话组组长 setsid(); //不让后台影响前台 int fd = open("/dev/null", O_RDWR, 0); cout << "fd is" << fd << std::endl int (fd != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); //就是把输入输出全部都定向到dev下的null,就是直接吃掉,避免终端上输入输出影响前台程序 } if(fd > STDERR_FILENO) close(fd); }