守护进程编写实例

守护进程

如果一个进程永远都是以后台方式启动,并且不能受到Shell退出影响而退出,一个正统的做法是将其创建为守护进程。守护进程值得是系统长期运行的后台进程,类似Windows服务。守护进程信息通过ps –a无法查看到,需要用到–x参数,当使用这条命令的时候,往往还附上-j参数以查看作业控制信息,其中TPGID一栏为-1就是守护进程

创建守护进程最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader。成功调用该函数的结果是:

  • 创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id
  • 创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id
  • 如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。

三. 守护进程实例


例程:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

#define  LOG_FILE     "/tmp/my.log"

int Daemon(int nochdir, int noclose)
{
    /*1. 调用fork,创建子进程,并退出父进程*/
    pid_t p = fork();
    if (p == -1) {
        perror("fork failed");
        return -1;
    }
    if (p > 0) {
        _exit(0);
    }
    /*1000微妙*/
    usleep(1000);

    /*2. 脱离终端,成为会话组的组长,主进程*/
    p = setsid();
    if (p == -1) {
        perror("setsid failed.");
        return -1;
    }

    /*3. 改变家目录为根目录*/
    if (! nochdir) {
        chdir("/");
    }

    /*4. 关闭所有打开过的文件*/
    if (! noclose) {
        int dtable_size = getdtablesize();//返回每个进程所能打开的最大的文件数量
        for (;dtable_size >= 0; --dtable_size) {
            close(dtable_size);
        }
    }

    /*5.把输出重定向到日志文件中*/
    int null_fd = open("/dev/null", O_RDWR);
    dup2(null_fd, STDIN_FILENO);//输入为NULL

    int log_fd = open(LOG_FILE, O_WRONLY | O_APPEND| O_CREAT, 0666);
    if (log_fd != -1) {
        dup2(log_fd, STDOUT_FILENO);
        //dup2(log_fd, STDERR_FILENO);    
    }

    return 0;
}


int main()
{
    printf("pid = %d, ppid = %d\n", getpid(), getppid());

    Daemon(0, 0);
    
    while (1) {
        printf("daemon is running, %d, %d\n", getpid(), getppid());
    sleep(1);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/iot_shun/article/details/81026063