创建守护进程
一、什么是守护进程?
是指在后台运行的,没有控制终端与之相连的进程,它独立于控制终端,通常周期性地执行某种任务。
二、怎么创建守护进程?
1. 让进程在后台执行。
- 方法:调用fork或vfork生成一个进程,然后父进程退出。
2.调用setsid创建一个新会话(目的是为了摆脱终端)。控制终端、登录会话和进程组通常是从父进程继承下来的,守护进程要摆脱它们,不受它们的影响。
- 方法: 调用setsid使进程成为一个会话组长和进程组长,并与原来的登录会话和进程组脱离,由于会话过程对控制终端的独占性,进程同时与控制终端脱离
3.禁止进程重新打开控制终端
- 方法:通过使进程不再是会话组长来实现,再一次通过fork创建新的子进程,使调用fork的进程退出
4.关闭不再需要的文件描述符
- 方法:先得到最高的文件描述符值,然后通过一个循环,关闭0~最高描述符之间的所有文件描述符
5.将当前进程工作目录更改为根目录
- 原因:当守护进程当前工作目录在一个装配文件系统中时,该文件系统不能被拆卸。
6.将文件创建时使用的屏蔽字设置为0
- 方法:umask(0);
7.处理SIGCHID信号,防止产生僵尸进程
三、守护进程通常怎么使用?
守护进程通常创建后即用写好的守护进程可执行程序替换其代码区(使用exec函数族)
使用举例:
题目描述:创建一个守护进程,每一秒打印一个hello world!
创建守护进程的程序test.c文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pid;
int i;
//创建子进程
if((pid = fork()) < -1)
{
perror("fork");
exit(1);
}
if(pid > 0)
{
//退出父进程
exit(0);
}
//改变创建文件的权限掩码
umask(0);
//创建一个新会话
setsid();
//改变进程工作目录
chdir("/");
//关闭所有文件描述符(除了标准输出), getdtablesize函数获取进程可打开最大文件数
close(0);
for(i = 2; i < getdtablesize(); i++)
{
close(i);
}
//使用可执行程序hello替换子进程的进程空间的代码段
execl("/home/sunxiwang/03AgainStudyLinux/workspace/10process/hello", NULL);
return 0;
}
守护进程真正可执行程序hello.c文件
#include <stdio.h>
#include <unistd.h>
int main(void)
{
while(1)
{
printf("hello world!\n");
sleep(1);
}
return 0;
}
截图: