进程组与作业、会话之间的关系

一、进程组、作业、会话 1.进程组(process group) 每个进程除了有一个进程ID(保存在PCB当中),还属于一个进程组。进程组由一个或多个进程组成,通常和一个作业相关联,可以接收来自同一终端的各种信号。每个进程组有一个唯一的进程组ID。 每个进程组都有一个组长进程,组长进程的ID等于组ID。 组长进程可以组建一个进程组。只要进程组中有一个进程存在,这个进程组就存在。 2.作业(job) 当命令行上运行一个进程时,就会变成一个作业,这个作业可能是一个进程,也可能是多个进程。 shall有且只能运行一个前台作业,当前台有作业时,就不会运行其他作业,shell在后台运行(此时不能接收指令),当作业终止,shall被提到前台,可以接收指令 shell分前后台来控制的不是进程而是作业或者进程组。一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成。shell可以运行一个前台作业和任意多个后台作业。(作业控制) *作业和进程组区别:如果作业中某个进程又创建子进程(fork),则子进程不属于作业,属于进程组。一旦前台作业运行结束,shell就把自己提到前台,若原来前台进程还在(子进程还没终止 ),则自动变为后台进程组 3.会话(session ) 会话是一个或多个进程组的集合。一个会话可以有一个控制终端。建立与控制终端连接的会话首进程被称为控制进程(一般bash就是控制进程)。一个会话中几个进程组可被分为一个前台进程组和一个或多个后台进程组。 一个会话中,应该包括控制进程(会话首进程)、一个前台进程组和任意后台进程组。 ctrl+c(SIGINT信号),ctrl+(SIGQUOT),ctrl+Z(SIGTSTP)内核发送相应的信号给前台进程组中所有进程。 切换用户就是当前会话首进程起新进程组,每次su会加载新bash,每次打开终端也会新起一个bash

二、终端 1.基本概念 用户通过登录系统后获得一个shell进程,这个终端称为shell进程的控制终端,控制终端是保存在PCB中的信息。fork时会复制PCB中的信息,所以由shell进程启动的其他进程的控制终端也是这个终端。默认情况下(未重定向)每个进程的标准输入、标准输出和标准作物都指向控制终端。在控制终端输入一些特殊的控制键可给前台进程发送信号(ctrl+c 、ctrl+Z等) 每个进程都可通过一个特殊的设备文件/dev/tty访问控制终端例: 1.一个进程要访问它的控制终端可以通过dev/tty也可以通过该终端设备对应的设备文件来访问 2.ttyname函数可由文件描述符查看对应文件名。该文件描述符必须指向一个终端设备而不是任意文件。

2.终端的登陆 一个pc通常只有一套键盘和显示其,也就是只有一套终端设备,但可以通过Ctrl+Alt+F1~F6 切换到6个字符终端,相当于有6套虚拟终端设备,它们共同用一套物理终端设备,对应的设备文件为/dev/tty1~/dev/tty6 登陆过程: 1.系统启动,init进程根据配置文件确定打开那些终端 2.getty根据命令行参数打开终端设备作为它的控制终端,把文件描述符0、1、2指向控制终端,然后提示用户输入账号,当用户账号输后,getty任务完成。 3.lofin程序提示用户输入密码(输入密码期间关闭终端回显),然后验证账号密码的正确性。若密码错误,login进程终止,init重新fork/exec一个getty,继续步骤2;若正确,login设置一些环境变量,设置当前工作目录为该用户主目录,然后执行shell 4.execl函数启动bash,在bash前加“-”表示bash作为shell启动,执行shell脚本 *getty->exec->login->execl->bash

三、作业控制 1.Session与进程组 shell可以同时运行一个 作业/进程组 和任意多个后台 作业/进程组,这称为作业控制。一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成。例: 启动5个进程: proc1 | proc2 & proc3 | proc4 | proc5 其中:1.proc1和proc2属于同一个后台进程组(&表示后台运行),proc3、proc4、proc5属于同一个前台进程组。shell进程属于一个单独的进程组。 2.这些进程控制终端相同,属于同一个session。 3.当用户在控制终端输入特殊的控制键(ctrl+c等),内核发送相应的信号给前台进程。

