下面我们用ps axj
命令查看系统中的进程。参数a
表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x
表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j
表示列出与作业控制相关的信息。
凡是TPGID
一栏写着-1的都是没有控制终端的进程,也就是守护进程。在COMMAND
一列用[]
括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行,通常采用以k
开头的名字,表示Kernel。init
进程我们已经很熟悉了,负责维护/dev
目录下的设备文件,acpid
负责电源管理,syslogd
负责维护/var/log
下的日志文件,可以看出,守护进程通常采用以d
结尾的名字,表示Daemon。
创建守护进程最关键的一步是调用setsid
函数创建一个新的Session,并成为Session Leader。
成功调用该函数的结果是:
例 34.2. 创建守护进程
为了确保调用setsid
的进程不是进程组的Leader,首先fork
出一个子进程,父进程退出,然后子进程调用setsid
创建新的Session,成为守护进程。按照守护进程的惯例,通常将当前工作目录切换到根目录,将文件描述符0、1、2重定向到/dev/null
。Linux也提供了一个库函数daemon(3)
实现我们的daemonize
函数的功能,它带两个参数指示要不要切换工作目录到根目录,以及要不要把文件描述符0、1、2重定向到/dev/null
。
运行这个程序,它变成一个守护进程,不再和当前终端关联。用ps
命令看不到,必须运行带x
参数的命令才能看到。另外还可以看到,用户关闭终端窗口或注销也不会影响守护进程的运行。