Bootstrap

创建守护进程

创建守护进程

一、什么是守护进程?

是指在后台运行的,没有控制终端与之相连的进程,它独立于控制终端,通常周期性地执行某种任务。

二、怎么创建守护进程?

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;
}  
截图:

查看守护进程信息:

;