目录
进程组
什么是进程组
我们在命令行中输入sleep 1 | sleep 2 | sleep 3,然后查看进程,

我们看到它们有不同的pid,表明它们是不同的进程,它们的ppid是一样的,那么它们是兄弟进程。除了pid和ppid外,我们看到第三列还有pgid(process group id,进程组id),它们对应的pgid是一样的,表明它们属于同一个组,这三个进程的组长是第一个被创建的进程,即sleep 1000。我们再来写这样一段简单代码:


我们发现这一个进程也有自己的pgid,其pgid就是它自己的pid本身。也就是说,哪怕只有一个进程,也能自成进程组。
我们再来写这样一段代码:


我们发现,它们的pid不一样说明这是两个进程。但是我们发现它们的pgid是一样的,就是父进程的pid。如果我们将来在写一个多进程程序的时候,多个进程其实是以进程组的方式来共同完成一件任务的。进程组是一个或者多个进程的集合, 一个进程组可以包含多个进程。
组长进程
每一个进程组都有一个组长进程,组长id就是其进程id。
- 进程组长的作用:可以创建一个进程组或者创建该进程组中的进程。
- 进程组的生命周期:从进程组创建开始到其中最后一个进程离开为止。注意:只要某个进程组中有一个进程存在,则该进程就存在,与其组长进程是否已经终止无关。
-e 选项表示every的意思,表示输出每一个进程的信息。
-o 选项以逗号操作符(,)作为分界符,可以指定要输出的列

会话
什么是会话
在使用xshell登录linux服务器时,linux会为我们创建一个终端文件,还创建一个bash进程,以进程组的方式来给我们提供命令行解释的服务。bash进程通过终端文件进行读写数据,



一个会话内部可以有多个进程组。
我们再看这样的命令:

加上&表示让进程在后端运行,同时继续运行自己写的process_task进程:

我们发现,运行的sleep和process_task,它们属于不同的进程组。更重要的是,后面有一列叫SID,即会话ID,它们的会话ID是一样的,会话ID是一样的。会话ID一般是会话中的第一个进程,一般是bash。会话可以看成是一个或多个进程组的集合, 一个会话可以包含多个进程组。 每一个会话也有一个会话 ID(SID)。

如果想把这个进程放在后台,就在后面加&。

这种前台进程运行时,我们输入一些命令pwd、ls,发现没有反应。
实际上,同一个会话中,可以运行同时存在多个进程组,但是任何时刻只允许一个前台进程(组),可以允许多个后台进程(组)。当刚开始时,前台进程是bash,输入指令,bash就会响应,而当执行我们自己的任务进程时,我们的任务就变成了前台进程了,这是bash自动把自己切换到后台。当输入指令时,都给了前台进程,bash就收不到了,输入的命令当然就无法执行了。当把我们自己的进程终止了,bash又把自己重新切换到前台,等待用户输入。所以,我们现在发现,所谓前后台,就是谁应该从标准输入中获取数据!这就是后台进程使用ctrl+c也杀不掉的原因。这样正是我们自己运行的程序可以通过ctrl+c终止。
作业控制
作业是针对用户来讲, 用户完成某项任务而启动的进程, 一个作业既可以只包含一个进程, 也可以包含多个进程, 进程之间互相协作完成任务, 通常是一个进程管道。
当我们把完成某个作业的进程放在后台运行时,如下

1\]表示作业号,
我们再创建一个作业,

作业号就是2了,如果我们想查询当前的作业,可以使用jobs (-l),

这两个作业都在后台,如果想把某个作业放在前台,比如想把1号作业放在前台运行,就输入fg 1,此时这个作业就能接收键盘输入的命令,

如果想把刚才移到前台的作业放到后台,就需要先暂停这个前台作业,使用ctrl+z暂停,

然后再输入bg 2,将2号作业放到后台,

关于默认作业:对于一个用户来说,只能有一个默认作业(+) ,同时也只能有一个即将成为默认作业的作业(-),当默认作业退出后,该作业会成为默认作业。
**常见作业状态**
|-------------------|-------------------|
| 作业状态 | 含义 |
| 正在运行【Running】 | 后台作业(\&),表示正在执行 |
| 完成【Done】 | 作业已完成,返回的状态码为0 |
| 完成并退出【Done(code)】 | 作业已完成并退出,返回的状态码非0 |
| 已停止【Stopped】 | 前台作业,当前被Ctrl+Z终止 |
| 已终止【Terminated】 | 作业被终止 |
## 守护进程
进程组,无论是前台还是后台,都属于同一个会话。如果我们把某一个进程组从当前会话a中拿出来,形成一个单独的会话b,这样和刚才的会话a由包含关系变成并列关系。即使把a会话删除,也并不影响b会话,我们把这个进程称为**守护进程**。这个守护进程不会因用户登录或退出受影响,那一个进程如何将自己变成独立的会话从而变成守护进程呢?就需要使用setsid函数:
#include