守护进程&创建

来源:互联网 发布:毕加索美工钢笔 编辑:程序博客网 时间:2024/06/08 05:00

守护进程

守护进程也称为精灵进程,是一种运行在后台的特殊进程。和其他后台进程所不同的是,它始终独立其他会话,自成会话组,不受系统登录和注销的影响,一般都是7*24小时在后台运行的,并且守护进程是去关联的(因为不需要和前台服务进行交互)


背景知识

建立新会话:setsid()函数


原型:#include<unistd.h> pid_t setsid(void); //返回值:若成功则返回进程组ID,若出错则返回-1
1、该调用进程是组长进程,则出错返回。先调用fork, 父进程终止,子进程调用
2、该调用进程不是组长进程,则创建一个新会话
1)该进程变成新会话首进程(session header)

2)该进程成为一个新进程组的组长进程。 

3)该进程没有控制终端,如果之前有,则会被中断。具体也就是说:如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。

组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。

会话ID:会话首进程的进程组ID,获取会话ID用getsid()函数

原型如下:

#include<unistd.h> pid_t getsid(pid_t pid); //返回值:若成功则返回会话进程的进程组ID,若出错则返回-1


守护进程创建步骤

首先需要明确的一点是守护进程创建过程中最重要的一点就是调用setsid,创建一个新的会话,并使自己称为该会话的会话首地址,不过不允许当前进程是进程组的leader,要保证这一点我们最常使用的方法就是,先调用fork()函数,然后杀掉父进程,这样就可以保证该要求;

1)调用fork()创建子进程,然后exit掉父进程,这样就可以保证所有的任务都是在子进程下工作;

2)进行去连接操作,调用setsid在子进程中创建一个新的会话;

3)将当前工作目录修改为工作目录;(防止受到上层目录删除的影响)

4)将umask的值设置为0,这样就可以创建出想要的权限的文件,防止受到umask的影响;

5)关闭不需要的文件描述符,一般来说就是关闭默认的0,1,2三个文件描述符;

6)忽略掉SIGCHLD信号


代码实现:


守护进程查询:(可以看到三个.mydaemon都变成了守护进程)



当然库里面也有专门的daemon函数可以直接供我们,我们也可以直接在上面调用系统提供的daemon函数

函数原型:

#include <unistd.h>
int daemon(int nochdir, int noclose);

创建守护进程时fork一次和两次的比较:


1)首先两种方式都是需要先进行一次fork,作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组组长,如果不fork出子进程,则此时的父进程是进程组组长,就无法调用setsid。当子进程调用完setsid函数之后,子进程是会话组长也是进程组组长,并且脱离了控制终端,此时,不管控制终端如何操作,新的进程都不会收到一些信号使得进程退出。

2)第二次fork的作用:虽然当前关闭了和终端的联系,但是后期可能会误操作打开了终端。但是只有会话首进程能打开终端设备,也就是再fork一次,再把父进程退出,再次fork的子进程作为守护进程继续运行,保证了该精灵进程不是对话期的首进程,第二次不是必须的,是可选的。

原创粉丝点击