【LINUX】 会话 进程组 作业 终端

【进程组】 
进程组是一个或多个进程的集合。每个进程除了有一个进程ID之外,还属于一个进程组。 
每个进程组有一个唯一的进程组ID。每个进程组都可以有一个组长进程。
组长进程的进程组ID等于其进程ID。进程组是否存在和有无组长无关。
每个进程都是属于进程组的,没有独立的进程,除非该进程组中只有一个进程,则可以说这个进程是独立的。
组长进程可以创建一个进程组,创建该组中的进程,然后终止。
但是只要有一个进程存在,则这个进程组就存在,这与其组长进程是否终止无关。
通常,它们与同一作业相关联,可以接收来自同一终端的各种信号。

【作业】
Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。
(1)作业控制:
一个前台作业可以由多个进程组成,一个后台也可以由多个进程组成,
Shell可以运行一个前台作业和任意多个后台作业,这称为作业控制。
后台程序将不会被ctrl+c杀死
当我们再一个终端开了一个后台程序,关闭终端后,后台程序也就停了。
(2)作业与进程组的区别:
如果作业中的某个进程又创建了子进程,则子进程不属于作业,但是该子进程属于其进程组。
一旦作业运行结束,Shell就把自己提到前台,如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。

 【会话】 
会话(Session)是由多个作业或者进程组构成,是一个或多个进程组的集合。
一个会话可以有一个控制终端。这通常是登陆到其上的终端设备(在终端登陆情况下)或伪终端设备(在网络登陆情况下)。
建立与控制终端连接的会话首进程被称为控制进程。 
一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。
所以一个会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组。
打开一个终端,就是开始一个会话,再一个会话里运行一个进程,可以在别的终端查看其状态,当kill命令下达后,系统将其kill
查看终端设备
每个进程都可以通过一个特殊的设备文件/dev/tty访问它的控制终端。事实上每个终端设备都对应一个不同的设备文件,/dev/tty提供了一个通用的接口,一个进程要访问它的控制终端,既可以通过/dev/tty也可以通过该终端设备所对应的设备文件来访问。ttyname函数可以由文件描述符查出对应的文件名,该文件描述符必须指向一个终端设备而不 能是任意文件。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
 
int main()
{
printf("%d  ----> %d \n",0,ttyname(0));
printf("%d  ----> %d \n",1,ttyname(1));
printf("%d  ----> %d \n",2,ttyname(2));

return 0;
}
我的结果不是目录是一个地址:
0  ----> 140038152 
1  ----> 140038152 
2  ----> 140038152 
再开一个运行如下:
0 ----> 134569992 
1  ----> 134569992 
2  ----> 134569992 
  【守护进程】
守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。
守护进程是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。
 守护进程的特点:
(1)Linux系统启动时会启动很多系统服务进程,守护进程没有控制终端,不能直接和用户交互
(2)其他进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但守护进程不受用户登录注销的影响,只受开机或者关机的影响。
        在系统查看中ps ajx |grep -ER ‘d]$‘
[[email protected] 20160729]$ ps ajx |grep -ER ‘d]$‘
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2    17     0     0 ?           -1 S        0   0:00 [kacpid]
    2    22     0     0 ?           -1 S        0   0:00 [ksuspend_usbd]
    2    23     0     0 ?           -1 S        0   0:00 [khubd]
    2    24     0     0 ?           -1 S        0   0:00 [kseriod]
    2    28     0     0 ?           -1 S        0   0:00 [khungtaskd]
    2    30     0     0 ?           -1 SN       0   0:00 [ksmd]
    2    38     0     0 ?           -1 S        0   0:00 [pciehpd]
    2    40     0     0 ?           -1 S        0   0:00 [kpsmoused]
    2    71     0     0 ?           -1 S        0   0:00 [kstriped]
    2   954     0     0 ?           -1 S        0   0:00 [kauditd]
[统一 -1的tpgid]        与终端无关 自成用户组,自成会话,可以创建子线程                                  
 守护进程存在的原因:
daemon函数存在的原因是因为控制终端由于某些原因(如断开终端链接)会发送一些信号的原因。
而接收处理这些信号的缺省动作会让进程退出。这些信号会由于终端上敲一些特殊按键而产生。

  守护进程和后台进程的区别:
(1)守护进程是后台进程,后台进程不一定是守护进程
(2)守护进程运行是与终端无关的,是不能往终端上打消息的
(3)守护进程的会话组和当前目录,文件描述符都是独立的。后台运行只是终端进行了一次fork,让程序在后台执行

 创建守护进程:

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

