验证daemon程序中setsid的作用以及重定向stdin、stdout、stderr的原因

daemon程序包括第一次fork、setsid、第二次fork、改变工作目录、关闭所有打开的描述符以及重定向stdin、stdout、stderr。

setsid发挥的作用是使得当前进程成为新会话的会话头进程以及新进程组的进程组头进程,从而不再有控制终端。

将stdin、stdout和stderr重定向到/dev/null,其中一个原因是打开正常文件占用这些描述符时,诸如perror等之类函数会把非预期的数据写到正常文件中。


daemon程序中setsid的作用以及重定向stdin、stdout、stderr的原因,验证如下:


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

#define MAX_FD 64
typedef void (*sighandler_t)(int);

int main()
{
    sighandler_t ret = NULL;
    int fd = -1;
    pid_t pid = -1;
    if ((pid=fork()) < 0)
    {
        perror("fork error");
        return -1;
    }
    else if (pid > 0)//parent
        exit(0);

    if ((fd=open("/dev/tty", O_RDONLY)) < 0) //是否有控制终端,通过打开/dev/tty来判断。
        perror("open tty error");
    else
    {
         perror("open tty ok");
         close(fd);
    }
    sleep(10);
    if (setsid() < 0)
    {
        perror("setsid error");
        return -1;
    }

    if ((fd=open("/dev/tty", O_RDONLY)) < 0) //是否有控制终端,通过打开/dev/tty来判断。
        perror("open tty error");
    else
    {
        perror("open tty ok");
        close(fd);
    }

    if ((ret=signal(SIGHUP, SIG_IGN)) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }
    sleep(10);
    if ((pid=fork()) < 0)
    {
        perror("fork error");
        return -1;
    }
    else if (pid > 0)
        exit(0);

    umask(022);
    chdir("/");

    perror("close fd begin...");
    for (fd=0; fd<MAX_FD; fd++)
        close(fd);

    perror("close fd end...");
    perror("open fd start...");
    open("/dev/null", O_RDONLY);
    open("/dev/null", O_RDWR);
    //open("/dev/null", O_RDWR);
    open("log", O_CREAT | O_RDWR);
    perror("open fd end...");
    sleep(20);

    return 0;
}

终端打印:

open tty ok: Success
open tty error: No such device or address
close fd begin...: No such device or address

log文件内容:

open fd end...: Bad file descriptor

ps查看进程情况:

STAT  EUID  RUID TT       TPGID  SESS  PGRP  PPID   PID %CPU COMMAND
S        0     0 pts/0    19585 19585  6533     1  6534  0.0 start_daemon (在第一次fork之后,setsid之前)
Ss       0     0 ?           -1  6534  6534     1  6534  0.0 start_daemon (在setsid之后,第二次fork之前)
S        0     0 ?           -1  6534  6534     1  6636  0.0 start_daemon (在第二次fork之后)

结论:

在上述daemon程序中,setsid后进程组ID改变了,没有控制终端了;当打开log文件占用描述符std_err时,perror将内容写到log中了,所以为了防止不期望的事情发生,

std_in、std_out、std_err需要重定向到/dev/null。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值