终端

概念

在UNIX系统中,用用户通过终端登录系统后得到一一个Shell进程,这个终端成为Shell进程的控制终端 (Controlling Terminal),控制终端是保存在PCB中的信息,而我们知道fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端。

默认情况 下(没有重定向),每个进程的标准输入、标准输出和标准错误输出都指向控制终端,进程从标准输入读也就是读用户的键盘输入,进程往标准输出或标准错误输出写也就是输出到显示示器上。此外 在控制终端输入一些特殊的控制键可以给前台进程发信号,例如Ctrl-C表 示示SIGINT。

每个进程都可以通过一个特殊的设备文件/dev/tty访问它的控制终 端。事实上每个终端设备都对应一个不同的设备文件,/dev/tty提供了一一个通用的接口,一个进程要访问它的控制终端既可以通过/dev/tty也可以通过该终端设备所对应的设备文文件来访 问。

ttyname函数可以由文件描述符查出对应的文件名,该文件描述符必须指向一个终端设备而不能是任意文件。

下面我们来验证:

下面是验证代码:

得到的结果是:

由结果我们可以看出

文件描述符:0(标准输入),1(标准输出),2(标准错误)的文件都在同一个终端下。

如果我们重新开一个终端,再次运行上面的代码,得到结果为:

进程组

概念

每一个进程除了有一个进程ID外,还属于一个进程组。

进程组是一个或多个进程的集合,通常情况下,他们是在同一作业中结合起来的,同一进程组的个进程接受来自同一终端的各种信号。

每一个进程组有一个唯一的进程ID。

进程组ID是一个正整数,可以使用getpgrp函数返回调用进程的进程组ID

#include

pid_t getpgrp(void);

组长进程

每个进程组都有一个组长进程,组长进程的进程组ID等于其进程ID。

进程组组长可以创建一个进程组,创建进程组中的进程然后种植。只要进程组中还有任意一个进程存在,那么这个进程组就存在。

从进程组的创建到最后一个进程离开的时间去成为进程组的生命周期。

进程组验证

首先我们编写验证进程组的代码:

在上面的代码中,我们首先创建两个进程,一个father父进程,一个child子进程,我们让father和child首先输出自己的pid,然后循环输出自己进程名称。

结果如下:

由结果我们看出,父进程pid为3306,子进程pid为3307,然后父子进程循环打印father,child。

重新打开一个终端,输入命令

ps -axj | grep "proc_rela"

首先我介绍一下各个标识的意义。

PID(Process ID 进程 ID号)

Linux系统中总是会分配一个号码用于在其命名空间中唯一地标识它们,即进程ID号(PID),用fork或者cline产生的每个进程都由内核自动地分配一个新的唯一的PID值

TPGID(显示前台进程组)

TGID(Thread Group ID 线程组 ID号)

处于某个线程组(在一个进程中,通过标志CLONE_THREAD来调用clone建立的该进程的不同的执行上下文)中的所有进程都有统一的线程组ID(TGID)

如果进程没有使用线程,则它的PID和TGID相同

线程组中的”主线程”(Linux中线程也是进程)被称作”组长(group leader)”,通过clone创建的所有线程的task_struct的group_leader成员,都会指向组长的task_struct。

在Linux系统中,一个线程组中的所有线程使用和该线程组的领头线程(该组中的第一个轻量级进程)相同的PID,并被存放在tgid成员中。只有线程组的领头线程的pid成员才会被设置为与tgid相同的值。注意,getpid()系统调用

返回的是当前进程的tgid值而不是pid值。

我们可以这么理解

对于一个多线程的进程来说,它实际上是一个进程组,每个线程在调用getpid()时获取到的是自己的tgid值,而线程组领头的那个领头线程的pid和tgid是相同的

对于独立进程,即没有使用线程的进程来说,它只有唯一一个线程,领头线程,所以它调用getpid()获取到的值就是它的pid

PGID(Process Group ID 进程组 ID号)

每个进程都会属于一个进程组(process group),每个进程组中可以包含多个进程。进程组会有一个进程组领导进程 (process group leader),领导进程的PID成为进程组的ID (process group ID, PGID),以识别进程组.