成功调用该函数的结果是:
(1)创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
(2)创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
(3)如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。
所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。

创建守护进程的步骤:
(1)调用umask将文件模式创建屏蔽字设置为0
(2)父进程fork出子进程,然后子进程调用setsid,父进程直接退出(保证了子进程不是一个进程组的组长),
(3)调用setsid创建一个新的会话(调用成功会使调用进程成为新会话的首进程,
        并且成为一个进程组的组长进程,调用进程没有控制终端)
(4)将当前工作目录更改为根目录
(5)关闭不在需要的文件描述符
(6)忽略SIGCHLD信号 
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
void create_daemon()
{
   int i,f;
   pid_t pid;
  struct sigaction  sa;
   umask(0);
  if(pid=fork()<0);
  if(pid!=0) exit(0);
  setsid();
  sa.sa_handler=SIG_IGN;
   sigemptyset(&sa.sa_mask);
                          sa.sa_flags=0;
   if(sigaction(SIGCHLD,&sa,NULL)<0) return ;
   if(pid=fork()<0)   return;
   if(pid!=0)     exit(0);
   if(chdir("/")<0) return;
   close(0);
   f=open("/dev/null",O_RDWR);
   dup2(f,1);
   dup2(f,2);
}

int main()
{
 
 create_daemon();
 while(1)
 {
sleep(1);
  }

 getchar();
}
 
 
编译运行后,ps  ajx查看  
PPID   PID      PGID   SID  TTY   TPGID  STAT   UID   TIME COMMAND
  1      14550 14550 14550 ?           -1     Ss     500     0:00    ./a.out
14550 14552 14550 14550 ?           -1     S      500     0:00    ./a.out

(1)调用一次fork的作用:
    第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组组长,如果不fork出子进程,则此时的父进程是进程组组长,就无法调用setsid。当子进程调用完setsid函数之后,子进程是会话组长也是进程组组长,并且脱离了控制终端,此时,不管控制终端如何操作,新的进程都不会收到一些信号使得进程退出。
(2)第二次fork的作用:
虽然当前关闭了和终端的联系,但是后期可能会误操作打开了终端。
只有会话首进程能打开终端设备,也就是再fork一次,再把父进程退出,再次fork的子进程作为守护进程继续运行,保证了该精灵进程不是对话期的首进程,
第二次不是必须的,是可选的,市面上有些开源项目也是fork一次
进程 前后台切换的方式

程序
 
int main()
{ 
 while(1)
 {
  printf("wzzx");
  }
 getchar();
}
 运行
[[email protected] 20160729]$ ./a.out 
zxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzx^Z
[1]+  Stopped                 ./a.out
[[email protected] 20160729]$ jobs  查看 
[1]+  Stopped                 ./a.out
[[email protected] 20160729]$ fg 1  前台运行   
(死循环打印中  能被ctrl+z 或ctrl+c 处理掉)
zxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzxwzzx^Z
[[email protected] 20160729]$ bg 1   后台运行
(死循环打印中  不能被ctrl+z 或ctrl+c 处理掉 仅仅关闭终端会话)

/*

http://blog.csdn.net/asd7486/article/details/51956929

http://blog.csdn.net/yh1548503342/article/details/41891047

http://blog.sina.com.cn/s/blog_6642cd020101g3tl.html

*/

时间: 2024-08-24 05:38:29

【LINUX】 会话 进程组 作业 终端的相关文章

linux 进程 进程组 作业 会话 控制终端

linux 进程 进程组  会话 控制终端 这几个很容易搞昏,记录一下,防止忘记 1 进程 个人理解 进程就是一段内存中运行的程序 pid 是进程ID 2 进程组 顾名思义,就是一组进程,他们之间不是孤立的,肯那个存在父子 或进程关系,注意linux 下进程是树状组织,  每个进程一定属于一个进程组,也只能属于一个进程组,进程组里面有多个进程  每个进程组都有一个leader,领导进程的PID 就是集成组ID 即 PGID eg: ps -o pid,pgid,ppid,sid,comm  |

linux 进程组 作业 会话

   进程组,作业,会话1. 进程组      每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或多个进程的集合.      通常,它们与同一作业相关联,可以接收来自同一终端的各种信号. 每个进程组有一个唯一的进程组ID.每个进程组都可以有一个组长进程.组长进程的标识是其进程组ID等于其进程ID.组长进程可以创建一个进程组,创建该组中的进程,然后终止. 只要在某个进程组中一个进程存在,则该进程组就存在,这与其组长进程是否终止无关.2.作业     Shell分前后台来控制的不是进程

