1. 进程组
进程组定义:一组相关进程的集合;它们共享同一个进程组 ID —— PGID。
sleep 1000 | sleep 2000 | sleep 3000
sleep 1000
、sleep 2000
和 sleep 3000
分别是三个进程,但它们拥有同样的 PGID(进程组 ID),因此称这些进程属于同一个进程组。
我们可以通过发送信号到整个进程组来控制这些进程,如使用 kill
终止整个管道中的所有进程。
2. 会话
会话通常由一个登入会话创建,每个会话都有一个唯一的标识符,称为 SID(Session ID)。
在**当前会话(SID:32813)**中启动 tcpserver,在另一个终端中再次运行 ps axj | grep -E "tcpserver|bash" | grep -v grep
命令,查看当前的进程及其会话信息。
tcpserver
的 SID 仍是 32813 ,与当前会话的 SID 相同,这表明 tcpserver 属于当前会话。
3. 守护进程(精灵进程)
在 Linux 中,守护进程(Daemon) 是一种后台服务进程,它独立于其它程序运行,通常是为了执行特定的任务或等待处理某些事件。
守护进程通常是在系统启动时启动,持续运行直到系统关闭,它们不与用户直接交互,而是提供服务给其它进程或程序。
那么,如何创建守护进程?
3.1 方法一:setsid()
—— 系统调用接口
setsid
不仅创建一个新的会话,还会使调用进程成为新会话的领导进程,且该进程不能已经是任何进程组的组长。
实际编程中,通常采用 创建子进程,并让父进程退出
的方法。
// Main.cc // 伪代码
int main() {
// ...
if (fork() > 0) exit(0); // 父进程退出
int sid = setsid(); // 子进程执行 setsid 函数
}
3.2 方法二:daemon()
—— 库函数
daemon
函数用于将当前进程转化为守护进程,函数内部封装了创建守护进程所需要的一系列步骤。
#include <unistd.h>
int daemon(int nochdir, int noclose);
// 成功,返回 0; 失败,返回 -1
-
nochdir
0
:改变当前工作目录到根目录/
;非 0
:不改变当前工作目录。 -
noclose
0
:关闭标准输入、输出、错误流;
非 0
:不关闭标准输入、输出、错误流。