PPID( Parent process ID 父进程 ID号)

PPID是当前进程的父进程的PID

SID(Session ID 会话ID)

STAT(状态栏)

D 不可中断 Uninterruptible sleep (usually IO)

R 正在运行,或在队列中的进程

S 处于休眠状态

T 停止或被追踪

Z 僵尸进程

W 进入内存交换(从内核2.6开始无效)

X 死掉的进程

< 高优先级

N 低优先级

L 有些页被锁进内存

s 包含子进程

+ 位于后台的进程组;

l 多线程,克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)

得到结果:

下面我们分析一下结果:

由程序输出结果我们已经得到,父进程的进程ID为3235,子进程的进程ID为3236。

于是我们看到第一个进程PID = 3235,为父进程,他的PGID为3235,就是他本身,即:

父进程就是进程组组长进程。

关于STAT位的意义在上面STAT有提到,所有标志相结合即可。

总结:

程序创建了一个进程,该进程又创建了子进程,于是父进程和子进程构成了一个进程组,进程组的组长为父进程。

那么如果父进程结束,子进程不结束,进程组存在不存在呢?

下面我们修改代码:

这次,我们让父进程创建子进程后就退出,当然父进程依然是组长进程,当父进程退出后,子进程依然在进行。

可以看到,子进程还在运行,并且组长进程ID就是父进程ID。

但是,即使子进程继续运行,我们还是可以在shell输入,并且ctrl+C键不能结束子进程,原因是什么呢?

这就是我下面要介绍的:

作业

Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。一个前台作业可以由多个进程组成,一个后台也可以由多个进程组成,Shell可以运行一个前台作业和任意多个后台作业,这称为作业控制。

作业与进程组的区别:

如果作业中的某个进程又创建了子子进程,则子子进程不属于作业。一旦作业运行行结束,Shell就把自己提到前台,如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。

shell中运行的是作业,当父进程创建了子进程后,虽然子进程属于进程组,但是子进程不属于当前作业 ,所以当父进程退出的时候,当前作业也随之结束掉了。子进程就到后台进行。然后当前作业就变成bash,我们可以输入命令。因为此时子进程在后台,所以我们给他发送ctrl+C信号,他接收不到。所以无法停止,我是用kill命令结束子进程的。

会话

会话(Session)是一个或多个进程组的集合。

一个会话可以有一个控制终端。这通常是登陆到其上的终端设备(在终端登陆情况下)或伪终端设备(在网络登陆情况下)。建立与控制终端连接的会话首进程被称为控制进程。

一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。所以一个会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组。

无论何时键入终端的终端键,都会将中断信号发送到前台进程组的所有进程

作业控制

作业控制允许在一个终端上启动多个作业(进程组),他控制哪一个作业可以访问该终端以及哪些作业在后台运行。

如上图,我们输入两个命令,可以看出,输入第一个命令时:

ps,cat进程同属于一个进程组,组长为ps,bash,ps,cat三个进程属于一个会话,Learder是bash。

当输入第二个命令时,在命令后在&符号,表示该进程在后台运行,[1]是作业编号,4439是该作业中某一个进程的ID,很明显,在上例中,4439是cat进程。

作业控制与三个信号

SIGINT(Ctrl + C)——中断字符

SIGQUIT(Ctrl +\)——退出字符

SIGTSTP(Ctrl + Z)——挂起字符

