文章目录
守护进程
守护进程概念
什么是守护进程
守护进程就是后台运行的一种特殊的进程,它独立于控制终端并且周期性的进行某种任务或者等待处理某些时间。
守护进程的应用
守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的,比如,ftp服务器,ssh服务器,Web服务器httpd等。同时,守护进程完成许多的系统任务,比如说作业规划等
守护进程的特点
(1)自成进程组,自成会话,与控制终端脱关联
(2)守护进程的父进程是1号进程,其实守护进程都是孤儿进程
(3)守护进程的命令一般以字符d结尾,代表deamon
(4)守护进程的生命周期是7*24小时不掉线
查看系统中进程
ps axj | more
a表示显示其他用户下的进程
x表示不仅显示有控制终端的进程,也显示没有控制终端的进程
j表示列出与作业有关的信息
- 凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程
- 在COMMAND一列用[]括起来的名字标识内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行,通常采用以k开头的名字,表示Kernel
- init进程我们已经很熟悉了,udevd负责维护/dev目录下的设备文件,acpid负责电源管理,syslogd负责维护/val/log下的日志文件
- 可以看出,守护进程通常采用以d结尾的名字,表示Daemon
创建守护进程
知识储备
最关键的一步调用setsid函数
#include <unistd.h>
pid_t setsid(void);
调用该函数的作用
创建一个新的Session
成功调用该函数的结果
(1)创建了一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id
(2) 创建了一个新的进程组,该进程称为该进程组的Leader,当前进程的id就是进程组的id。
(3) 如果当前进程原本有一个控制终端,则它失去了这个控制终端的控制权限。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。
创建守护进程的步骤
(1)umask(0)
调用umask将文件模式创建屏蔽字设置为0,守护进程创建文件可以获得最大的权限
(2)调用fork
调用setsid的进程不能是进程组Leader,所以先fork,然后父进程退出2
(3)调用setsid()
创建一个新的会话
(4)设置忽略SIGCHLD信号
忽略SIGCHLD信号,如果守护进程创建了子进程后,子进程退出时会自动被操作系统回收,不需要调用waitpid
(5)将当前工作目录更改为根目录
防止当前目录有一个目录被删除,导致守护进程无效,使用fork创建的子进程继承了父进程的当前工作目录,由于在进程运行中,当前目录所在的文件系统是不能被卸载的,这对以后使用会造成好多的麻烦,因此通常的做饭是让"/"作为守护进程的当前目录,当然也可以指定其他别的目录作为守护进程的工作目录
(6)关闭不需要的文件描述符
有些文件被打开了但永远不会被守护进程读写,这就造成了系统的资源浪费,所以关闭最好.比如
close(0);
close(1);
close(2);
fork两次的原因
第一次
第一次fork作用主要是为了setsid服务,因为调用setsid的进程不能是进程Leader
第二次
第二次不是必须的,第二次fork是在调用了setsid之后,目的为了防止进程再打开一个控制终端,打开控制终端的条件是必须是会话Leader,但是如果再fork一下,子进程id就不等于会话Id了,这样就不可能打开一个控制终端了
系统提供创建守护进程的接口
daemon函数
int daemon(int nochdir, int noclose);
参数传0代表能改变,也就是说当前目录可以改变,可以改变文件描述符的打开与关闭
参数
当 nochdir为零时,当前目录变为根目录,否则不变;
当 noclose为零时,标准输入、标准输出和错误输出重导向为/dev/null,也就是不输出任何信 息,否则照样输出。
返回值
deamon()调用了fork(),如果fork成功,那么父进程就调用_exit(2)退出,所以看到的错误信息 全部是子进程产生的。如果成功函数返回0,否则返回-1并设置errno。
这个函数把上面的事都帮你做了,你只需要像下面那样调用即可
#include <stdio.h>
#include <unistd.h>
int main()
{
daemon(0,0);
while(1);
}