Linux下的进程间关系

11人阅读 评论(0) 收藏 举报
分类:

进程组
在linux中,每一个进程还属于一个进程组,一个进程组有多个进程组成,通常,他们联合起来作业,可以接受从同一个终端下的各种信号。并且每一个进程组都有一个进程组ID。在Linux中叫做PGID,一个进程组由多个进程组成,进程组中有一个组长进程,组长进程的标识是他的进程ID和组ID相同。一般一个进程组中第一个创建的进程就是组长进程。一个进程组中只要还有一个进程存在,那么这个进程组就存在。
我们可以通过ps 命令,来查看进程信息。
-a 列出所有用户的进程
-x 不仅列出有终端控制的,也列出没有终端控制的进程。
-j列出与作业控制相关的信息

这里写图片描述
PID:进程ID
PPID:父进程ID
PGID:所属进程组的ID
SID:会话ID
TTY:相关控制终端


作业
Shell分前后台来控制的不是进程而是作业或者叫做进程组,Shell可以运行一个前台作业和任意多个后台作业,这就叫做作业的控制。
作业和进程组的区别:如果一个进程组中的某个进程fork出来了子进程,那么子进程属于进程组,而不属于作业。
现在我们就可以理解为什么当我们运行一个进程之后,再输入命令,就没有作用了,原因就是因为让我们启动一个作业以后,默认是放在前台的,而前台只能有一个进程,因此Shell就被提到后台了,无法接受我们的指令。

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5     pid_t pid;
  6     if(pid=fork()==0)
  7     {
  8         //child
  9        while(1)
 10        {
 11            printf("hello, world\n");
 12            sleep(2);
 13        }
 14  
 15     }
 16     else
 17     {
 18         sleep(5);
 19     }
 20                                                                                                                                                                                                              
 21     return 0;
 22 }

来看一下结果:
这里写图片描述
输入./a.out按下回车,就会在前台起一个作业,父进程sleep(5)秒,在这5秒期间,Shell被提到后台,无法接受我们输入的指令,五秒之后,父进程退出,那么Shell变成前台作业,可以接受我们的ls指令,子进程属于进程组但是不属于作业,因此它在后台一直向屏幕上打印hello,world。


会话
会话是由一个或者多个进程组的集合,一个会话可以有一个控制终端,这通常是登陆到其上的终端设备(终端登陆情况下)和伪终端情况(xshell网络登陆),建立与终端控制的会话首进程我们称之为控制进程,一般为bash,一个会话的进程组可以分为一个前台进程和任意多个后台进程,所以一个会话包括一个控制进程(会话首进程),一个前台进程组和任意多个后台进程组


作业控制
事实上,Shell分前后台来控制的不是进程而是作业,Shell可以运行一个前台作业和任意多个后台作业,这就叫做作业控制。

  1. 在启动程序的时候,和后面跟上&选项表示把进程放在后台运行。
  2. jobs命令可以查看后台作业
  3. fg+作业编号,就可以把后台作业提到前台。
  4. 一个前台进程我们也可以用ctrl+z让他变成stop状态放在后台,然后再用bg命令让它运行起来。此时还是在后台
  5. ctrl+c只能结束掉前台作业。
    下面来看一个例子,在前台新起一个作业cat,它的作用是从标准输入中读取数据,然后输出到标准输出中
    这里写图片描述
    当我们把cat放到后台运行时,再查看它的状态
    这里写图片描述
    此时cat的状态变成stopped,为什么会这样呢,原因是bash不允许后台进程从标准输入中读取数据,就会给cat发送一个SIGTTIN信号,该信号的默认处理动作是让进程停止。但是后台进程是运行写的。前面我们写的一个小程序子进程就是后台作业,一直再向屏幕上写,验证了这一点,当我们尝试给一个停止的进程发送信号的时候,并不会立即处理,而是等到进程运行起来的时候,才会去处理。但是linux中有强大的9号信号,可以插死除了僵尸进程之外的各种状态进程。

守护进程
守护进程也叫做精灵进程,是在运行期间的一种特殊的进程,它独立于控制终端并且周期性的执行某种任务或者等待某些事件的发生,这是一种很有用的进程,再linux中很多的服务都是由守护进程实现的,比如,http服务器,ssh服务器,Web服务器,守护进程完成着很多的系统任务,比如说作业规划进程crond。
linux系统启动的时候有很服务进程启动,这些进程没有控制终端,无法和用户进行交互,其他进程都是在用户登陆或者程序运行时创建,在运行结束或者用户注销的时候终止,但是守护进程不受用户登陆和注销的影响,他们一直在运行。
通过ps -ajx|more来查看守护进程
这里写图片描述

  • 凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。
    -在COMMAND一栏中用[]括起来的表示内核线程,没有用户态代码,因此没有程序文件名和命令行,通常以K开头的表示kernal。
    -我们可以看出来,守护进程通常是以d结尾的,表示Daemon。

创建守护进程
创建守护进程用setsid函数创建一个新的Session,并成为Session Leader。

  #include<unistd.h>
  setsid(void);    

