(转)进程间关系:进程、僵尸进程、孤儿进程、进程组、前台进程组、后台进程组、孤儿进程组、会话、控制终端

不同的shell对使用管道线时创建子进程的顺序不同,本文以bash为例,它是支持作业控制的shell的典型代表。

僵尸进程与孤儿进程

僵尸进程:先于父进程终止,但是父进程没有对其进行善后处理(获取终止子进程有关信息,释放它仍占有的资源)。消灭僵尸进程的唯一方法是终止其父进程。
孤儿进程:该进程的父进程先于自身终止。其特点是PPID=1(init进程的ID)。一个孤儿进程可以自成孤儿进程组。

文中用到的缩写

PID = 进程ID (由内核根据延迟重用算法生成)
PPID = 父进程ID(只能由内核修改)
PGID = 进程组ID(子进程、父进程都能修改)
SID = 会话ID(进程自身可以修改,但有限制,详见下文)
TPGID= 控制终端进程组ID(由控制终端修改,用于指示当前前台进程组)

进程、进程组、会话之间的关系

总体关系

进程属于一个进程组,进程组属于一个会话,会话可能有也可能没有控制终端

会话

  • 会话首进程:
    新建会话时,会话中的唯一进程,其PID=SID。它通常是一个登陆shell,也可以在成为孤儿进程后调用setsid()成为一个新会话。
  • 会话:
    一个或多个进程组的集合。一个登陆shell发起的会话,一般由一个会话首进程、一个前台进程组、一个后台进程组组成。

进程组

一个或多个进程的集合,进程组属于一个会话。fork()并不改变进程组ID。

  • 进程组组长:
    PID与PGID相等的进程。组长可以改变子进程的进程组ID,使其转移到另一进程组。
    例如一个shell进程(下文均以bash为例),当使用管道线时,如echo "hello" | cat,bash以第一个命令的进程ID为该管道线内所有进程设置进程组ID。此时echocat的进程组ID都设置成echo的进程ID。
  • 前台进程组
    该进程组中的进程能够向终端设备进行读、写操作的进程组。
    登陆shell(例如bash)通过调用tcsetpgrp()函数设置前台进程组,该函数将终端设备的fd(文件描述符)与指定进程组关联。成为前台进程组的进程其TPGID=PGID,常常可以通过比较他们来判断前后台进程组。
  • 后台进程组
    一个会话中,除前台进程组、会话首进程以外的所有进程组。该进程组中的进程能够向终端设备,但是当试图终端设备时,将会收到SIGTTIN信号,并停止。登录shell可以根据设置在终端上发出一条消息[1]通知用户有进程欲求终端。
    前台进程组ID只能有一个,而后台进程组同时可存在多个。后台进程组的PGID≠TPGID。

孤儿进程组

  • 定义1
    该组中的每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员
  • 定义2
    不是孤儿进程组的条件是,该组中有一个进程,其父进程属于同一会话的另一个组中。
    也就是说,将该父进程终止就能使该进程组成为僵尸进程孤儿进程(感谢网友”hello”的指正)。这个父进程通常是这个进程组的组长进程,因为只有它的父进程在这个进程组外,而其他进程(组长的子进程)的父进程都是组长进程的ID。

解析:产生一个僵尸进程(组)并读终端

  1. 由组长fork()产生的子进程其进程组ID不变(因为fork()不改变进程组ID)
  2. 若组长是bash,则将子进程的进程组ID设置成第一个命令的PID,即由第一个命令当组长,并成为一个新的进程组
  3. 由bash产生的新进程组中,至少要有一个进程的PPID指向该bash,否则该进程组成为孤儿进程组,无法将进程状态的改变通知bash
  4. bash通过wait函数族检测子进程(新的进程组)的状态,从而决定如何设置前台进程组ID(给指定的终端设备)
  5. 后台进程(组)试图控制终端设备时,终端驱动程序向其发送SIGTTIN信号,此时应当由bash唤醒该进程(组),使之进入前台
  6. 对于孤儿进程(组),bash无法知晓其状态,因为bash不知道其PID,而唯一知道其PID的进程已经终止,也就无法知晓其组ID,从而不能将其组ID放入前台。如果孤儿进程(组)试图读取终端,read()调用将失败,并将errno置为EIO。

注释

[1] 可以通过使用stty tostop命令禁止后台进程组向终端进行操作,当发出写请求时,将会收到SIGTTOU信号。

