守护进程 Daemon
- 守护进程的特点
(1)运行方式: 守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程。
周期性的执行某种任务或等待处理某些发生的事件
(2)生命周期: 守护进程会长时间运行,常常在系统启动时就开始运行,直到系统关闭时才终止
(3)守护进程不依赖于终端
- 查看系统中的守护进程
ps -ajx
-a: 显示所有
-x:显示没有控制终端的进程
-j:显示与作业有关的信息(显示的列):会话期ID(SID),进程组ID(PGID),控制终端(TTY),终端进程组ID(TRGID)
如何识别一个守护进程:
1)一般所有的守护进程都是以超级用户启动的(UID为0);
2)没有控制终端(TTY为 ?);
3)终端进程组ID为-1(TPGID表示终端进程组ID,该值表示与控制终端相关的前台进程组,如果未和任何终端相关,其值为-1;
4)所有的守护进程的父进程都为init进程(PPID为1的进程)。
-
相关概念
1)进程组(process proup):进程组是一个或多个进程的集合。进程组由进程组ID(PGID)来唯一标识。每个进程组都有一个组长进程,组长PID=PGID
2)会话期(session):是一个或多个进程组的集合。一般一个用户登录后新建一个会话,每个会话也有一个ID来标识(SID)。
3)控制终端:一个会话一般会拥有一个控制终端用于执行IO操作。用户登录的终端就成为该会4)前台进程组登录后的第一个进程叫做会话领头进程(session leader),通常是一个shell/bash。领头进程的PID=SID
4)前台进程组:该进程组中的进程能够向终端设备进行读、写操作的进程组。
5)后台进程组:该进程组中的进程只能够向终端设备写。每个会话有且只有一个前台进程组,但会有0个或者多个后台进程组。
6)终端进程组ID(TPGID)
用来标识一个进程和终端的关系
"前台进程组"中的进程的TPGID=PGID
"后台进程组"的PGID≠TPGID。
TPGID=-1 说明该进程和终端无关,不依赖于终端 -
编写守护进程
step1:创建子进程,父进程退出
step2:脱离控制终端,创建新的会话
#include <unistd.h>
pid_t setsid(void);
函数功能:
1)首先内核会创建一个新的会话,并让该进程成为该会话的leader进程,
2)同时伴随该session的建立,一个新的进程组也会被创建,同时该进程成为该进程组的组长。
3)如果调用setsid之前该进程有一个控制终端,那么这种联系也被切断。
返回值:
成功 返回新会话期的ID sid
失败 返回 -1
注意:
调用该函数的进程不能是进程组组长
step 3 禁止进程重新打开控制终端。//再次调用fork函数生成子进程,并将父进程关闭
step 4: 改变当前工作目录
因为守护一直运行在后台,如果工作目录被卸载,运行会出错。所以将守护进程的工作目录切换到一个不能被卸载的目录下。
也可以把当前工作目录换成其他的路径,如/tmp。
#include <unistd.h>
int chdir(const char *path);
函数功能:
改变进程的工作目录
函数参数:
path : 改变后的路径
返回值:
成功 返回 0
失败 返回 -1
step 5: 重设文件权限掩码
#include <sys/types.h>
#include <sys/stat.h>mode_t umask(mode_t mask);
函数功能:
设置文件权限掩码
函数参数:
[1] mask : 文件权限掩码
返回值:
原先的文件权限掩码
step 6:关闭文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源
#include <unistd.h>
int getdtablesize(void);
函数功能:
返回最多打开的文件描述符个数(1024)