# 进程

## 进程组（process group）

* 每个进程组都有一个leader进程称为进程组组长，进程组组长的pid与进程组pgid一致

## 会话（session）

* 会话是若干进程组的集合
* 一个会话最多拥有一个控制终端（tty或pts）
* 一个会话有且只有一个前台进程组，可以有若干后台进程组
* 会话的控制终端被前台进程组的所有进程共享
* 每个会话有一个会话首进程，该进程的pid与sid一致
* 当会话首进程退出时，会给该会话的所有进程发送sighup信号（kill -1 pid）

当我们使用ssh登录到一台主机时，其实就开启了一个bash进程，可以通过以下命令查看该bash进程的pid

```
$ echo $$
29575
```

创建bash进程的同时也为它创建一个会话以及一个控制终端，我们登录到主机时能够输入命令的那个就是控制终端。通过以下的命令查看会话id与终端名称等信息：

```
$ ps j 29575
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
 29571  29575  29575  29575 pts/2     29603 Ss       0   0:00 -bash
```

解释一下上面的前几列：

* PPID：父进程id
* PID：进程id
* PGID：进程组id
* SID：会话id
* TTY：控制终端名称
* TPGID：该session的前台进程组id

可以看出：pid等于pgid，所以bash进程是进程组29575的组长；pid等于sid，所以bash进程是会话29575的会话首进程。

接下来，我们在当前终端下起一个进程，先编写脚本 `a.sh`，内容如下：

```
#!/bin/bash

echo "a start"
/usr/bin/dockerd --config-file /etc/docker/daemon.json &
sleep 1000
echo "a end"
```

执行命令：

```
$ ./a.sh
```

接下来，我们在另一个终端（另一个ssh登录）下查看该session下的进程：

```
$ ps j -e | grep 29575
 29571  29575  29575  29575 pts/2     29575 Ss+      0   0:00 -bash
 29575  29633  29633  29575 pts/2     29575 S        0   0:00 /bin/bash ./a.sh
 29633  29634  29633  29575 pts/2     29575 Sl       0   0:00 /usr/bin/dockerd --config-file /etc/docker/daemon.json
 29633  29635  29633  29575 pts/2     29575 S        0   0:00 sleep 1000
```

可以看到，这几个进程共用一个控制终端（pts/2）。在这里要注意的是，a.sh在执行命令`sleep 1000`时，是起了一个新的进程，a.sh进程之所以没有退出是要等待`sleep 1000`进程结束返回。这几个进程的父子关系是：

```
bash
└── a.sh
    ├── dockerd
    └── sleep 1000
```

接下来，我们在新的终端下终止会话首进程bash进程：

```
$ kill -1 29575
```

执行该命令后，29575的bash进程的连接就断开了。我们查看会话29575中的进程情况：

```
$ ps j -e | grep 29575
1  29634  29633  29575 ?            -1 Sl       0   0:00 /usr/bin/dockerd --config-file /etc/docker/daemon.json
```

发现，a.sh进程与sleep进程不在了，但dockerd进程还在。我猜测是：会话首进程给进程组中的每个进程发送了sighup信号，`a.sh`进程与`sleep 1000`进程接收到信号后终端运行退出，而dockerd进程却忽略了该信号还继续执行。

这里我们可以手动给dockerd进程发送sighup信号，验证该进程会忽略该信号。执行以下命令，发现dockerd进程还在：

```
$ kill -1 29634
$ ps j -e | grep 29575
1  29634  29633  29575 ?            -1 Sl       0   0:00 /usr/bin/dockerd --config-file /etc/docker/daemon.json
```

同时，dockerd进程的tty变成了`?`，说明该进程已经没有了终端输入与输出能力；dockerd的父进程id变成1，说明该进程已被init进程管理；sid与pgid却还保持没变。

## `nohup` vs `&`

后台命令符号`&`的意思是，子进程进入后台执行模式，父进程不需要等待子进程的返回就可以继续往后面执行。

nohup的意思是，当进程接收到sighup信号时，选择忽略，不会主动结束执行。

## Reference

\[1] <https://www.ibm.com/developerworks/cn/linux/1702_zhangym_demo/index.html> \[2] <https://blog.csdn.net/outofmemo/article/details/54151326>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pshizhsysu.gitbook.io/linux/other/jin-cheng.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
