守护进程(Daemon)

守护进程(精灵进程):独立于控制终端,不能直接和用户交互,不受用户登录注销的影响的一种进程。
  • 守护进程特点:
    • 独立于控制端(不受控制端的影响)
    • 自成进程组
    • 自成回话
    • 本身是孤儿进程(fork之后父进程退出),所以父进程为init(孤儿进程都被1号进程收养)
    • 守护进程通常采用d结尾,例如:Internet服务器inted;Web服务器httpd;acpid电源管理;sshd远程登录
  • 守护进程一些应用场景:
    • Linux的大多服务器使用Linux守护进程实现的;
    • 作业规划进程(crond)

守护进程的创建
  • 调用umask设置屏蔽字为0(如果不设置创建文件是权限可能会有一定的影响)
  • 创建子进程(fork),父进程退出;
    • 父进程创建的子进程与父进程不属于同一作业,父进程退出表示该作业已执行完
    • 创建的子进程是第二个进程,保证了子进程不是组长进程
  • 调用setsid函数创建一个新会话;

    setsid函数:

    #include <unistd.h>
    pid_t setsid(void)

    返回值:成功返回新建session的ID,出错返回-1;
    调用该函数的进程不能是进程组的Leader,否则返回-1;

  • 将当前工作目录更改为根目录

    • 因为根目录一般是不会删除的,而其他的目录极有可能会被删除,工作目录都被删除了,当然运行的作业也就不了了之了
  • 关闭文件描述符
    • 前面我们提到守护进程不能直接和用户交互,即没有标准输入,输出等,所以文件描述符不在需要
  • 忽略SIGCHLD信号

代码(fork一次)
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<signal.h>

void mydaemon()
{
    int i;
    pid_t id ;

    umask(0);//设置屏蔽字

    id = fork();//创建子进程
    if(id < 0)
    {
        printf("create error");
    }else if(id >0)
    {
        exit(0);//父进程退出
    }

    setsid();//新建session

    i = chdir("/");//更改当前目录为根目录
    //sussess 0
    if(i<0)
    {
        printf("change error");
    }

    close(0);//关闭文件描述符
    close(1);
    close(2);

    signal(17,SIG_DFL);//屏蔽SIGCHLD信号
}

int main()
{
    mydaemon();
    while(1)
    {
        sleep(1);
    }
    return 0;
}

程序运行:
这里写图片描述


fork 1 次与 2 次
  • 首先分析前面用到的setsid函数
    • 调用setsid函数后,创建一个新的session,当前进程成为session的 Leader,即当前进程的ID就是session的ID;
    • 也创建一个新的进程组,当前进程成为进程组的Leader,组ID即当前进程ID;
    • 当前进程失去原有的控制端,成为一个无控制端的进程
  • 上面的分析,调用完setsid函数后,当前进程成为会话首进程(控制进程),会话首进程能够建立与终端的连接,后序如果再打开终端,有可能就会建立连接;所以再次fork保证子进程不是会话首进程
//fork两次代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<signal.h>
#include<stdlib.h>

void mydaemon()
{
    int i;
    pid_t id ;

    umask(0);

     id = fork();
    if(id < 0)
    {
        printf("create error");
    }else if(id >0)
    {
        exit(0);
    }

    setsid();

//第二次fork
    id = fork();
    if(id < 0)
        printf("create error");
    else if(id >0)
        exit(0);
    i = chdir("/");

    //sussess 0
    if(i<0)
    {
        printf("change error");
    }

    close(0);
    close(1);
    close(2);

    signal(17,SIG_DFL);
}

int main()
{
    mydaemon();
    daemon(0,0);//调用系统的
    while(1)
    {
        sleep(1);
    }
    return 0;
}

Linux标准Daemon
 #include <unistd.h>
 int daemon(int nochdir, int noclose);
//第一个参数:nochdir 如果为0,则改变当前工作目录为根目录
//第二个参数:noclose 如果为0,关闭文件描述符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值