【Linux】守护进程

一、概念

   守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件守护进程是一种很有用的进程。Linux 的大多数服务器就是用守护进程实现的。比如,Internet 服务器inetdWeb服务器 httpd 等。同时,守护进程完成许多系统任务。比如,作业规划进程 crond等。

   Linux 系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着。这种进程有一个名称叫守护进程(Daemon)。

   守护进程脱离于终端并且在后台运行,它脱离终端的目的是为了避免进程在运行过程中的信息在任何终端中显示并且进程也不会被任何终端所产生的终端信息所打断。它从被执行的时候开始运转,直到整个系统关闭才退出(当然可以认为杀死相应的守护进程)。如果想让某个进程不因为用户或中断或其他变化而影响,那么就必须把这个进程变成一个守护进程。

二、创建

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

2.调用 fork,父进程退出(exit)。

  原因:1)如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得 shell认为该命令已经执行完毕。

      2)保证子进程不是一个进程组的组长进程。

3.调用 setsid创建一个新会话。setsid 会导致:1)调用进程成为新会话的首进程。

                           2)调用进程成为一个进程组的组长进程 。

                           3)调用进程没有控制终端。(再次 fork  一次,保证 daemon进程,之后不会打开 tty设备)

进程组:是一个或多个进程的集合。进程组有进程组 ID来唯一标识。除了进程号(PID)之外,进程组 ID也是一个进程的必备属性。每个进程组都有一个组长进程,其组长进程的进程号等于进程组 ID。且该进程组 ID 不会因组长进程的退出而受到影响。

4.将当前工作目录更改为根目录。通常的做法是让“/”作为守护进程的当前目录,当然也可以指定其他的别的目录来作为守护进程的工作目录。

5.关闭不再需要的文件描述符。如果不进行闭的话将会浪费系统的资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。

6.其他:忽略 SIGCHLD 信号。

三、守护进程的退出

   当用户需要外部停止守护进程运行时,往往需要使用 kill 命令来停止该守护进程,所以守护进程中需要编码来实现 kill发出的 signal信号处理,达到进程的正常退出。实现该过程的函数是 signal函数:

signal(SIGTERM, sigterm_handler);
                void sigterm_handler(int arg)
                  {
                      //进行相应处理的函数
                  }

功能是:将一个给定的函数和一个特定的信号联系起来,即在收到特定的信号的时候执行相应的函数。

四、创建守护进程的例子

1.fork 一次

建立目录 mkdir daemon,创建文件 vim mydaemon.c  并加入,代码如下:



运行 ./mydaemon,并进入根目录,用命令 ps axj | grep mydaemon查看系统中的守护进程得出 mydaemonPID,结果如下:

进入 proc目录,proc将内存中的进程信息及系统中的软硬件信息以文件系统的形式呈现。

上面已经知道了 mydaemon PID,进入 PID,我们可以查看守护进程的信息。进入文件描述符表 fd,查看文件描述符表可以看到此时文件描述符为空。


当然我们也可以在程序代码中设置关闭一部分文件描述符,此时查看文件描述符表就不再为空。


创建守护进程也可以直接调用 daemon  函数:int daemon(int nochdir, int noclose); 

一般调用 daemon 有两种方式: 

1) daemon(0,0);  //默认更改工作目录且更改文件描述符 0,1,2 为空,使其指向 /dev/null。这个 /dev/null 类似于一个信息黑洞,不管哪个文件描述符对其进行写操作,它都会直接将数据丢弃; 

2) daemon(1,0);   //不更改工作目录也不更改文件描述符。


2. fork 两次





运行结果如下,可以看到 fork一次和 fork两次的结果是一样的:




守护进程要 fork两次的原因:

  第一次 fork:作用是让 shell认为这条命令已经终止,不用挂在终端输入上,另一个是为了后面的 setsid服务,因为调用 setsid函数的进程不能是进程组组长,如果不fork 子进程,那么此时的父进程是进程组组长,无法调用 setsid。所以到这里子进程便成为了一个新会话组的组长。

  第二次 fork 2 fork不是必须的fork第二次主要目的是防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长,再fork 一次,子进程ID != sidsid是进程父进程的 sid)。所以也无法打开新的控制终端。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值