什么是会话?我们知道一个进程有组id,当多个进程的组id相同时,我们称这些进程隶属于同一个进程组,而会话则是由进程组组成的,会话也有会话id,我们通过ps ajx可以看到一栏名为sid,这个sid就是会话id。
我们可以通过setsid函数来将一个进程脱离原有的会话,建立新的会话。但是,要想该函数调用成功,需要注意以下2点:
1. 调用进程不能是进程组的组长,否则会出错
2. 需要root权限,但ubuntu不需要
当我们调用成功后,通过ps ajx可以发现调用进程的tty那一栏变成了?,也就是说该进程已经没有和控制终端绑定了。我们知道当我们在终端上执行一个程序的时候,直接退出终端,会结束掉我们的进程,这是因为我们的程序是和控制终端进程绑定的,当控制终端结束时,会终止和它绑定的所有进程,也就是与控制终端同一会话的都会被终止。那么,该进程脱离了控制终端,则终端结束,该进程也不会结束。
什么是守护进程?守护进程就相当于windows中的服务程序,周期性的执行某种任务或等待处理某些发生的事件。守护进程是独立的,脱离了控制终端的,而且都是长时间运行在后台的。
那么如何创建一个守护进程的,有以下几个基本步骤:
1.创建子进程,父进程退出。这样我们就能保证该进程不可能是进程组组长。
2.在子进程中创建新的会话。这就把子进程脱离了控制终端
3.改变当前工作目录。主要是为了防止占用可卸载的文件系统
4.重设文件权限掩码。防止继承的文件创建屏蔽字拒绝某些权限,增加守护进程灵活性。
5.关闭文件描述符。因为已经脱离了控制终端,所以哪些标准输入输出已经不会用到。
6.开始执行守护进程的核心工作。
7.守护进程退出处理。
以下是一个守护进程的示例代码,它每个10s会向当前目录下的time.log文件写入当前时间:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <string.h> void daemonize(void) { pid_t pid; if((pid = fork()) < 0) { perror("fork"); exit(1); } else if(pid != 0) { exit(0); } setsid(); if(chdir("/") < 0) { perror("chdir"); exit(1); } umask(0); close(0); open("/dev/null",O_RDWR); dup2(0,1); dup2(0,2); } int main(void) { int fd = open("./time.log",O_RDWR | O_APPEND | O_CREAT,0777); if(fd < 0) { perror("open"); exit(1); } time_t t; char buf[1024]; bzero(buf,sizeof(buf)); daemonize(); while(1) { time(&t); ctime_r(&t,buf); write(fd,buf,strlen(buf)); sleep(10); } return 0; }