Linux—守护进程

守护进程:
守护进程常常在系统引导装入时启动,仅在系统关闭时才终止,是运行在后台的一种特殊进程,且它不受用户登录注销的影响,独立于控制终端周期性的执行某种
任务或等待处理某些发生的事情。

思考:为什么守护进程不受用户登录注销的影响?
守护进程自成进程组,自成会话,与其他会话没有包含关系,所以其他会话的退出不会影响守护进程。

如何查看守护进程:
命令:ps axj 可以查看进程信息。
这里写图片描述

如何创建守护进程:
创建守护进程最关键的一步是调用setsid()函数,包含在unistd.h头文件中。
pid_t setsid(void)
该函数创建成功返回新创建的Session的id,出错返回-1.

setsid函数的作用:
1.创建一个新Session,当前进程成为会话首进程,会话id为当前进程id;
2.创建一个新的进程组,当前进程成为进程组组长,进程组id为当前进程id;
3.如果当前进程有一个控制终端,那么失去控制终端。
调用setsid函数的要求:保证调用者不是进程组的组长。
如何满足这个要求:先fork创建子进程,因为子进程和父进程在同一进程组中,所以子进程不可能是进程组组长,用子进程调用setsid函数就可以满足。

创建守护进程的步骤
调用umask将文件模式屏蔽字设置为0,由继承得来的文件模式创建屏蔽字可能会被设置为拒绝某些权限,如果守护进程创建文件就可能要设置特定的权限;
调用fork成功后使父进程exit,保证子进程不是一个进程组的组长;
调用setsid函数创建一个新会话,使调用进程成为一个新会话的首进程,成为一个新进程组的组长进程,没有终端控制。
将当前目录更改为根目录
关闭不再需要的文件描述符,使守护进程不再持有从父进程中继承来的任何文件描述符;
忽略SIGCHLD信号

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
void mydaemon()
{
    umask(0);
    pid_t pid;
    if(pid=fork()>0)
    {
        exit(0);
    }
    setsid();
    chdir("/");
    close(0);
    close(1);
    close(2);
    signal(SIGCHLD,SIGIGN);
}
int main()
{
    mydaemon();
    while(1);
    return 0;
}

思考:创建守护进程时为什么有的fork两次?
为了避免后期进程误操作再次打开终端。因为打开一个控制终端的前提条件是该进程必须为会话组组长,而通过第二次fork,确保了第二次fork出来的子进程不会是会话组组长。

猜你喜欢

转载自blog.csdn.net/qq_39295755/article/details/79773454