ToB企服应用市场:ToB评测及商务社交产业平台

标题: 历程间关系与历程守护 [打印本页]

作者: 去皮卡多    时间: 2024-9-21 12:04
标题: 历程间关系与历程守护
一、历程组

1、理解

   每一个历程除了有一个历程   ID(PID)之外 还属于一个历程组,  历程组是一个大概多个历程的集合, 一个历程组可以包含多个历程。 每一个历程组也有一个唯一的历程组 ID(PGID), 并且这个 PGID 雷同于历程 ID, 同样是一个正整数, 可以存放在 pid_t 数据范例中。  2、举例

   

  上图就是用管道创建了一个历程组。
  

    我们可以用 ps ajx | head -1 && ps ajx | grep sleep,来查看指定的历程。    发现PGID是一样的2114632。  3、结论

   PGID是历程组组长的PID,历程组组长可以创建一个历程组,也可以在自己的历程组里面创建新历程(父历程)    历程组的声明周期终止于末了一个历程退出,与组长无关。  二、会话

1、理解

   会话可以看成是一个或多个历程组的集合, 一个会话可以包含多个历程组。每一个会话也有一个会话   ID(SID)     

如三个历程SID雷同,阐明构成的历程组在同一个会话中。   2、Linux会话结构


首先我们登录Linux之后,先有 bash 历程创建终端文件,此时 bash 不但是历程组组长,bash 历程组还是会话组长,我们大部门的工作都是在 bash 创建的会话里面完成的。创建与控制终端连接的会话首历程是控制历程 bash。
3、结论

(1)在同一个会话中允许存在多个历程组。
(2)但是前台历程只有一个,背景历程可以有多个
例如我在前台启动一个历程组,输入指令 bash 由于在背景,就不会处理指令。
(3)前背景:前台可以从标准输入中获取数据。历程在启动时末了带上&就是背景历程
(4)无论何时,发送的制止信号只能给前台历程。
三、控制终端

   在   UNIX   系统中,  用户通过终端登录系统后得到一个   Shell   历程,这个终端成为   Shell   历程的控制终端。控制终端是保存在   PCB   中的信息,我们知道   fork   历程会复制   PCB   中的信息,因此由   Shell   历程启动的别的历程的控制终端也是这个终端。  默认环境下 没有重定向,每个历程的标准输入、标准输出和标准错误都指向控制终端,历程从标准输入读也就是读用户的键盘输入,历程往标准输出或标准错误输出写也就是输出到显示器上。别的会话、历程组以及控制终端另有一些其他的关系:    一个会话可以有一个控制终端,通常会话首历程打开一个终端(终端装备或伪终端装备)后,该终端就成为该会话的控制终端。     创建与控制终端连接的会话首历程被称为控制历程  。     一个会话中的几个历程组可被分成一个前台历程组  以及一个大概多个  背景进  程组  。     假如一个会话有一个控制终端,则它有一个前台历程组,会话中的其他历程组则为背景历程组。     无论何时进入终端的制止键(ctrl+c  )或退出键(  ctrl+\  ),就会将制止信号发送给前台历程组的所有历程。     假如终端接口检测到调制解调器(或网络)已经断开,则将挂断信号发送给控制历程(会话首历程)。  四、作业与作业控制

1、理解

   作业  是针对用户来讲,用户完成某项使命而启动的历程,一个作业既可以只包含一个历程,也可以包含多个历程,历程之间相互协作完成使命, 通常是一个历程管道。  2、作业控制操作

jobs:查看作业。-p查看作业pid
   关于默认作业:对于一个用户来说,只能有一个默认作业(+),同时也只能有一个即将成为默认作业的作业(-),当默认作业退出后,该作业会成为默认作业。     + : 表示该作业号是默认作业     -:表示该作业即将成为默认作业     无符号: 表示其他作业   fg 作业号:把一个指定作业提到前台(担当用户输入的数据)
把作业放回背景:(1)作业停息(ctrl z,也叫挂起)之后OS就会把作业放回背景。(2)bg 作业号:在背景启动作业
3、作业状态


4、举例


五、守护历程

1、理解

一个服务历程独立成为一个会话,就不会受原来会话的影响。
2、把历程变成守护历程


不是历程组组长调用函数 setsid 就可以把自己变成守护历程。调用的历程就会变成新会话的首历程,此时会话中只有一个历程,也是一个历程组的组长。
做法:父历程先 fork 子历程,父历程退出,子历程调用函数,由于子历程继承父历程的历程组id,历程id被重新分配,所以守护历程是孤儿历程。
这种历程已经不属于 bash 会话,只能用 kill 杀死历程。
3、代码实现

  1. #pragma once
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <signal.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. const char *root = "/";
  10. // 路径/dev/null 文件里面的数据不能被读取,相当于是被丢弃
  11. const char *dev_null = "/dev/null";
  12. void Daemon(bool ischdir, bool isclose)
  13. {
  14.     // 1. 忽略可能引起程序异常退出的信号
  15.     signal(SIGCHLD, SIG_IGN);
  16.     signal(SIGPIPE, SIG_IGN);
  17.     // 2. 让自己不要成为组长,父进程退出
  18.     if (fork() > 0)
  19.     exit(0);
  20.     // 3. 设置让自己成为一个新的会话, 后面的代码其实是子进程在走
  21.     setsid();
  22.     // 4. 每一个进程都有自己的 CWD,是否将当前进程的 CWD 更改成为 / 根目录
  23.     if (ischdir)
  24.         chdir(root);
  25.     // 5. 已经变成守护进程,不需要和用户的输入输出,错误进行关联了
  26.     if (isclose)
  27.     {
  28.         close(0);
  29.         close(1);
  30.         close(2);
  31.     }
  32.     else
  33.     {
  34.         // 这里一般建议就用这种
  35.         int fd = open(dev_null, O_RDWR);
  36.         if (fd > 0)
  37.         {
  38.             dup2(fd, 0);
  39.             dup2(fd, 1);
  40.             dup2(fd, 2);
  41.             close(fd);
  42.         }
  43.     }
  44. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4