从进程组、会话、终端的概念深入理解守护进程

一.写在前面 「守护进程」是 Linux 的一种长期运行的后台服务进程,也有人称它为「精灵进程」.我们常见的 httpd.named.sshd 等服务都是以守护进程 Daemon 方式运行的,通常服务名称以字母d结尾,也就是 Daemon 第一个字母.与普通进程相比它大概有如下特点: 无需控制终端(不需要与用户交互) 在后台运行 生命周期比较长,一般是随系统启动和关闭 二.守护进程必要性 为什么要设置为守护进程,普通进程不可以吗? 当我们在命令行提示符后输入类似./helloworld程序时,在

linux内核之进程的基本概念(进程,进程组,会话关系)

进程是操作系统的一个核心概念.每个进程都有自己唯一的标识:进程ID,也有自己的生命周期.一个典型的进程的生命周期如图4-1所示. 进程都有父进程,父进程也有父进程,这就形成了一个以init进程为根的家族树.除此以外,进程还有其他层次关系:进程.进程组和会话. 进程组和会话在进程之间形成了两级的层次:进程组是一组相关进程的集合,会话是一组相关进程组的集合. 这样说来,一个进程会有如下ID: ·PID:进程的唯一标识.对于多线程的进程而言,所有线程调用getpid函数会返回相同的值. ·PGID:进

作业、进程组、会话和守护进程

1. 进程组 每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或多个进程的集合.通常,它们与同一作业相关联,可以接收来自同一终端的各种信号.每个进程组有一个唯一的进程组ID.每个进程组都可以有一个组长进程.组长进程的标识是,其进程组ID等于其进程ID.组长进程可以创建一个进组,创建该组中的进程,然后终止.只要在某个进程组中一个进程存在,则该进程组就存在,这与其组长进程是否终止无关. 2.作业 Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group

Linux-进程、进程组、作业、会话、控制终端详解

一.进程 传统上,Unix操作系统下运行的应用程序. 服务器以及其他程序都被称为进程,而Linux也继承了来自unix进程的概念.必须要理解下,程序是指的存储在存储设备上(如磁盘)包含了可执行机器指 令(二进制代码)和数据的静态实体:而进程可以认为是已经被OS从磁盘加载到内存上的.动态的.可运行的指令与数据的集合,是在运行的动态实体.这里指的 指令和数据的集合可以理解为Linux上ELF文件格式中的.text .data数据段. 二.进程组 每个进程除了有一个进程ID之外,还属于一个进程组,那什

进程的基本属性:进程ID、父进程ID、进程组ID、会话和控制终端

摘要:本文主要介绍进程的基本属性,基本属性包括:进程ID.父进程ID.进程组ID.会话和控制终端. 进程基本属性 1.进程ID(PID) 函数定义: #include <sys/types.h> #include <unistd.h> pid_t getpid(void); 函数说明: 每个进程都有一个非负整型表示的唯一进程ID(PID).好比如我们的身份证一样,每个人的身份证号是唯一的.因为进程ID标示符总是唯一的,常将其用来做其他标示符的一部分以保证其唯一性,进程ID(PID)

进程组、作业、会话

基本概念 一.进程 进程与程序的区别:程序是指的存储在存储设备上(如磁盘)包含了可执行机器指 令(二进制代码)和数据的静态实体:而进程可以认为是已经被OS从磁盘加载到内存上的.动态的.可运行的指令与数据的集合,是在运行的动态实体. 二.进程组 每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或多个进程的集合.通常,它们与同一作业相关联,可以接收来自同一终端的各种信号.每个进程组有一个唯一的进程组ID.每个进程组都可以有一个组长进程.组长进程的标识是,其进程组ID等于其进程ID. 组

Linux进程组和会话

Linux的进程相互之间有一定的关系.比如说,每个进程都有父进程,而所有的进程以init进程为根,形成一个树状结构.我们在这里讲解进程组和会话,以便以更加丰富的方式了管理进程. 进程组 (process group) 每个进程都会属于一个进程组(process group),每个进程组中可以包含多个进程.进程组会有一个进程组领导进程 (process group leader),领导进程的PID成为进程组的ID (process group ID, PGID),以识别进程组. $ps -o pi