这个函数成功调用新的Session的id,也就是当前进程的id,出错返回-1
注意:调用这个函数之前,当前进程不允许是所属进程组的组长,否则调用出错,必须要出子进程,然后再调用setsid,这是因为fork出子进程,子进程也属于这个进程组,但肯定不是组长进程,因为守护进程自成一个进程组,它的ID肯定是组长ID,如果创建它的进程是组长进程,那么再内核中就会有两个ID一样的进程中,这是错误的。
这个函数调用成功的结果是:

  1. 创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id,即自成一个会话
  2. 创建一个新的进程组,并且自成组长
  3. 如果当前进程有一个控制终端,那么它将会失去这个控制终端,没有控制终端
    基于上面几点,我们来自己写一个守护进程
  1 #include<stdio.h> 
  2 #include<sys/types.h>             
  3 #include<sys/stat.h>              
  4 #include<signal.h>
  5 #include<fcnatl.h>
  6 #include<stdlib.h>
  7 #include<unistd.h>
  8          
  9         
 10 void mydaemon()
 11 {       
 12     umask(0);//文件创建模式的屏蔽字设为0
 13     pid_t pid;
 14     if(pid=fork()==0)             
 15     {   
 16         //child
 17         //三个重定向              
 18       setsid();
 19       signal(SIGCHLD,SIG_IGN);    
 20         
 21         //忽略SIGCHLD信号         
 22         if(chdir("./")<0)         
 23         {     
 24             perror("chdir\n");    
 25             exit(0);              
 26         }//更改当前工作目录为根目录
 27         close(0); 
 28         int fd=open("/dev/null",O_RDWR);
 29         dup2(fd,1);
 30         dup2(fd,2);
 31     }   
 32     else
 33     {   
 34         //father
 35         exit(0);
 36     }   
 37 }       
 38  int main()   
 39 {       
 40         
 41     mydaemom();
 42 while(1);
 43         
 44         
 45 return 046 }

看看结果:
这里写图片描述
这是我们根据守护进程的特性,自己模拟实现的一个创建守护进程的函数,当然有封装好的接口拱我们使用。

  1 #include<unistd.h>
  2 daemon(0,0);      

daemon()函数也是必须fork出子进程才可以调用,这里两个参数默认都是0,表示更改进程默认打开的三个文件描述符,和更改进程的工作目录。

查看评论

进程间关系和守护进程

进程间关系和守护进程 一、进程组(Process Group) 每个进程除了进程ID以外还属于一个进程组,进程组是一个或者多个进程的集合,通常与同一作业相关联,可以接受同一个终端的各种信号,每个进...
  • DY_1024
  • DY_1024
  • 2018-02-06 21:48:51
  • 66

进程以及进程间关系

进程是现代操作系统最为深刻的概念之一,它提供了运行中程序的抽象。一个进程指的是正在内存中运行的一个程序,任何程序都运行在进程的上下文中,进程的上下文包括虚拟的地址空间、独占的cpu以及寄存器等系统状态...
  • Repaint_The_World
  • Repaint_The_World
  • 2015-10-04 18:22:53
  • 320

运行中的Nginx进程间的关系

第2章 Nginx的配置 Nginx拥有大量官方发布的模块和第三方模块,这些已有的模块可以帮助我们实现Web服务器上很多的功能。使用这些模块时,仅仅需要增加、修改一些配置项即可。因此,本章的目的...
  • ai2000ai
  • ai2000ai
  • 2016-09-18 14:10:31
  • 460

进程间关系

Linux的进程相互之间有一定的关系。比如说,在Linux进程基础中,我们看到,每个进程都有父进程,而所有的进程以init进程为根,形成一个树状结构。我们在这里讲解进程组和会话,以便以更加丰富的方式了...
  • u011068464
  • u011068464
  • 2013-09-07 23:39:01
  • 454

nginx源码分析--nginx进程间通信

Linux下的IPC很多,nginx的进程都是有亲缘关系的进程,对于他们的通信我们选择TCP socket进行通信。   TCP socket 用来做进程通信的好处有,   1.socket是文件描述...
  • yusiguyuan
  • yusiguyuan
  • 2014-11-15 07:50:01
  • 1399

workerman 进程间关系

最近在看workerman 的源码,以加深对进程管理,信号量机制,网络编程方面的理解,workerman 进程间的个关系如下。...
  • a930716
  • a930716
  • 2018-01-18 15:43:04
  • 112

进程间关系与守护进程

       在我们学习完进程和线程之后,我们知道进程与进程之间是相互独立的,而线程与线程之间是有一定的联系的。那么进程与进程之间就真的没有关系吗?接下来就来学习一下进程间关系以及一个新的名词守护进程...
  • weixin_38175489
  • weixin_38175489
  • 2018-04-17 20:54:16
  • 11

Linux进程间关系之守护进程

概念守护进程也称精灵进程,是运行在后台的一种特殊进程。守护进程独立于控制终端并且周期性的执行某种任务或者等待处理某些打算的事件。可认为守护进程目的就是防止终端产生的一些信号让进程退出特点 所有的守护进...
  • LLZK_
  • LLZK_
  • 2017-02-27 16:05:56
  • 1177

进程、线程、端口间关系

进程是指在系统中正在运行的一个应用程序;线程是系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元。对于操 作系统而言,其调度单元是线程。一个进程至少包括一个线程,通常将该线程称为主线程...
  • xufeipeng
  • xufeipeng
  • 2013-06-14 09:18:00
  • 3309

Linux进程间关系之进程组,作业,会话与作业控制。

本片博客用到的相关指令fg,bg,jobs,ps等可自行查阅。进程组每个进程除了有一个进程ID之外还有一个进程组ID。每个进程都属于一个进程组。进程组是一个或多个进程的集合。每个进程都有一个唯一的进程...
  • LLZK_
  • LLZK_
  • 2017-02-27 13:22:57
  • 596
    个人资料
    持之以恒
    等级:
    访问量: 2050
    积分: 304
    排名: 25万+
    文章分类
    最新评论