守护进程(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 命令可查看头部信息