进程组: 一个或者多个进程的集合。进程有自己的进程ID,同时他还属于一个进程组。既然有进程组那么肯定就有组长进程; 组长进程的ID等于该进程组ID;这个组中只要还有一个进程还在,进程组就在!与组长在不在没关系。
作业控制:一个shell可以运行一个前台作业和任意个后台作业。前台和后台都可以由多个进程 组成。
什么是shell?: shell 单词是“壳”的意思,在Linux中shell就是一个面向用户的命令接口,可以由用户录入的界面,并且在界面反馈信息。(也就是我们打开终端敲命令的那个命令行。)
(详细了解shell,请查看如下链接)
作业和进程组的区别: 如果作业中的某个进程创建了子进程,该子进程不属于作业。作业运行结束后,shell即将自己从后台提到前台(此时刚那个子进程还在),如果这个子进程还没终止,则变为后台进程组。
来看个例子:
结果:
分析:
- 程序运行,前台新起了一个作业,有父子两个进程;(子进程不属于作业)
- 5秒之内,shell不能接受任何命令,所以表明:shell变为了后台进程
- 5秒之后,父进程退出,子进程还在运行;
- 此时输入 ls 命令,命令生效,说明shell已经变为了前台进程;
- 总的来说,刚刚新起的作业运行完了,子进程还在,它就自动变为了后台进程
- -
我们在做个测试:在写一个死循环的程序:
运行程序,就会一直循环,我们使用 “ctrl+z”命令可将正在前台执行的命令*放到后台并暂停执行*;
jobs命令:查看Linux任务列表中的任务状态;包括后台运行的程序。
使用:jobs 选项 参数
选项
-l :显示进程号
-p : 仅任务对应的显示进程号
-n :显示任务状态的变化
-r/s :仅输出正在运行状态running / 停止状态stoped的任务
jobs命令详细介绍
在Linux系统中执行某些操作时候,有时需要将当前任务暂停调至后台,或有时须将后台暂停的任务重启开启并调至前台,这一序列的操作将会使用到 jobs、和 fg(把后台的命令调到前台继续运行)、bg(把后台暂停的任务唤醒,继续执行) 三个命令以及两个快捷键来完成。
我们继续测试:(刚刚运行了死循环的程序,并用ctrl+z将他放到了后台暂停执行);现在执行我们一开始的那个程序:(在父进程没有退出前,我们也将他放到后台)
然后jobs查看后台进程:我们发现有两个
到这里,我们看到,子进程不在后台了,却在一直运行;同时shell(我们输指令的命令行)也是可以运行的,我们敲的指令都能运行,这是为什么???
**其实:shell只能运行一个前台作业;而作业可以由多个进程组成;所以,前台下当然可以运行多个进程咯;就像这里可以同时运行shell(输入指令的命令行)
和子进程。**
会话
会话是一个或者多个进程组的集合;一个会话可以由一个控制终端;建立与控制终端连接的会话首进程称为控制进程。
一个会话中的几个进程组被分成一个前台进程组和一个或者多个后台进程组。
守护进程
什么是守护进程?
- 守护进程也叫精灵进程,是运行在后台的一种特殊进程,它独立于控制终端并且周期性的执行任务或者等待处理发生的事件;
有什么用?
- Linux上的大多数服务器就是用守护进程实现的。例如:ssh服务,ftp服务,web服务器等
- Linux系统启动时会启动很多系统服务进程,他们没有控制终端,不能喝用户交互,其他进程都是在用户登录时创建,用户注销时终止;但是守护进程不受用户登录、注销的影响,他一直运行着。
ps auj | more //查看系统中的进程
创建守护进程:
- 关键是调用setsid函数,是他创建一个新会话(Session),并且成为会话首进程。
#include<unistd.h>
pid_t setsid(void);
返回值:成功返回新创建的会话(session)的ID(也就是当前进程ID),
失败返回-1;
注意:在调用setsid函数之前,当前进程不能是进程组的Leader,否则函数返回-1;
怎么保证当前进程不是进程组的Leader呢?
很简单!fork()出来一个子进程,用子进程调用setsid函数;因为fork出来的子进程和父进程在同一进程组里,而进程组的Leader是进程组的第一进程;所以子进程肯定不是Leader;
调用setsid成功的结果:
- 创建一个新的会话,当前进程成为(session Leader)会话首进程,当前进程id就是会话首进程的id;
- 创建新的进程组,当前进程称为组长,当前id是进程组id
- 如果当前进程有一个控制终端;则它是去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是⼀个普通的打开⽂件⽽不是控制终端了。
例子:
结果:(我们看到a.out的TPGID时候 -1,就是守护进程了)