进程、进程组、session

进程属于一个进程组,进程组属于一个会话,会话可能有也可能没有控制终端

  • session(会话)是用户登录系统以后所需的context(上下文)
  • process group(进程组)是一组相关联的进程,用来方便信号量的分发
  • session退出以后所有隶属于该session的进程组都会收到hup信号而挂起,这样就有了控制进程生命周期的作用
  • tty可以作为输入输出设备被绑定到一个session上,bash就是这么干的
  • 子进程会继承父进程的session和process group,可以通过setsid建立新的session来脱离继承的sid,从而逃离旧session的生命周期
  • 当使用killpg将信号传递给进程组的时候,这个信号会被分发至进程组的每个进程。所以进程组可以方便对进程的控制

 

进程

  • PPID 父进程id
  • PID 进程id
  • PGID 进程组id
  • SID 会话id

进程组

进程组的存在是为了方便对一组进程进行统一的管理。比如我们可以通过killpg向进程组传递信号量。或者方便利用job controll来进行前后台进程组的切换。

进程组组长的PID与PGID相等。可以通过 int setpgid(pid_t pid, pid_t pgid);设置进程所在进程组。
下面三个接口含义一致,都是创立新的进程组,并且指定的进程会成为进程组的首进程。如果参数pid和pgid的值不匹配,那么setpgid函数会将一个进程从原来所属的进程组迁移到pgid对应的进程组。 

setpgid(0,0)
setpgid(getpid(),0)
setpgid(getpid(),getpid()) 

可使用 int killpg(int pgrp, int sig);向进程组内所有进程同时发送信号。

进程组可用于容器的虚拟化。

会话

用户每个用户和系统的相对独立的交互。当用户登录并打开bash时,会通过系统调用setsid建立一个session。session就是用户此次登录的context,可以方便的用来存储信息、控制会话、分配资源。比如,session就是tty(控制终端)绑定的对象。

// 用于创建会话的系统调用

#include <unistd.h>
pid_t setsid(void); 

如果这个函数的调用进程不是进程组组长,那么调用该函数会发生以下事情:

  1. 创建一个新会话,会话ID等于进程ID,调用进程成为会话的首进程。
  2. 创建一个进程组,进程组ID等于进程ID,调用进程成为进程组的组长。
  3. 该进程没有控制终端,如果调用setsid前,该进程有控制终端,这种联系就会断掉。

调用setsid函数的进程不能是进程组的组长,否则调用会失败,返回-1,并置errno为EPERM。
这个限制是比较合理的。如果允许进程组组长迁移到新的会话,而进程组的其他成员仍然在老的会话中,那么,就会出现同一个进程组的进程分属不同的会话之中的情况,这就破坏了进程组和会话的严格的层次关系了。

 

在任意时刻,可能同时存在多个后台进程组,但是不管什么时候都只能有一个前台进程组。只有在前台进程组中进程才能在控制终端读取输入。当用户在终端输入信号生成终端字符(如ctrl+c、ctrl+z、ctr+\等)时,对应的信号只会发送给前台进程组。

shell中可以存在多个进程组,无论是前台进程组还是后台进程组,它们或多或少存在一定的联系,为了更好地控制这些进程组(或者称为作业),系统引入了会话的概念。会话的意义在于将很多的工作囊括在一个终端,选取其中一个作为前台来直接接收终端的输入及信号,其他的工作则放在后台执行。

posted @ 2022-09-08 09:03  某某人8265  阅读(172)  评论(0编辑  收藏  举报