作业:

    一个或多个进程的集合,一个前台作业可以由多个进程组成,一个后台作业也可由多个进程组成。Shell真正控制的不是进程而是作业,Shell只能运行一个前台作业和任意多个后台作业,这为作业控制。

进程组:

    每个进程都属于一个进程组,每个组都有唯一的进程组ID,每个进程组都有一个组长进程。只要某进程组的一个进程存在,该进程组就存在,与组长进程是否终止无关。

会话:

    一个或多个进程组的集合,包括一个控制进程(会话首进程)、一个前台进程组和任意多个后台进程组。

终端:

    用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端 (Controlling Terminal),控制终端是保存在PCB中的信息,调用fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端。每打开一个终端,与该控制终端相关联的那个控制进程为bash(会话首进程)。每个进程通过一个特殊设备文件/dev/tty访问它的控制终端。

守护进程(精灵进程):

    是在后台运行的一种特殊进程,它独立于控制终端(即与终端无关联),自成一个会话,不能进行前后台控制。

守护进程的用处:

    Linux系统启动时会启动很多系统服务进程,例如网络登录过程中的inetd,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着。


创建守护进程最关键的是调用setsid函数创建一个新的Session,并成为Session Leader。 

该函数调用成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。

注意,调这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。

成功调用该函数的结果是: 

1. 创建个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。 

2. 创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。 

3. 如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进

程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普

通的打开文件而不是控制终端了。

守护进程的创建:

1.调用umask将文件模式创建屏蔽字设置为0

2.让init进程成为新产生进程的父进程,调用fork()创建子进程后,父进程立即退出,产生的子进程成为孤儿进程,并被init进程接管,同时所产生的新进程将变为在后台进行。

3.调用setsid函数,使得新创建的进程脱离控制终端,同时创建新的进程组,并成为该进程的首进程。setsid函数原型:pid_t setsid(void);

4.注册信号处理函数,使之对SIGCHLD信号进行忽略动作处理

5.再次fork,终止父进程,保持子进程不是话首进程,从而保证后续不会在和其他终端关联 

6.关闭不需要的文件描述符,同时重定向三个标准文件描述符。

  

wKioL1cu5xvQSAJcAABcEkK4e0M229.png

wKiom1cu5kGwMNMyAABDWYJwvIY050.png

wKioL1cu5xzQRSIGAABqjpn3UIc316.png

wKioL1cu5xzR18BdAAAhFAph4Ec401.png

使用ps axj 命令查看系统中的进程

参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与作业控制相关的信息。 

查看该守护进程:使用ps axj | grep -E 'my_daemon'

wKiom1cu59uRnHQuAABDQnJApQs299.png

可以看到该进程的TTY为?,表示这个程序无控制终端