2.从session核进程组的角度看终端过程 ①getty或telnetd进程打开终端设备之前调用setsid创建一个新session(该进程为session leader),该进程的id可以看做session的id,然后该进程打开终端设备作为这个session中所有进程的控制终端。。 ②登陆时,getty/telnetd变为login,然后变为shell,但仍是同一个进程,仍是session leader。 ③shell进程fork子进程(子进程和shell的session、进程组、控制终端相同),shell调用setgid函数将作业中某个子进程指定为一个新进程组leader,然后将该作业中其他子进程也转移到这个进程组中。 若进程组需要在前台运行,就调用tcsetgrp函数将它设置为前台进程组。由于一个session只能有一个前台进程组,所以shell所在的进程组自动变为后台进程组。shell调用wait等待前台进程运行结束,一旦结束shell调用tcsetgrp函数将自己提到前台继续接受命令。 注意:若前台进程某个进程又fork出子进程, 这个子进程 虽然属于这个进程组但是不属于这个作业,shell不知道子进程存在,所以不会调用wait等待它结束。所以前台作业运行结束,shell自动到前台,这个子进程若没有终止,则自动变为后台。

3.与作业控制相关的信号 cat cat指令读标准输入(终端输入) jobs 查看当前有哪些作业

fg 进程号 将某个作业提到前台运行,若改作业的进程组正在后台运行则提至前台运行,若该作业处于停止状态,则给该进程组每个进程发送SIGCONT信号使它继续运行

bg 让某个停止的作业在后台继续运行,也需要该作业的进程组每个进程发送SIGCONT信号,cat继续运行,但是cat需要读终端输入,然而后台不能读所以收到SIGTTIN信号终止

*注意:kill命令可以给一个停止的进程发SIGTERM信号,这个信号不会立即处理,而是等进程准备继续运行之前处理,默认动作是终止。若给一个停止的信号发SIGKILL信号则立即处理 SIGKILL信号即不能被阻塞也不能被忽略,也不能自定义捕捉函数,只能立即处理,SIGSTOP信号同STOPKILL信号。

四、守护进程 1.概要 守护进程也成精灵进程(daemon),是指在后台运行的一种特殊进程。独立于控制终端并周期性的执行某种任务或等待处理某些发生的事件。 linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能喝用户交互,其他进程都是在用户登录或运行程序时创建,在运行结束或者用户注销时终止,但系统服务进程不受用户注销影响,它们一直运行,这种进程就是守护进程。 ps axj 可以查看系统中的进程 a表示不仅列出当前用户进程,也列出所有其他用户的进程 x表示不仅列出控制终端的进程,也列出所有无控制终端的进程 j表示列出与作业控制相关的信息

\

上图中 ①TPGID为-1表示没有控制终端的进程,即守护进程 ②COMMAND用[]括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,所以没有程序文件名和指令行 ③COMMAND中k开头的表示kernel ④守护进程通常以d结尾(daemon) 2.创建守护进程 创建守护进程: 1.调用umask将文件模式创建屏蔽字设置为0 2.调用fork,父进程退出(原因:①若该守护进程作为一条简单的shell命令启动,则父进程终止使shell认为该命令执行完毕。②保证子进程不是进程组的组长进程) 3.调用setsid创建一个新会话(①调用进程成为新会话首进程。②调用进程称为组长进程。③调用进程没有控制终端) 4.当前共工作目录改为根目录 5.关不不需要的文件描述符 6.忽略SIGCHLD信号。 创建守护进程最关键的是调setsid函数创建新session,并成为session leader

函数调用成功返回新创建的session的id(即当前进程的id),出错返回-1. 当调用这个函数之前,当前进程不允许是进程组的leader,否则返回-1.(先fork再调用setsid,fork创建的子进程和父进程在同一个进程组中,leader一般是该组的第一个进程,所以这个子进程一定不是leader) 调用成功: ①创建一个新session,当前进程称为session leader,当前进程id是session id ②创建一个新的进程组,当前进程成为进程leader,当前进程id就是进程组id ③若当前进程原本有一个控制终端,则它失去这个控制终端(原来的控制终端仍打开,仍可以读写但是只是一个普通的打开文件而不是控制终端),成为一个没有控制终端的进程。

猜你喜欢

转载自blog.csdn.net/qq_39539470/article/details/80369815
今日推荐