守护进程(daemon)也叫精灵进程,它是运行在后台的与终端无关的一种特殊进程
#include <unistd.h>
pid_t setsid(void);
setsid()函数调用时,要保证当前进程不是进程组组长,否则出错返回-1
可以调用fork()做到这一点,fork出来的子进程和当前进程属于同一个进程组,而一个进程组组长是该进程组的第一个进程,所以保证fork出来的子进程一定不是进程组组长,接着调用setsid()函数
setsid()函数调用成功后,当前进程独自成一个会话(sid为当前进程id),且为进程组组长(gid也为进程id),如果当前进程有控制终端,则它会失去这个终端
#include#include #include #include #include #include #include void create_daemon(){ pid_t id=-1; struct sigaction sa; sa.sa_handler=SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags=0; if(sigaction(SIGCHLD,&sa,NULL)<0){//注册子进程退出忽略信号 return; } if((id=fork())<0){//保证当前进程不是组长进程,否则下面setdid会失败 perror("fork"); exit(-1); } else if(id!=0){//父进程退出 exit(0); } umask(0); if(-1==setsid()){//当前进程成为了守护进程,和终端无关 perror("setsid"); exit(1); } if(-1==(id=fork())){//保证进程不会再次打开终端 perror("fork"); } else if(0!=id){//父进程退出 exit(0); } if(-1==chdir("/")){//把当前守护进程的工作目录改为根目录 perror("chdir"); exit(-1); } close(0);//关闭不必要的文件描述符 int fd=-1; fd=open("/dev/null",O_RDWR); dup2(fd,1); dup2(fd,2);}int main(){ create_daemon(); while(1){ ; } return 0;}
运行结果:
运行程序后用ps ajx | grep -E 'my_daemon'命令后有两个进程,其中第一行就是我们创建的守护进程
它的父进程为1号init进程,因为它的父进程退出后它成为了孤儿进程,被init进程收养
PGID和SID都为2816,而它的PID为2817,可看出它不是该会话的会话首进程,也不是它所属进程组的组长进程
TTY列是?说明该进程和终端无关
ps ajx | head -n1 命令可查看头部信息