每一个进程除了有个进程id外,还属于一个进程组。进程组是一个或者多个进程的集合。一般他们与同一个做业相关联,能够接受来自同一终端的信号。进程组id等于其进程组长id。进程组的终止与进程组长是否存在无关,只要有一个成员进程存在,那么这个进程组就存在。linux
shell分先后台进行控制的不是进程而是做业或者进程组。一个前台做业能够由多个进程组成,一个后台做业也能够由多个进程组成。shell能够运行一个前台做业和多个后台做业,这称为做业控制。shell
做业与进程组的区别:若是一个做业中的某个进程建立了一个子进程,那么这个子进程不属于做业,但属于进程组。bash
会话是一个或者多个进程组的集合。session
一个会话能够有一个控制终端。创建与控制终端链接的会话首进程被称为控制进程。spa
注:经过管道方式实现一个做业任务。命令行
前两行:对比能够看出,两个sleep命令的PPID(父进程id:bash),PGID(进程组ID),SID(会话ID),TTY(终端)都是相同的。code
PID是不一样的,他们是一个进程组中的两个不一样进程。blog
将之与第三行对比,发现,各个项都是不一样的,特别是SID,TTY,TPGID(top PGID(前台进程组ID))都是不一样的。进程
ps -e 或 ps -o pid,ppid,session,tpgid, comm (其中session显示的sessionid, tpgid显示前台进程组id, comm显示命令名称)get
同时,咱们能够验证,SID会话ID是由每一个终端进行肯定的。
由这个图咱们更能够清晰的理解到,对于每个连续的命令执行流,其进程组/做业id是相同的。会话id则是终端相关的。
#include <stdio.h> #include <unistd.h> int main(int argc, char const *argv[]) { printf("fd: %d -> %s\n",0,ttyname(0) ); printf("fd: %d -> %s\n",1,ttyname(1) ); printf("fd: %d -> %s\n",2,ttyname(2) ); return 0; }
一、系统启动时,init进程根据配置文件/etc/inittab肯定须要打开哪些终端。例如配置文件中有
这样一行:
1:2345:respawn:/sbin/getty 9600 tty1
和/etc/passwd相似,每一个字段用用:号隔开。开头的1是这一一行行配置的id,一般要和tty的后缀一一致,配置tty2的那一一行行id就应该是2。第二二个字段2345表示示运行行级别2~5都执行行这个配置。最后一个字 段/sbin/getty 9600 tty1是init进程要fork/exec的命令,打开终端/dev/tty1,波特率 是9600(波特率只对串又口口和Modem终端有意义),而后提示示用用户输入入账号。中间的respawn字段表示示init进程会监视getty进程的运行行状态,一一旦该进程终止止,init会再次fork/exec这个命令,因此 咱们从终端退出登陆后会再次提示示输入入账号。
二、getty根据命令行行参数打开终端设备做为它的控制终端,把文文件描述符0、一、2都指向控制终 端,而后提示示用用户输入入账号。用用户输入入账号以后,getty的任务就完成了,它再执行行login程序:
execle("/bin/login", "login", "-p", username, NULL, envp);
三、若是密码不正确,login进程终止止,init会从新fork/exec一一个getty进程。若是密码正确,login程 序设置一一些环境变量,设置当前工工做目目录为该用用户的主目目录,而后执行行Shell:
execl("/bin/bash", "-bash", NULL);
从getty开始exec到login,再exec到bash,其实都是同一一个进程,所以控制终 端没变,文文件描述符0、一、2也仍然指向控制终端。因为fork会复制PCB信息,因此由Shell启动的 其它进程也都是如此。
1。getty或者telnetd调用setsid,设置会话id,在这个id的基础上开启终端,创建会话。同时建立一个进程组。且该进程是此终端下全部会话的控制终端。
2。登陆过程当中,进行exec替换。变为login,而后变为shell
3。当shell调用fork建立子进程进行工做时,调用setpgid将做业中的某个进程设置伪新的组进程,造成本会话内的一个做业流。
注:在做业中,若是某个进程建立新的子进程了,该子进程并不会做为做业内容而被等待。当真是做业完成时,做业就会退出。(进程组和做业的区别)。
关于做业的命令:
jobs查看当前系统执行做业
process & 将process做为后台做业执行。
bg 将做业改成后台执行
fg 将做业改成前台执行
参数的话, %1 表示做业号为1
lang@liang:~/linux/thread$ cat fsdf & [2] 6470 lang@liang:~/linux/thread$ fsdf
给一个须要写入终端的命令设置后台执行时,并不能成功。
这时咱们须要设置stty tostop 禁止后台进程写。而后才能成功