守护进程

守护进程

一:什么是守护进程
守护进程是生存期长的一种进程,他们常常在系统引导装入时启动,在系统关闭时终止,他们没有终端,所以他们始终在后台运行。

二、守护进程的特性
1.大多数守护进程都是root权限。
2.因为守护进程没有终端,所以终端名为问号 ‘?’。
3.大多数守护守护进程是进程组组长和会话的首进程。
4.用户层的守护进程是init进程,init进程是系统守护进程。
5.内核守护进程的名字出现在方括号中。

我们可以在中端输入命令 ps -aux 查看进程
aaa
我们可以看到 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就是我们的守护进程,至此,我们一个初级的守护进程就大功告成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值