1. 进程
程序是指的存储在存储设备上包含了可执行机器指令和数据的静态实体,可执行指令即二进制代码。进程是已经被操作系统从存储设备加载到内存,动态运行的指令和数据的集合,是运行中的动态实体。
2. 进程组
每个进程除了有一个进程ID、父进程ID外,它还有一个进程组ID,标识它属于一个进程组。进程组是一个或者多个进程的集合。这些进程并非孤立,它们之间或者是父子进程,或者功能有相近的联系。每个进程都有父进程,而所有的进程都是以init进程为根,形成一个树状结构。
Linux中提供进程组实质是为了方便对进程进行管理。假设为完成一个任务,需要并发100个进程,但当用户处于某种场景时要终止这100个进程,若没有进程组就需要一个个地去终止,且严格按照亲缘关系顺序,否则会出现僵尸进程等现象扰乱进程树。有了进程组,就可以将这100个进程设置为一个进程组,这些进程共用一个进程组ID,进程组ID等于”辈分最高”的进程的ID,一般是父进程。这样一来,终止这100个进程,只需要终止这100个进程所在的进程组即可。
关于进程组需要注意的:
(1) 一个程序对应一个进程组
(2) 进程组的ID就是进程组领导进程的PID
(3) 在领导进程的PID前面加负号即是操作进程组
(4) 领导进程不能再创建进程组
(5) 领导进程结束不会影响进程组的PID。只要进程组中一个进程存在,则该进程组就会存在,这和组长进程是否终止无关
涉及到的系统调用有:
int setpgid(pid_t pid, pid_t pgid);
pid_t getpgid(pid_t pid);
pid_t getpgrp(void); /* POSIX.1 version */
pid_t getpgrp(pid_t pid); /* BSD version */
int setpgrp(void); /* System V version */
int setpgrp(pid_t pid, pid_t pgid); /* BSD version */
任何一个可执行程序,例如a.out。运行它时它便成为一个进程,该进程可能还会在代码中创建子进程,所以说,a.out运行后还是一个进程组,a.out所创建的子进程所在的组也在a.out进程组。
int main(void)
{
printf("parent: pid = %d, ppid = %d, pgid = %d\n", getpid(), getppid(), getpgrp());
//setpgrp(); //新建进程组,本父进程作为领导进程。但是本进程已经是进程组的领导进程,它不可再创建组
//printf("parent: pid = %d, ppid = %d, pgid = %d\n", getpid(), getppid(), getpgrp());
if (fork() == 0)
{
printf("child: pid = %d, ppid = %d, pgid = %d\n", getpid(), getppid(), getpgrp());
getchar();
//setpgrp(); //新建进程组,本子进程作为领导进程,创建成功后,子进程的进程组ID等于本子进程ID
//printf("child: pid = %d, ppid = %d, pgid = %d\n", getpid(), getppid(), getpgrp());
exit(0);
}
wait(NULL);
return 0;
}
运行结果:
在程序运行中,若想终止这个进程组,可以通过命令
$ kill -9 -3671
3671既是进程组的ID,也是a.out父进程的ID。所以,若想终止整个进程组,即在ID前加上负号,否则则是终止父进程
3. 会话
Linux是多用户多任务的分时系统,它支持多个用户同时使用一个操作系统。当一个用户登录一次系统就会形成一次会话。一个会话可包含多个进程组,但只能有一个前台进程组,其他的是后台进程组。每个会话可以连接一个控制终端,当控制终端有输入输出时,都会传递给该会话的前台进程组。由终端产生的信号,比如ctrl+z,ctrl+\和ctrl+c。一个会话可以有一个控制终端,建立控制终端连接的会话首进程被称为控制进程。
进程属于一个进程组,进程组属于一个会话,会话可能有也可能没有控制终端。当用户在某个终端上登录时,一个新的会话就开始了。进程组由组中的领导进程的ID标志,同理,每个会话也对应有一个领导进程,该进程的ID也作为该会话的标志。
会话相关的函数是:
pid_t getsid(pid_t pid);
pid_t setsid(void);
会话相关的注意点:
(1) 组长和会长不能创建会话
(2) 一个会话只有一个控制终端,也可以没有(守护进程,后台运行)
(3) 前台进程组,使用控制终端的进程组为前台进程组 (命令fg)
(4) 后台进程组,没有使用控制的进程组为后台进程组 (ctrl + z) (jobs 查看后台运行的程序)
在嵌入式Linux开发中,用到进程组和会话的地方,估计只有shell编程和守护进程了。文章内容大都摘自别人博客文章,有用到再来补充吧。