守护进程的特征
什么是守护进程?
守护进程通常在系统引导时启动,系统关闭时终止。它们不控制终端,在后台运行。
在我的Linux系统中输入:ps -axj,输出了以下参数:
其中,PPID—父进程ID、PID—进程ID、PGID—进程组ID、SID—会话ID、UID—用户ID、TTY—终端名称、COMMAND—命令字符串。
父进程ID为0的进程是内核进程,内核进程存在于系统的整个生命期中,以超级用户特权运行,无命令行。
内核守护进程名字用[]中,Linux通过名为kthreadd的内核进程来创建其他内核进程,因此该进程是其他内核进程的父进程。在这些进程中,如:
- kswapd:称为内存换页守护进程,支持虚拟子系统将脏页面写回磁盘来回收页面。
- flush:称为冲洗守护进程。在可用内存达到设置的最小阈值时,将脏页面冲洗到磁盘中。他也会定期清洗脏页面,从而减少系统故障时的数据丢失。
- sync_supers:定期将文件系统元数据冲洗至磁盘。
大多数守护进程都以超级用户root特权运行(即UID是0),所有守护进程没有控制终端,TTY都是?。内核守护进程以无控制终端方式启动,用户层守护进程不控制终端可能是调用了setsid的结果。用户层守护进程的父进程都是init进程。
创建守护进程
创建守护进程的编程规则:
- 调用umask将文件模式创建屏蔽字设置为已知值(一般为0);
- 调用fork,父进程exit。保证进程不是一个进程组组长,这是setsid调用的先决条件;
- 调用setsid创建新会话,使调用进程:(1)成为会话首进程,(2)成为新进程组的组长,(3)不控制终端;
- 将当前工作页面更改为根目录;
- 关闭不需要的文件描述符;
- 打开文件描述符0、1、2,使任何读标准输入、标准输出、标准错误的库例程不产生效果。
下面是一个守护进程的初始化函数:
1 |
|
单实例守护进程
有些守护进程,在任一时刻必须只运行该守护进程的一个副本,防止一些操作的重复执行,可能导致出错。
文件和记录锁可以保证一个守护进程只有一个副本在运行。一个守护进程创建一个文件,并在文件上加了一把写锁,并且只允许创建一把写锁。此后创建写锁的操作均会失败,这告诉后续的守护进程此时已经有一个副本正在运行。在该守护进程终止时,写锁将自动被删除,从而去除了之前守护进程实例进行清理的相关操作。
实例
下面是用文件和记录锁来保证只运行一个守护进程的一个副本。
1 |
|