Linux中的进程组、作业以及会话

来源:互联网 发布:网络机顶盒刷机包下载 编辑:程序博客网 时间:2024/05/21 14:44
进程组  
 
每个进程除了有一个进程ID之外,还属于一个进程组。进程组是一个或多个进程的集合。 通常,它们与同一作业相关联,可以接收来自同一终端的各种信号。每个进程组有一个唯 一的进程组ID。每个进程组都可以有一个组长进程。组长进程的标识是,其进程组ID等于其进程ID。 组长进程可以创建一个进程组,创建该组中的进程,然后终止。只要在某个进程组中一个进程存在,则该进程组就存在,这与其组长进程是否终止无关

第一个进程,都是组长进程

作业   
 
Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。一个前台作业可以由多个进程组成,一个后台也可以由多个进程组成,Shell可以运行一个前台作业和任意多个后台作业,这称为作业控制。
    
作业与进程组的区别:如果作业中的某个进程又创建了子进程,则子进程不属于作业。一旦作业运行结束,Shell就把自己提到前台,如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。

一个作业:


运行结果:


父进程退出,但是子进程一直在运行(父进程结束,shell调到前台,但是子进程没有终止,又把自己调到后台)

会话

会话(Session)是一个或多个进程组的集合。
一个会话可以有一个控制终端。这通常是登陆到其上的终端设备(在终端登陆情况下)或伪终端设备(在网络登陆情况下)。建立与控制终端连接的会话首进程被称为控制进程。
一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。所以一个 会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组。    
1    $ proc1 | proc2 &               
2    $ proc3 | proc4 | proc5           
其中proc1与proc2属于同一个后台进程组,proc3,proc4和proc5属于同一个前台进程组, Shell本身属于一个单独的进程组。这些进程组的控制终端相同,它们同属于一个会话,当用户在控制终端输入特殊的控制键(如Ctrl+C,产生SIGINT,Ctrk+\,产生SIGQUIT,Ctrl+Z, 产生SIGTSTP),内核发送相应的信号给前台进程组中的所有进程。

终端也就是一个文件

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

查看终端对应的设备:

在两个终端中运行的结果:


守护进程(精灵进程)
守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。

创建守护进程最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader。
该函数调用成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进 程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进 程组中,进程组的Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个 进程,在子进程中调用setsid就不会有问题了。

创建守护进程 
1. 调用umask将文件模式创建屏蔽字设置为0.
2. 调用fork,父进程退出(exit)。原因:1)如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得shell认为该命令已经执行完毕。2)保证子进程不是一个进程组的组长进程
3. 调用setsid创建一个新会话。setsid会导致:1)调用进程成为新会话的首进程。 2)调用进程成为一个进程组的组长进程 。3)调用进程没有控制终端。(再次fork一次,保证daemon进程,之后不会打开tty设备)
4. 将当前工作目录更改为根目录。
5. 关闭不在需要的文件描述符。
6. 其他:忽略SIGCHLD信号。


运行结果:


fork两次进程,让孙子进程做守护进程,为什么?


fork第二次主要目的是。防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次,孙子进程ID != sid(sid是进程子进程的sid)。所以也无法打开新的控制终端。

终止子进程 保证孙子进程 不是话首 进程 从而保证此后不会再和其他终端关联


也可以直接调用系统函数来创建守护进程:int daemon(int nochdir, int noclose);




0 0
原创粉丝点击