一.进程组与会话
对于单个进程以及对应的PCB,我们之前已经大体全部讲过了,现在我们就来讲解进程组的概念
进程组:指的是一个或者多个进程的集合, 一个进程组可以包含多个进程。 每一
个进程组也有一个唯一的进程组 ID(PGID), 并且这个 PGID 类似于进程 ID, 同样是
一个正整数, 可以存放在 pid_t 数据类型中补充:
pid:指当前进程的ID
ppid:指的是当前进程的父ID(可以为自身)
pgid:指的是当前进程的进程组ID
我们知道ps 指令可以查看当前系统运行的进程,下面我们认识两个新的选项:
-e 选项表示 every 的意思, 表示输出每一个进程信息
-o 选项以逗号操作符(,) 作为定界符, 可以指定要输出的列如下图:
上面我们可以看出第二列是pgid,第二行和第三行属于同一个组,其中第二行pid=14528为组长进程,组长特点:pid=pgid
注意点:进程组的生命周期: 从进程组创建开始到其中最后一个进程离开为止。 注意:
主要某个进程组中有一个进程存在, 则该进程组就存在, 这与其组长进程是否已经终
止无关会话:
定义:
会话可以看成是一个或多个进程组的集合, 一个会话可以包含多个进程组。 每一个会
话也有一个会话 ID(SID)上图我们就可以看到sleep 10000/20000和30000属于同一个会话
会话如何创建呢?
在linux中有如下函数:
//头文件; #include <unistd.h> //函数: pid_t setsid(void) {}; //返回值:成功返回对应的sid,失败返回-1 //注意点: //1.调用该函数的进程成为了新会话的话首进程,并且新的会话中目前只有一个进程,无bash //2.调用的进程不能为话首进程,否则报错,我们可以fork通过子进程来调用
二.控制终端
在 UNIX 系统中, 用户通过终端登录系统后得到一个 Shell 进程, 这个终端成为 Shell
进程的控制终端。 控制终端是保存在 PCB 中的信息, 我们知道 fork 进程会复制 PCB
中的信息, 因此由 Shell 进程启动的其它进程的控制终端也是这个终端。 默认情况下
没有重定向, 每个进程的标准输入、 标准输出和标准错误都指向控制终端, 进程从标
准输入读也就是读用户的键盘输入, 进程往标准输出或标准错误输出写也就是输出到
显示器上。
注意点:1.一个会话有最多一个终端,通常是话首进程打开一个终端(终端设备或伪终端设备) 后, 该终端就成为该会话的控制终端
2.建立与控制终端连接的会话首进程被称为控制进程
3.一个会话中多个进程组可以分为一个前台进程和多个后台进程
4.终端的终止等快捷键都是指向前台进程的
三.作业控制
定义:作业是针对用户来讲, 用户完成某项任务而启动的进程, 一个作业既可以只包含
一个进程, 也可以包含多个进程, 进程之间互相协作完成任务, 通常是一个进程
管道Shell 分前后台来控制的不是进程而是作业 或者进程组。 一个前台作业可以由多
个进程组成, 一个后台作业也可以由多个进程组成, Shell 可以同时运⾏一个前台
作业和任意多个后台作业, 这称为作业控制
放在后台执⾏的程序或命令称为后台命令, 可以在命令的后面加上&符号从而让
Shell 识别这是一个后台命令, 后台命令不用等待该命令执⾏完成, 就可立即接收
新的命令, 另外后台进程执行完后会返回一个作业号以及一个进程号(PID)
如下图:
下面我们来认识一些指令控制后台:
&:表示将进程放后台运行(例如服务器,都是挂后台运行)
jobs:
-l:查看详细
-p:只显示pid
作业挂起:ctrl+z
作业切回:
fg 后面可以跟作业号或作业的命令名称。 如果参数缺省则会默认将作业号为 1 的作业切到前台来执⾏, 若当前系统只有一个作业在后台进⾏, 则可以直接使用 fg 命令不带参数直接切回
如下是将后台进程切回前台并终止操作
四.守护进程
定义:一类在后台运行的特殊进程,用于执行特定的系统任务。 很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。 另一些只在需要的时候才启动,完成任务后就自动结束
下面我们认识下deamon函数:
#include <unistd.h> int daemon(int nochdir, int noclose); //作用:创建守护进程 //参数: //nochild:表示是从当前位置还是/位置开始 //noclose:是否进行输入输出的处理
关于该文件,可以看成垃圾站,任何都可以向其中写读,但是会自动清除,deamon重定向可以到该文件位置
下面我们手撕一个简单的deamon函数:
#include <iostream> #include <cstdlib> #include <signal.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> void Deamon(bool ischdir,bool isclose) { // 忽略可能引起程序异常退出的信号 signal(SIGCHLD, SIG_IGN); signal(SIGPIPE, SIG_IGN); //利用当前进程,创建子进程,保证自己不为组长 pid_t pid =fork(); if(pid>0) { //父进程 exit(0); } //下面就是子进程了: //3设置让自己成为一个新的回话 setsid(); //下面修改参数部分: //ischdir: if(ischdir) { chdir(root); } //isclose if(isclose) { //不需要重定向,直接关闭 close(0); close(1); close(2); } else { //需要重定向,dup2 int fd=open(dev/null,O_RDWR); if(fd>0) { //打开文件成功: dup2(fd,0); dup2(fd,1); dup2(fd,2); close(fd);//关闭文件 } } }
利用deamon函数我们很容易就可以将服务进程守护进程化
以上就是守护进程的全部内容,感谢大家的支持!!!