linux 进程组id 错乱,【Linux】终端,进程组,作业,会话及作业控制相关推荐

  1. Linux进程ID号--Linux进程的管理与调度(三)

    进程ID概述 进程ID类型 要想了解内核如何来组织和管理进程ID,先要知道进程ID的类型: 内核中进程ID的类型用pid_type来描述,它被定义在include/linux/pid.h中 enum ...

  2. linux孤儿进程组深入理解,LInux下僵尸进程与孤儿进程是如何产生的?

    1:如何产生: 僵尸进程,先于父进程终止,但是父进程没有对其进行善后处理(获取终止子进程有关信息,释放它仍占有的资源).消灭僵尸进程的唯一方法是终止其父进程. 孤儿进程:该进程的父进程先于自身终止.其 ...

  3. 嵌入式Linux系统编程学习之十二守护进程

    文章目录 前言 一.守护进程的特性 二.daemon 进程的编程规则 1.创建子进程,父进程退出 2.在子进程中创建新会话 前言   daemon 运行在后台,也称作"后台服务进程" ...

  4. Linux多任务编程之七:Linux守护进程及其基础实验(转)

    来源:CSDN  作者:王文松  转自Linux公社 ------------------------------------------------------------------------- ...

  5. linux进程管理内存管理,Linux专业知识四:Linux系统进程管理及查看内存

    本文主讲Linux专业知识之Linux系统进程管理及查看内存的情况,以Redhat RHEL7操作系统为例. 一.进程 程序与进程:程序是静态的(文件),进程是动态的(运行的程序). 进程和线程:一个 ...

  6. linux mysql 进程查看工具_linux查看正在运行的进程(如何在Linux中查看所有正在运行的进程)...

    如何在Linux中查看所有正在运行的进程 名称:ps 使用权限:所有使用者 使用方式:ps [options] [--help] 说明:显示瞬间行程 (process) 的动态 参数:ps的参数非常多 ...

  7. linux中把程序启到前台,Linux操作系统桌面应用与管理Q4rw2进程与作业管理-PPT精品文档.ppt...

    红旗Linux,情境四任务2:进程和作业管理,任务2-1,了解进程管理知识用命令实现进程管理,Linux进程管理,WINDOWS?任务管理器LINUX利用命令管理进程包括前.后台进程的管理以及终止等, ...

  8. linux查看守护进程格式,详解Linux中的守护进程

    一.什么是守护进程 Linux系统启动时会启动很多系统服务进程,这些系统服 务进程没有控制终端,不能直接和用户交互.其它进程都是在用户登录或运行程序时创建,在运⾏结束或⽤户注销时终止,但系统服务进程不 ...

  9. linux ps -ef哪一位是进程号,Linux ps 命令详解

    (此文章为收集网络IT达人们博文中有用信息后,整理出来的,感谢他们)(PS:追加感谢 by lxrm) ps  aux详细解释ps aux 显示其他用户启动的进程(a) 查看系统中属于自己的进程(x) ...

最新文章

  1. for each .. in ,for ... in , for ... of的用法
  2. 善于 调用Windows API
  3. 第七周实践项目5 排队看病模拟(队列)
  4. 用神经网络分类连续与离散
  5. java int数列转字符串,鍥剧墖杞瓧绗︿覆
  6. 软设考试笔记--数据流图
  7. 如何删除 Windows.old 文件夹
  8. C#中多线程和定时器是不是有冲突?
  9. Java8 Optional类
  10. 自我介绍(老师作业,大神自行忽略)
  11. Android and Apple 投屏至linux电脑
  12. .net面试问答(大汇总)(转)
  13. VC dxgi 截屏保存bmp文件
  14. LeetCode刷题第5周小结
  15. 华为鸿蒙麒麟玉兔_鸿蒙、麒麟、鲲鹏……这是属于中华的浪漫
  16. 笔记本计算机没有没有显示无线网络连接,笔记本没有无线网络连接,教您笔记本没有无线网络连接...
  17. 计算机应用英语app,学英语必备的9款APP,学生党都在用
  18. 天眼查python_GitHub - wagaman/Python-Tianyancha: 天眼查爬虫
  19. 全球最值得听的100首英文歌
  20. 从汇编到太空——保罗·艾伦

热门文章

  1. 为您的下一个基于Spring的应用程序考虑使用spring-boot的原因!
  2. 番石榴条纹类的细粒度并发
  3. 您好GroovyFX
  4. Spring Security使用Hibernate实现自定义UserDetails
  5. android官方文档中文版_最全实至名归,NumPy 官方早有中文教程,结合深度学习,还有防脱发指南...
  6. WPS for MacOS如何设置自动句首字母大写
  7. 混合模式商城的可经销商品池
  8. 人生永无止境的意思是什么_励志人生:生活不会给任何脆弱鼓掌。
  9. java大文件解析_java大文件(百M以上)的上传下载实例解析
  10. aspose word 获取标题_Word干货|多级标题的自动编号怎么添加?