(lesca原创,转载请注明转自http://lesca.me)

版权声明 » 进程间关系:进程、僵尸进程、孤儿进程、进程组、前台进程组、后台进程组、孤儿进程组、会话、控制终端

时间: 2024-10-17 04:07:34

(转)进程间关系:进程、僵尸进程、孤儿进程、进程组、前台进程组、后台进程组、孤儿进程组、会话、控制终端的相关文章

进程间关系

POSIX规定一个进程内部的多个thread要共享一个PID, 但是,在linux kernel中不论是进程还是线程,都是会分配一个task struct并且分配一个唯一的PID(这时候PID其实就是thread ID). 这样,为了满足POSIX的线程规定,linux引入了线程组的概念,一个进程中的所有线程所共享的那个PID被称为线程组ID,也就是task struct中的tgid成员. 因此,在linux kernel中,线程组ID(tgid,thread group id)就是传统意义的进

linux 进程 进程组 作业 会话 控制终端

linux 进程 进程组  会话 控制终端 这几个很容易搞昏,记录一下,防止忘记 1 进程 个人理解 进程就是一段内存中运行的程序 pid 是进程ID 2 进程组 顾名思义,就是一组进程,他们之间不是孤立的,肯那个存在父子 或进程关系,注意linux 下进程是树状组织,  每个进程一定属于一个进程组,也只能属于一个进程组,进程组里面有多个进程  每个进程组都有一个leader,领导进程的PID 就是集成组ID 即 PGID eg: ps -o pid,pgid,ppid,sid,comm  |

[转] linux系统文件流、文件描述符与进程间关系详解

http://blog.sina.com.cn/s/blog_67b74aea01018ycx.html linux(unix)进程与文件的关系错综复杂,本教程试图详细的阐述这个问题. 包括: 1.linux多/单进程与多/单文件对于文件流和描述符在使用时的关联情况及一些需要注意的问题. 2.fork,vfork流缓冲等对文件操作的影响. 1.linux文件系统结构 首先补充一点基础知识,了解一下linux文件系统.如下图所示: 图1 磁盘,分区和文件系统 应该明白,上图所示结构是硬盘中文件存放

操作系统 进程间的通信 之 信号 消息队列 共享内存 浅析

[几个易混淆的相关概念] 进程互斥:指在多道程序环境下,每次只允许一个进程对临界资源进行访问. 进程同步:指多个相关进程在执行次序上的协调. 临界资源:在一段时间内只允许一个进程访问的资源. 临界区:每个进程中访问临界资源的那段代码. [进程通信] 现在常用的进程间通信方式有信号.信号量.消息队列.共享内存.通信,是一个广义的意义,不仅仅指传递一些 message.进程通信就是指不同进程之间进程数据共享和数据交换. [信号和信号量] 信号和信号量是不同的,他们虽然都可用来实现同步和互斥,但信号是

进程间的通信方式汇总

最近在设计一个多进程的系统,主进程和子进程的通讯和调用方式是其中的一个关键问题,程序需要考虑跨平台和跨语言,后台守护进程和UI界面,子进程管理等,对可靠性要求高,还是很复杂的.今天掰一掰进程间通信的问题 # 命令行参数和返回值调用,最直接的方法 跨平台和跨语言应该OK # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. windows下管道不好用吧 # 有名管道 (named pipe) : 有名管道也

Android(IPC)进程间通讯1:详解Binder由来?

完整原文:http://tryenough.com/android-ipc1 Android开发的进程间通讯,整个Android的应用都依赖于binder做底层通信机制.而Linux中提供的进程间通讯方式并没有binder机制,那么android中为什么要单独创造这种通讯方式呢?带着这个问题,继续往下读. Linux中进程相关概念 Linux将系统内存划分成了 用户空间 和 内核空间 两部分: 用户空间 : 普通应用程序则运行在用户空间上,它们不能使用某些特定的系统功能,不能直接访问硬件,不能直

ACE框架 基于共享内存的进程间通讯

ACE框架将基于共享内存的进程间通讯功能,如其它IO组件或IPC组件一样,设计成三个组件.流操作组件ACE_MEM_Stream,连接器组件ACE_MEM_Connector,以及接收连接组件ACE_MEM_Accpter.ACE框架为基于共享内存的进程间通讯提供了两种数据传输(分发deliver)策略.一种是使用生产者-消费者队列的一对多的多用户MT策略,另一种是使用socket流的可以使用反应器响应数据接收事件的Reactor策略.不论哪一种策略都要通过socket进行TCP连接,并进行进程

Android进阶笔记04:Android进程间通讯之Messenger ( 区别于AIDL)

一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽.哈哈.此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信:甚至作为一个转接处,任意两个进程都能通过服务端进行通信. (2) Messenger 与 AIDL 比较:    

进程间同步(1)——条件变量和互斥量

1. 概述 条件变量和互斥量是最基本的同步形式,总是用于同步同一个进程的各个线程间同步. 当把条件变量或互斥量放在共享内存区时,可用于进程间同步. 同样的情况还有读写锁,它们都是随进程的持续性.   2.互斥锁 互斥锁指代相互排斥,用于保护临界区.多个线程和多个进程分享的共享数据. 静态初始化:static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 动态初始化:互斥锁是动态分配的,pthread_mutex_init(&mutex);初始