守护进程(Daemon)

来源:互联网 发布:linux cp 所有文件 编辑:程序博客网 时间:2024/06/04 19:35
守护进程(精灵进程):独立于控制终端,不能直接和用户交互,不受用户登录注销的影响的一种进程。
  • 守护进程特点:
    • 独立于控制端(不受控制端的影响)
    • 自成进程组
    • 自成回话
    • 本身是孤儿进程(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,关闭文件描述符
原创粉丝点击