一、进程组
(1)进程组是一个或多个进程的集合;
(2)通常,进程组与同一作业相关联,可以接收来自同一终端的各种信号;
(3)每个进程组都有一个唯一的进程组ID;
(4)每个进程组都有一个组长进程,组长进程的标识是,其进程ID等于其进程组ID;
(5)只要在某个进程组中有一个进程存在,则该进程组就存在,与组长进程是否终止无关;
(6)组合键(Ctrl+c、Ctrl+v、Ctrl+)可以终止前台的进程组。
二、作业
(1)Shell分前后台来控制的不是进程而是作业或者进程组;
(2)不管是前台作业还是后台作业,都可以由多个进程组成;
(3)Shell可以同时运行一个前台作业和任意多个后台作业,称为作业控制;
(4)bash默认是前台作业。
·作业和进程组的区别:
如果作业中的某个进程又创建了子进程,则子进程不属于作业,但属于进程组。
三、会话
(1)会话是一个或多个进程组的集合;
(2)会话ID(SID):以bash的ID为会话ID;
(3)一个会话可以有一个控制终端(通常是登录到其上的终端设备或伪终端设备);
(4)建立与控制终端连接的会话首进程被称为控制进程;
(5)一个会话中,应包括控制进程(会话首进程),一个前台进程组(默认为bash)和任意多个后台进程组
(6)每次打开终端进行登录时,就会创建一个会话。
四、作业控制
Shell可以同时运行一个前台作业和任意多个后台作业,称为作业控制。
jobs----查看后台命令
fg n----将n号作业提到前台
#----将前台作业提到后台
ctrl + z ----暂停当前进程
bg n----将暂停的n号作业运行起来
ctrl + c----杀掉的不是进程,而是杀掉整个作业
·作业控制相关的信号
cat----输入什么,显示什么
五、守护进程
·对守护进程的基本认识
守护进程本质上也是孤儿进程。
(1)守护进程又称精灵进程,是运行在后台的一种特殊进程;
(2)它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件;
(3)守护进程自成进程组,自成会话,不会受用户登录和注销的影响,它们一直在运行着;
(4)所有网络服务都以守护进程的形式运行;
(5)大多以d结尾,它的tty设为与终端无关。
·创建守护进程
创建守护进程最关键的一步是调用setsid函数来创建一个新的会话,并成为Session Leader。
#include<unistd.h>
pid_t setsid(void);
该函数调用成功时返回新创建的会话ID,出错返回-1.
注意:
(1)调用setsid函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1;
(2)为了保证上述条件成立,则需要先fork,再调用setsid函数:
·用fork创建一个子进程,让父进程退出;
·用fork出来的子进程调用setsid函数。
成功调用setsid函数的结果是:
·会创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
·会创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
·若当前进程原本有一个控制终端,则它会失去这个终端,成为一个没有控制终端的进程。
daemon函数
int daemon(int nochdir,int noclose);
当nochdir和noclose都设为1时,不更改工作目录,不重定向文件;
当nochdir和noclose都设为0时,将工作目录更改为根目录,重定向文件至/dev/null.
#include<stdio.h>
#include<unistd.h>
int main()
{
daemon(0,0);
while(1);
}