进程间关系和守护进程

fg:该命令用于将后台作业(在后台运行的作业或者在后台挂起的作业)放在前台终端运行。若后台命令只有一个,使用该命令时 ,可以省略任务号。
在Linux系统中执行某些操作时,有时需要将当前任务暂停调至后台,有时需要将后台暂停的任务重启并调至前台,这一系列的操作将会使用到 jobs,fg,bg,以及两个快捷键。 fg jobnumber,(jobnumber可以通过jobs命令查到后台正在执行的命令序号(不是pid)。

bg:将一个在后台暂停的命令,变成继续执行。

&:用在一个命令的最后,将命令(进程组)放在后台运行,执行。
Ctrl+z:将一个正在前台执行的命令放到后台,并且暂停。
jobs:查看当前有多少进程在后台运行的命令。
Ctrl+c:杀掉的不是进程,而是整个作业。
nohup:不挂断的运行命令。

守护进程:是运行在后台的一种特殊进程,守护进程独立于控制终端,并且周期性的执行某种任务或者等待处理某些发生的事件,目的:防止终端产生的一些信号让终端退出。(ftp服务器,ssh服务器,web服务器httped),

特点:(1)所有的守护进程都没有控制终端,其终端名(tty)设置为?
(2)自成会话,自成进程组,不与其他回话或者进程组相关联,所以一般守护进程的进程ID,组ID,会话ID都相同。
(3)系统服务进程(守护进程)不受用户登录注销的影响。守护进程一直在运行。
(4)生存期长,在系统引导装入时启动,仅在系统关闭时停止。
(5)大多数进程以root权限运行。

内核线程(内核守护进程)
(其实也叫内核进程,Linux没有真正意义上的线程,都是用进程模拟实现,轻量级进程。)
内核守护进程以无终端的方式启动,凡是在TPGID一栏写着-1的进程都是没有控制终端的进程,也就是守护进程。在COMMAND列[ ]括起来的名字表示内核线程,这些线程在内核创建,没有用户空间代码,因此没有程序文件名和命令行, 通常采用以k开头的名字,表Kernel。对于需要在进程上下文执行工作但却不被用户层进程上下文调用的每一个内核组件,通常都有它自己的内核守护进程。

Linux通常使用一个叫kthreadd的特殊内核进程来创建其他内核进程,所以kthreadd表现为其他内核进程的父进程
由此我们可看到kthread的进程ID为2。这也就解释了为什么在上图中内核进程(内核线程)的父进程ID(PPID)都为2了。
会话:一个会话有一个控制终端,简历与控制终端相连接的会话首进程叫做控制进程,一个会话当中分为一个前台进程组和多个后台进程组。内核通常发信号给前台进程组的所有进程。
会话的意义在于将多个工作囊括在一个终端,并且取其中的一个工作为前台,来直接接受终端的输入输出,以及终端信号,其他的工作在后台运行。

创建守护进程
函数setsid,创建守护进程的关键一步就是调用setsid函数创建一个新的回话(session),并让当前的进程称为这个会话的leader,即会话首进程。

pid_t setsid(void)
返回值:成功,返回进程组ID,失败,返回-1.
直接在要设置的进程里调用。
执行结果:
(1)创建一个新会话,使该进程变成新会话的会首进程(创建会话的进程),此时,该进程是当前会话的唯一进程。
(2)使该进程成为一个新进程组的组长进程,进程组ID就是该进程的进程ID。
(3)使该进程没有控制终端,如果在调用setsid之前有,那么就切断控制终端与当前进程的联系。
(4)当前进程的进程ID,进程组ID,会话ID都相等。
setsid函数调用之前的特殊要求:该进程不能是一个进程租的组长进程,如果是,函数返回错。
所以我们通常为了防止出现这种情况会用以下做法:让一个进程fork出一个子进程,然后立即将父进程终止,而子进程继续。子进程的进程ID是新分配的,子进程的PCB集成了父进程的进程组ID,所以两者不可能相等。这样就保证了子进程不是一个进程组的组长。
除了以上两种操作外,创建一个守护进程还需要其他几项工作。下面我将完全的步骤列出来:

* 调用umask函数将当前文件模式创建屏蔽字为一个已知值(通常为0)。在上面提到过,我们要操作的进程是一个子进程。而子进程从父进程的PCB继承过来的文件模式创建屏蔽字可能会屏蔽某些权限。而加入我们要创建的守护进程正好需要这些权限的话就会造成很麻烦的问题。另一方面,如果守护进程调用了库函数创建了文件,那么文件模式创建屏蔽字应该设置为更强的(如007)。因为库函数不允许调用者通过一个显式的函数参数来设置权限。
* fork子进程,并且结束父进程。
* 调用setsid函数。创建一个会话,使当前进程称为一个会话的首进程,一个进程组的组长进程,一个没有控制终端的进程。
* 调用函数chdir将当前进程的工作目录更改为根目录或者某个指定位置。因为子进程从父进程继承来的工作目录可能是在一个挂载的文件系统中,而守护进程在系统再次引导前是一直存在的,如果不更改,那么挂载的文件系统就一直卸载不了。
* 调用fclose函数关闭不在需要的文件描述符(0,1,2等)。使守护进程不再持有从父进程继承来的任何文件描述符。或者还可以将文件描述符重定向到文件(/dev/null)。这样相当于将当前进程的标准输入,标准输出,标准错误都失效。关闭文件描述符的原因是守护进程是与控制终端没有任何联系的,并且它是在后台运行。后台并没有接受它输入输出也无处显示,我们不希望在终端上简单守护进程的输出,用户也不想在终端上的输入被守护进程读取。
* Linux专门的函数接口来创建守护进程。

int daemon(int nochdir,int noclose);
两个参数,第一个参数nochdir如果设置为0的话表示将工作目录改为根目录。第二个参数noclose如果设置为0的话就将文件描述符重定向到/dev/null文件。与上面原理相似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值