在掌握会话的相关概念后,本篇完成一个创建会话的实例。
1. 目标
创建一个新会话,该会话中只有一个进程,就是创建该会话的进程。
2. 思路
创建会话的一个必要条件就是创建会话的进程不能是进程组组长。
这样做的理由是:假设该进程是进程组组长,创建完该会话后,该进程成为了其它会话中的 session leader。然而,其组员(如果存在的话)仍然存在于原来的会话中,这将导致同一个进程组中的进程处在不同会话中,显然这是不允许的。
直接在 bash 中执行进程,默认情况下,bash 会将该进程设置为进程组组长。
所以为了防止进程是进程组组长,有两种做法:一、将你的进程加入到当前会话中的其它组中;二、让你的进程 fork 出一个子进程,再 kill 掉父进程(不 kill 也没关系)。
第一种做法通常不太适合,因为你并不知道当前会话中有哪些组;其次,你怎么能随便把你的进程加到其它不相干的组呢?
所以这里就只有第二种做法了。
3. 程序清单
- 代码
注意,上面的程序并没有 kill 掉父进程,这不是必须的。但是通常会 kill 掉,因为父进程已经没什么用了,除非你另作它用。
- 编译和运行
- 运行结果
图1 session 进程运行的结果
通过使用命令 ps ajx | sed -n '1p;/\/session$/p;/bash/p;/ps ajx/p'
可以查看当前相关的会话。
图2 通过命令查看会话
图 2 中一共显示了 3 个会话,分别是 2874、2294、2925.
我们理一下这些会话之间的关系:
从上面的树型图可以很清晰的理清各个会话、进程组以及进程间的关系。
进程 2874 就是我们 fork 出来的子进程,它创建了一个新的会话 2874,同时任该会话的 session leader,同时也是进程组的组长。注意到进程 2874 已经脱离的终端了,在图 2 中的 TTY 一栏显示的是一个问号。
在会话 2294 中,进程 2294 是 session leader,也就是 bash 进程,我们执行 ./sesion 程序时,就是在这个 bash 中。其中,父进程 2873 仍然还在该会话中。
会话 2925 的 session leader 是 bash 2925 进程,也就是是我们执行命令ps ajx | sed -n '1p;/\/session$/p;/bash/p;/ps ajx/p'
的那个地方,该会话中有两个进程组,其中一个进程组就只有 bash 进程组自己,另一个进程组,就是我们执行的命令,该进程组中有两个进程,分别是 ps 和 sed,而 ps 是该进程组的组长。
4. 总结
- 理解会话
- 掌握创建会话的方法
- 理解进程组组长为什么不能创建新会话
练习1:完成本文中的实验,分析进程间关系。
练习2:直接关闭掉执行 ./sesion 程序的终端,再使用 ps 命令查看结果。