创建子进程,父进程退出。 (脱离控制终端),很自然地,子进程成了孤儿进程,被init进程收养。
子进程中创建新会话。
我们先介绍下进程组的概念:
进程组是一个或者多个进程的集合,由进程组id来唯一标识,除了进程号PID之外,进程组ID也是一个进程的必备属性。
每个进程组都有一个组长进程,其组长进程的进程号PID等于进程组ID,且该进程ID不会因为组长进程的退出而受到影响。会话期
会话组是一个或者多个进程组的集合,通常,一个会话开始于用户登录,终止于用户退出,在此期间用户运行的所有进程 都属于这个会话期。
Setid函数就是用于创建一个新的会话,并担任该会话组的组长,有三个作用,让进程摆脱原会话和进程组,终端的控制,使进程完全独立出来。
- 由于fork()继承了父进程的工作目录,对以后的使用造成不便,所以我们要改变当前目录为根目录。
关闭文件描述符。 (fork()继承过来的)
重设文件权限掩码。因为由继承得来的文件模式屏蔽字可能会被设置为拒绝某些权限
void daemonize() { pid_t pid; pid = fork(); /* In case of fork is error. */ if (pid < 0) { fprintf(stderr,"fork error.\n"); exit(0); } /* In case of this is parent process. */ if (pid != 0) exit (0);// 父进程退出 /* Become session leader and get pid. */ pid = setsid(); if (pid == -1) { fprintf(stderr, "setsid failed.."); exit(0); } /* Change directory to root. */ chdir ("/"); /* File descriptor close. */ int fd; fd = open ("/dev/null", O_RDWR, 0); if(fd != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO);//all the output to stdin&stdout&stderr will go into /dev/null now if(fd > 2) close(fd); } umask (0); }