守护进程
一:什么是守护进程
守护进程是生存期长的一种进程,他们常常在系统引导装入时启动,在系统关闭时终止,他们没有终端,所以他们始终在后台运行。
二、守护进程的特性
1.大多数守护进程都是root权限。
2.因为守护进程没有终端,所以终端名为问号 ‘?’。
3.大多数守护守护进程是进程组组长和会话的首进程。
4.用户层的守护进程是init进程,init进程是系统守护进程。
5.内核守护进程的名字出现在方括号中。
我们可以在中端输入命令 ps -aux 查看进程
我们可以看到 TTY 终端这一列都是问号,说明他们都是守护进程,包括我们熟悉的init进程,我们还可以看到一些进程有方括号括起来了,这些事内核的守护进程。
我们看一下这几个进程。
pid=2的进程是kthreadd,在Linux中kthreadd进程用来创建其他内核进程,所以kthreadd进程是其他内核进程的父进程。
pid=9的进程,内核工作进程,1:主设备号,0副设备号
pid=18的进程sync_supers,该守护进程定期将文件系统元数据冲洗至磁盘。
pid=27的进程kswapd,是内存换页守护进程,它支持虚拟内存子系统在一定时间回收磁盘的脏页面。
三、如何写一个守护进程
写守护进程我们需要根据它的特性注意一下几点
1. 调用umask 将文件模式创建屏蔽字设置为一个抑制值(一般是0),守护进程一般需要root权限,所以如果由继承来的文件模式创建屏蔽字会导致权限不够的问题,
2. 调用fork,然后使父进程exit,这样保证子进程不是进程组组长为调用setsid准备条件。
3. 调用setsid创建一个新的会话,然后(1)成为会话的首进程,(2)成为新进程组组长,(3)没有控制终端
4. 将当前工作目录改为根目录。因为父进程继承过来的目录可能是一个挂载的文件系统,一旦该文件系统被卸载了,那么该进程也不存在了。
5. 关闭不在需要的文件描述符
6. 打开/dev/null 使其具有文件描述符0、1、2。这样防止其输出到终端。
实例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <syslog.h>
void daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pit_t pid;
struct rlimit r1;
struct sigaction sa;
umask(0);
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
printf("%s: can't get file limit\n", cmd);
if (pid = fork() < 0)
printf("fork error\n");
else if (pid != 0)
exit(0);
setsid();
sa.sa_handler = SIG_IGN;
sigemptyset(sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
printf("sigaction error\n");
if (pid = fork() < 0)
printf("fork2 error\n");
else if (pid != 0)
exit(0);
if (chdir("/") < 0)
printf("chdir error\n");
if (r1.rlim_max == RLIMIT_INFINITY)
rl.rlim_max = 1024;
for (i = 0; i < r1.rlim_max; i++)
close(i);
fd0 = open("dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file description %d %d %d", fd0, fd1, fd2);
exit(1);
}
}
int main()
{
daemonize("a.out");
while(1)
{
}
}
最后我们gcc 编译这个程序,./a.out执行这个程序,我们可以看到如下结果
其实带问号的a.out就是我们的守护进程,至此,我们一个初级的守护进程就大功告成了。