http://hi.baidu.com/kanif?page=5
在linux中,系统与用户交流的界面为终端,每一个从此终端开始运行的进程都将依附于这个终端,当终端关闭时,相应的进程都会自动关闭。但在实际使用中,经常需要让进程脱离终端并在后台运行。让进程脱离终端有多种方法,例如nohup、screen、crontable等。那么如何让进城在运行时自动脱离终端转化为守护进程呢?
一 创建子进程
编写守护进程的首先需创建子进程,然后终止父进程,留下子进程运行。这样从终端来看,程序已经运行完毕。
switch (fork()){
case -1:
return -1;
case 0:
break;
default:
_exit(EXIT_SUCCESS);
}
二 创建新会话
使用fork函数创建的子进程拷贝了父进程的全部信息,包括会话期、进程组合控制终端等,使用setsid函数 让子进程彻底独立出来,成为新的会话的会话头进程和新的进程组的进程组头进程。
if(setsid() == -1)
return -1;
三 更改工作目录
更改工作目录有两个原因:1.守护进程可能在某个文件系统中启动,如果不更改的,就无法对其卸载。2. 需要将守护进程的某些文件保存到当前工作目录。一般来说需将子进程工作目录改到根目录,也可根据需要换成其他目录。
chdir("/");
四 重定向标准输入、输出和错误输出
由于守护进程已经脱离终端,那么守护进程无法从终端读取字符或将字符输出到终端,因此需要将其关闭。
if ( (fd = open("/dev/null", O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > STDERR_FILENO)
(void)close(fd);
五 保留进程信息
对于守护进程来说,如果要将其关闭一般是使用kill命令将其杀死,所以我们需要将进程号写入到文件中,方便服务的重启。
pid_t pid = getpid();
FILE *fp= fopen(pid_file, "w")
fprintf(fp, "%ld\n", (long)pid);
fclose(fp)
六 结束语
到目前为止,我们已经可以使用libevent和线程池来打造自己的linux守护进程。当然在实际使用中情况远比这个复杂,我们还需要处理各种异常、信号、日志等。