守护进程

先了解一些基本概念:

进程组:
一个或多个进程的集合,如父子进程或者通过管道连接起来的进程等这些都同属一个进程组。进程组id一般都是该进程组的组长id。
进程组中所有进程死亡,进程组才算结束。
ctrl+c 发送信号,发送给的是进程组,组内所有进程都会退出
ctrl+c信号不能发给后台进程


作业:
正在执行的进程称为作业,一个作业通常包含一个或多个进程,这几个进程共同完成一项任务,就叫作业。
尤其是使用了管道或重定向命令时,一个作业就同时启动多个进程。
shell分前后台控制的不是进程而是作业或者进程组,前后台作业都可以由多个进程组成,shell可同时运行一个前台作业和多个后台作业,这就是作业控制

作业与进程组的区别:
如果作业中的某个进程又创建了子进程,则子进程不属于作业。一旦作业运行结束,Shell就把自己提到前台,如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。

-

进程和作业:
联系:

一个作业通常包括几个进程,几个进程共同完成一个任务,即作业。
区别:

  • 一个作业是我们提交给shell的一项任务或者批处理,和操作系统无关。进程是具体执行的一个可执行程序,是操作系统调度的对象。
  • 进程是一个系统中最基本的也是必需要求的调度属于低级调度,而作业调度是为是了提高系统性能而调度的高级调度

jobs命令:查看后台作业
fg命令:将后台作业提到前台来执行

bg命令:将作业放在后台执行,使前台执行其他任务
在指令后添加&也有同样效果。

会话:
会话(session)是一个或多个进程组的集合。每打开一个终端,就新建了一个会话,一个会话对应一个终端
一个会话中可以有多个进程组,会话结束所有进程组都终止

守护进程:
也叫精灵进程。
守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。

在linux或者unix操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程。

常年在后台服务,不与其他用户进行交互
Linux中大多服务器进程都是守护进程 ftp服务器、web服务器等

守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)。

如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。

创建守护进程:
因为关掉终端进程就会结束,因此创建守护进程不能和终端有关系,不受终端影响

首先第一步:新启一个会话 setsid()函数用于创建一个新的会话
当该函数要求调用它的函数不是一个进程组的组长
所以我们要先创建一个子进程fork(),父进程退出,然后在子进程中调用setsid()函数
调用结束后,当前进程成为新的会话的组长,当前进程id成为session_id,它自成一个进程组,进程组的组长也是他。此时没有控制终端

要关闭所有已打开的文件描述符

  • 方式1:for( int i=0;i<=255;i++ )
    close(i);
  • 方式2:讲文件描述符dup到空洞文件
    空洞文件:/dev/null
    放进空洞文件的内容都不存在了
    推荐方式1,可以再拿出来用

最后再编写我们需要守护进程执行的任务即可

假如我们可以让守护进程定期扫描一个文件,并执行该文件中的命令,再将执行结果写入另一个文件中。
实际上windows下有和它功能类似的东西叫计划任务。
计划任务:可将脚本、程序或文档安排在某个时间运行,它在每次启动windows系统的时候自动启动并在后台运行。

setup 命令:打开系统服务

守护进程的工作目录一定在某个磁盘下,经过一段时间有可能磁盘坏掉了,我们就需要卸载掉这个磁盘,
可由于该磁盘下有守护进程一直在运行,导致无法卸载,所以我们就需要改变它的当前路径到根目录下来解决这个问题。根文件系统不能被卸载.

所以要创建守护进程一般需要进行以下五步:
1.创建子进程 fork()
2.新启一个会话 setsid()
3.关闭所有文件描述符
4.更改当前路径到根目录下
chdir(”/”)
5.写要执行的动作

简单实现一个守护进程,他的功能就是每秒向文件中打个” . “

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
    if(fork()>0)
    {
        exit(0);
    }
    setsid();//创建守护进程
    int i;
    for(i=0;i<255;i++)
        close(i);
    int fd=open("tmp",O_RDWR|O_CREAT,0644);
    for(;;)
    {
        write(fd,".",1);
        sleep(1);
    }
    close(fd);
}

系统提供了一个函数来代替以上几步:
int deamon( int nochdir,int noclose);
nochdir: 0表示更改到根目录,非0不更改
noclose: 0表示将标准输入、输出、错误重定向到/dev/null,非0不重定向

用该函数来实现一把:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
    daemon(0,0);
    for(;;)
    {
        write(fd,".",1);
        sleep(1);
    }
    close(fd);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值