首先,阐述一下有关概念:
a)Shell 上的一条命令形成一个进程组
进程组的生命周期到组中最后一个进程终止, 或加入其他进程组为止。
b)会话
一次登录形成一个会话。
一个会话可包含多个进程组,但只能有一个前台进程组。
setsid()可建立一个新的会话。
pid_t setsid(void)
但是,调用进程的不是进程组的领头进程,该函数才能建立起新的会话。调用 setsid()后,进程成
为新会话的领头进程。也成为新进程组的领头进程。同时,进程失去控制终端。
c)控制终端
会话的领头进程打开一个终端之后, 该终端就成为该会话的控制终端 (SVR4/Linux)
与控制终端建立连接的会话领头进程称为控制进程 (session leader)
一个会话只能有一个控制终端
产生在控制终端上的输入和信号将发送给会话的前台进程组中的所有进程
终端上的连接断开时 (比如网络断开或 Modem 断开), 挂起信号将发送到控制进程 (session
leader)
一. 守护进程及其特性
守护进程最重要的特性是后台运行。在这一点上 DOS 下的常驻内存程序 TSR 与之相似。其次,守
护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进
程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是 shell)
中继承下来的。最后,守护进程的启动方式有其特殊之处。它可以在 Linux 系统启动时从启动脚
本/etc/rc.d 中启动,可以由作业规划进程 crond 启动,还可以由用户终端(通常是 shell)执行。
总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际
上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。
二. 守护进程的编程要点
前面讲过,不同 Unix 环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一
样,区别在于具体的实现细节不同。这个原则就是要满足守护进程的特性。同时, Linux 是基于
Syetem V 的 SVR4 并遵循 Posix 标准,实现起来与 BSD4 相比更方便。编程要点如下;
1. 在后台运行。
为避免挂起控制终端将 Daemon 放入后台执行。方法是在进程中调用 fork 使父进程终止,让
Daemon 在子进程中后台执行。
if(pid=fork())
exit(0);//是父进程,结束父进程,子进程继续
2. 脱离控制终端,登录会话和进程组
有必要先介绍一下 Linux 中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程
组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组
共享一个控制终端。这个控制终端通常是创建进程的登录终端。