> 文档中心 > 守护进程与session

守护进程与session

文章目录

    • 一、session介绍
      • 1.1 进程
      • 1.2 session(会话期)
    • 二、守护进程
      • 2.1 创建session的可靠方法
      • 2.2 守护进程详解
      • 2.3 守护进程编写规则
    • 三、Linux-C实现
    • 三、参考

一、session介绍

1.1 进程组

进程组是一个或多个进程的集合,每个进程除了有一进程ID之外,还属于一个进程组,每个进程组有一个组长进程,组长进程的进程组ID等于其进程ID。

1.2 session(会话期)

当我们进入Linux操作系统,打开一个黑乎乎的终端输入框,这时,我们就打开了一个session,而每当我们打开一个新的终端时,总会创建一个新的session。

session是由session中的第一个进程创建的,一般情况下是打开终端时创建的 shell 进程。该进程也叫 session 的领头进程。session 中领头进程的 PID 也就是 session 的 SID。

就进程间的关系来说,session 由一个或多个进程组组成,也就是说,我们在终端下打开的进程都属于该session。

下面来一张经典的图进行说明:
守护进程与session
此外,Session 的意义在于多个进程组在一个终端中运行,其中的一个为前台 进程组,它直接接收该终端的输入并把结果输出到该终端,其它的进程组则在后台运行,新创建的每个进程都会属于一个进程组,当创建一个进程时,它和父进程在同一个进程组、session 中。

值得注意的是,使用 setsid 函数使进程成为新 session 的领头进程。

二、守护进程

2.1 创建session的可靠方法

前言:如果一个进程ID与其所在组的组ID一致,则该进程为所在进程组的组长。

建立新session的方法:进程调用setsid函数。
如果调用此函数的进程不是一个进程组的组长,则此函数创建一个新session,具体会发生以下三件事:
1)该进程会变成新session的会话首进程,此时该进程是新session中的唯一进程;
2)该进程成为一个新进程组的组长进程,新进程组ID是该调用进程的进程ID;
3)该进程没有控制终端,如果再调用setsid之前该进程有一个控制终端,那么该联系也被切断。

如果该调用进程已经是一个进程组的组长,则此函数返回错误,为了不出现这种情况,我们可以采取下列措施:
先调用fork函数,再将父进程终止,子进程继续,此时的子进程继承了父进程的进程组ID,其进程ID则是新分配的,两者不一致,即子进程不可能是该进程组的组长。

2.2 守护进程详解

进程有对应的终端,若终端退出,则对应的进程也会消失。守护进程是一种长期运行的进程,这种进程在后台运行,并且不跟任何的终端关联,基本特点如下:
• 生存期长,一般是操作系统启动的时候他就启动,操作系统关闭的时候他就关闭;
• 守护进程与跟终端无关联,即无控制终端,即终端退出也不会导致守护进程退出;
• 守护进程在后台运行,不会占着终端,终端可以执行其他命令。

2.3 守护进程编写规则

1)fork一个子进程,然后父进程退出
2)调用umask(0),umask函数用来限制或屏蔽一些文件权限
3)设置会话session
4)重定向标准输入、输出等
注意:守护进程虽然可以通过终端启动,但是和终端不挂钩,守护进程在后台运行,他不应该从键盘上接受任何东西,也不应该把输出结果打印到屏幕上或者终端上来,所以一般要把守护进程的标准输入、标准输出、重定向到 空设备(/dev/null),从而确保守护进程不从键盘接受任何东西,也不把输出结果打印到屏幕。

三、Linux-C实现

int SetDaemon(){    switch(fork()){ case -1:     printf("SetDaemon() failed! fork() failed!");     return -1; case 0:     break; default:     exit(1);    }    // 设置会话组,脱离终端    if(setsid() == -1){ printf("SetDaemon() failed! setsid() failed!"); return -1;    }    // 重设文件权限掩码    umask(0);    int fd = open("/dev/null", O_RDWR);    if(fd == -1){ printf("SetDaemon() failed! open() failed!"); return -1;    }    // 关闭文件描述符    if(dup2(fd, STDIN_FILENO) == -1) // 关闭并重定向标准输入为fd    { printf("SetDaemon()中dup2(STDIN)失败!");  return -1;    }    if(dup2(fd, STDOUT_FILENO) == -1)    { printf("SetDaemon()中dup2(STDOUT)失败!"); return -1;    }    if(fd > STDERR_FILENO)    { if(close(fd) == -1) {     printf("SetDaemon()中close(fd)失败!");     return -1; }    }    return 0;}

三、参考

https://www.cnblogs.com/shichuan/p/4496188.html
https://blog.csdn.net/inthat/article/details/122458580