聊城做网站低费用,手机网站如何排版,深圳兼职做网站,做维修广告在哪个网站终端概念在UNIX系统中,用用户通过终端登录系统后得到一一个Shell进程,这个终端成为Shell进程的控制终端 (Controlling Terminal),控制终端是保存在PCB中的信息,而我们知道fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端。默认情况 下(没有重定向)…终端概念在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#includepid_t getpgrp(void);组长进程每个进程组都有一个组长进程组长进程的进程组ID等于其进程ID。进程组组长可以创建一个进程组创建进程组中的进程然后种植。只要进程组中还有任意一个进程存在那么这个进程组就存在。从进程组的创建到最后一个进程离开的时间去成为进程组的生命周期。进程组验证首先我们编写验证进程组的代码 在上面的代码中我们首先创建两个进程一个father父进程一个child子进程我们让father和child首先输出自己的pid然后循环输出自己进程名称。结果如下 由结果我们看出父进程pid为3306子进程pid为3307然后父子进程循环打印fatherchild。重新打开一个终端输入命令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()获取到的值就是它的pidPGID(Process Group ID 进程组 ID号)每个进程都会属于一个进程组(process group)每个进程组中可以包含多个进程。进程组会有一个进程组领导进程 (process group leader)领导进程的PID成为进程组的ID (process group ID, PGID)以识别进程组.PPID( Parent process ID 父进程 ID号)PPID是当前进程的父进程的PIDSID(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输入并且ctrlC键不能结束子进程原因是什么呢这就是我下面要介绍的作业Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。一个前台作业可以由多个进程组成,一个后台也可以由多个进程组成,Shell可以运行一个前台作业和任意多个后台作业,这称为作业控制。作业与进程组的区别:如果作业中的某个进程又创建了子子进程,则子子进程不属于作业。一旦作业运行行结束,Shell就把自己提到前台,如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。shell中运行的是作业当父进程创建了子进程后虽然子进程属于进程组但是子进程不属于当前作业 所以当父进程退出的时候当前作业也随之结束掉了。子进程就到后台进行。然后当前作业就变成bash我们可以输入命令。因为此时子进程在后台所以我们给他发送ctrlC信号他接收不到。所以无法停止我是用kill命令结束子进程的。会话会话(Session)是一个或多个进程组的集合。一个会话可以有一个控制终端。这通常是登陆到其上的终端设备(在终端登陆情况下)或伪终端设备(在网络登陆情况下)。建立与控制终端连接的会话首进程被称为控制进程。一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。所以一个会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组。无论何时键入终端的终端键都会将中断信号发送到前台进程组的所有进程作业控制作业控制允许在一个终端上启动多个作业(进程组)他控制哪一个作业可以访问该终端以及哪些作业在后台运行。 如上图我们输入两个命令可以看出输入第一个命令时ps,cat进程同属于一个进程组组长为psbash,ps,cat三个进程属于一个会话Learder是bash。当输入第二个命令时在命令后在符号表示该进程在后台运行[1]是作业编号4439是该作业中某一个进程的ID很明显在上例中4439是cat进程。作业控制与三个信号SIGINT(Ctrl C)——中断字符SIGQUIT(Ctrl \)——退出字符SIGTSTP(Ctrl Z)——挂起字符