编写步骤
调用
fork(),父进程退出,保留子进程使进程在形式上脱离控制终端,shell 终端里可以执行其他命令了。
调用
setsid()创建新session上一步中子进程虽然已经在后台运行而不会随着终端的退出而退出,但其 session
仍然是 shell 所在的 session,process group ID 也没有变,这样 daemon 会受
到原 process group 的影响,比如向原 group 发送信号。setsid()会新建一个
会话,并设置 process group ID。调用者会成为新的 session 和 process group
的 leader。第一步调用
fork()的另一个原因是 process group leader 不能调用setsid()这个函数。新建一个子进程并退出父进程可保证子进程不是group
leader。再次调用
fork(),保留子进程因为
setsid()使进程成为了新的的 session leader,这使得它可以重新打开一个
控制终端,此次fork()的作用是使子进程不再是 session leader,所以不会因无
意或故意地打开终端设备而获得控制终端。调用
chdir()改变工作目录改变工作目录以防止一直占用某个目录而导致不能卸载文件系统。
调用
umask(0)重新设置掩码因为子进程继承了父进程的文件权限掩码,会给子进程使用文件带来麻烦,将其设
置为0可以减少不必要的麻烦。调用
close()关闭文件描述符子进程继承了父进程的文件描述符,通常并不需要,因此将其关闭。可使用
getdtablesize()获得文件描述符表的大小。调用
signal()处理SIGCHLD信号防止守护进程的子进程成为僵尸进程,可以将
SIGCHLD的信号处理函数设置为SIG_IGN。
一个简单例子
1  | 
  | 
References
LINUX下守护进程的C语言实现
UNIX环境高级编程(APUE)之单实例守护进程
How a session leader can take the control of tty in Linux?
How can I recover the controlling tty after a setsid
reptyr: Changing a process’s controlling terminal