Linux session(会话)

笔者在前文《Linux job control》中介绍了进程组(job)的概念以及常见的 job control 操作,本文接着介绍 session 的概念。本文中演示部分使用的环境为 ubuntu 18.04。

我们常见的 Linux session 一般是指 shell session。Shell session 是终端中当前的状态,在终端中只能有一个 session。当我们打开一个新的终端时,总会创建一个新的 shell session。

就进程间关系而言,会话由一个或多个进程组组成。通常,来自单一登录的所有进程属于同一会话。我们可以使用下图来了解进程、进程组和会话之间的关系:

[En]

In terms of inter-process relationships, a session consists of one or more process groups. In general, all processes from a single login belong to the same session. We can use the following figure to understand the relationship between processes, process groups, and session:

会话由会话中的第一个进程创建,通常是在打开终端时创建的外壳进程。这一过程也被称为会议的主导过程。在会话中引导进程的ID也是会话的SID。我们可以使用以下命令查看SID:

[En]

The session is created by the first process in the session, typically the shell process created when the terminal is opened. This process is also called the lead process of session. The PID that leads the process in Session is also the SID of session. We can view the SID with the following command:

Session 中的每个进程组被称为一个 job,有一个 job 会成为 session 的前台 job(foreground),其它的 job 则是后台 job(background)。每个 session 连接一个控制终端(control terminal),控制终端中的输入被发送给前台 job,从前台 job 产生的输出也被发送到控制终端上。同时由控制终端产生的信号,比如 ctrl + z 等都会传递给前台 job。

一般情况下 session 和终端是一对一的关系,当我们打开多个终端窗口时,实际上就创建了多个 session。

Session 的意义在于多个工作(job)在一个终端中运行,其中的一个为前台 job,它直接接收该终端的输入并把结果输出到该终端。其它的 job 则在后台运行。

通常,新的 session 由系统登录程序创建,session 中的领头进程是运行用户登录 shell 的进程。新创建的每个进程都会属于一个进程组,当创建一个进程时,它和父进程在同一个进程组、session 中。

将进程放入不同会话的唯一方法是使用setsid函数使其成为新会话的主导进程。这还会将会话领导流程放入新的流程组。

[En]

The only way to put a process into a different session is to use the setsid function to make it the lead process for the new session. This also puts the session lead process into a new process group.

当 session 中的所有进程都结束时 session 也就消亡了。实际使用中比如网络断开了,session 肯定是要消亡的。另外就是正常的消亡,比如让 session 的领头进程退出。一般情况下 session 的领头进程是 shell 进程,如果它处于前台,我们可以使用 exit 命令或者是 ctrl + d 让它退出。或者我们可以直接通过 kill 命令杀死 session 的领头进程。这里面的原理是:当系统检测到挂断(hangup)条件时,内核中的驱动会将 SIGHUP 信号发送到整个 session。通常情况下,这会杀死 session 中的所有进程。

session 与终端的关系
如果 session 关联的是伪终端,这个伪终端本身就是随着 session 的建立而创建的,session 结束,那么这个伪终端也会被销毁。
如果 session 关联的是 tty1-6,tty 则不会被销毁。因为该终端设备是在系统初始化的时候创建的,并不是依赖该会话建立的,所以当 session 退出,tty 仍然存在。只是 init 系统在 session 结束后,会重启 getty 来监听这个 tty。

如果我们在 session 中执行了 nohup 等类似的命令,当 session 消亡时,相关的进程并不会随着 session 结束,原因是这些进程不再受 SIGHUP 信号的影响。比如我们执行下面的命令:

此时 sleep 进程的 sid 和其它进程是相同的,还可以通过 pstree 命令看到进程间的父子关系:

如果我们退出当前会话引导进程(Bash),休眠进程将不会退出,因此我们可以安全地等待进程运行的结果。

[En]

If we exit the current session lead process (bash), the sleep process will not quit, so we can safely wait for the result of the process to run.

nohup 并不改变进程的 sid,同时也说明在这种情况中,虽然 session 的领头进程退出了,但是 session 依然没有被销毁(至少 sid 还在被引用)。重新建立连接,通过下面的命令查看 sleep 进程的信息,发现进程的 sid 依然是 7837:

但是此时的 sleep 已经被系统的 1 号进程 systemd 收养了:

setsid 会创建一个新的 session,它的目的是让进程在后台执行命令,实现方式就是让命令进程运行在一个新的与终端脱离的 session 中。看下面的示例:

在搜索过程中没有发现睡眠过程的任何痕迹:

[En]

No trace of the sleep process was found under the search:

通过 grep 查询 sleep 进程的 PID:

去查看 sleep 进程所在的 sid,发现是一个新的 session ID,并且没有关联终端:

当进程通过调用setsid成为新的会话主导进程时,它与控制终端断开连接。

[En]

When a process becomes a new session lead process by calling setsid, it disconnects from the control terminal.

此时通过 pstree 查看进程间的关系,发现 sleep 进程直接被系统的 1 号进程 systemd 收养了:

控制终端是进程的一个属性。通过 fork 系统调用创建的子进程会从父进程那里继承控制终端。这样,session 中的所有进程都从 session 领头进程那里继承控制终端。Session 的领头进程称为终端的控制进程(controlling process)。简单点说就是: 一个 session 只能与一个终端关联,这个终端被称为 session 的控制终端(controlling terminal)。同时只能由 session 的领头进程来建立或者改变终端与 session 的联系。我们可以通过 ps 命令查看进程的控制终端:

支持 job control 的 shell 必须能够控制在某一时刻由哪个 job 使用终端。否则,可能会有多个 job 试图同时从终端读取数据,这会导致进程在接收用户输入时的混乱。为了防止这种情况发生,shell 必须按照预定的协议与终端驱动程序协作。

shell 一次只允许一个 job(进程组)访问控制终端。来自控制终端的某些输入会导致信号被发送到与控制终端关联的 job(进程组)中的所有进程。该 job 被称为控制终端上的前台 job。由 shell 管理的其他 job 在不访问终端的情况下,被称为后台 job。

Shell 的职责是通知 job 何时停止何时启动,还要把 job 的信息通知给用户,并提供机制允许用户继续暂停的 job、在前台和后台之间切换 job。比如前台 job 可以无限制的自由使用控制终端,而后台 job 则不可以。当后台 job 中的进程试图从其控制终端读取数据时,通常会向进程组发送 SIGTTIN 信号。这通常会导致该组中的所有进程停止(变成 stopped 状态)。类似地,当后台 job 中的进程试图写入其控制终端时,默认行为是向进程组发送 SIGTTOU 信号,但是否允许写入的控制会更加的复杂。

Original: https://www.cnblogs.com/sparkdev/p/12146305.html
Author: sparkdev
Title: Linux session(会话)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/7229/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部