首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >linux上的文件描述符3有什么特别之处?

linux上的文件描述符3有什么特别之处?
EN

Stack Overflow用户
提问于 2010-08-20 22:24:48
回答 4查看 15.2K关注 0票数 19

我正在开发一个在Linux和Mac上工作的服务器应用程序。它是这样的:

启动控制器进程的主application

  • fork,在控制器process

  • terminate主application

  • the控制器进程中调用lock_down(),然后再次分叉,创建一个工人process

  • eventually控制器,控制器继续分叉更多的工作进程

我可以使用几种方法(例如syslog或一个文件)进行日志记录,但现在我正在考虑syslog。有趣的是,除非我在下面的#ifdef部分中包含了#ifdef部分,否则在控制器进程中看不到syslog输出。

工作人员在Mac和linux中处理日志时完美无缺,不管是否使用下面的ifdef‘’ed部分。控制器还在Mac中记录得完美无缺,没有# ifdef‘’ed部分,但是在linux上,如果我想看到来自控制器进程的任何输出到syslog (或相应的日志文件),则需要ifdef。

那么,为什么呢?

代码语言:javascript
复制
static int
lock_down(void)
{
    struct rlimit rl;
    unsigned int n;
    int fd0;
    int fd1;
    int fd2;

    // Reset file mode mask
    umask(0);

    // change the working directory
    if ((chdir("/")) < 0)
        return EXIT_FAILURE;

    // close any and all open file descriptors
    if (getrlimit(RLIMIT_NOFILE, &rl))
        return EXIT_FAILURE;
    if (RLIM_INFINITY == rl.rlim_max)
        rl.rlim_max = 1024;

    for (n = 0; n < rl.rlim_max; n++) {
#ifdef __linux__        
        if (3 == n) // deep magic...
            continue;
#endif
        if (close(n) && (EBADF != errno))
            return EXIT_FAILURE;
    }

    // attach file descriptors 0, 1 and 2 to /dev/null
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup2(fd0, 1);
    fd2 = dup2(fd0, 2);
    if (0 != fd0)
        return EXIT_FAILURE;

    return EXIT_SUCCESS;
}

camh是近在咫尺的,但使用closelog()是成功的主意,所以这一荣誉属于吉利斯。不过,除了关闭syslog下的文件描述符之外,还必须继续进行其他一些工作。为了使代码正常工作,我在循环之前添加了一个对closelog()的调用:

代码语言:javascript
复制
closelog();
for (n = 0; n < rl.rlim_max; n++) {
    if (close(n) && (EBADF != errno))
        return EXIT_FAILURE;
}

我依靠对手册页的逐字理解,说:

使用openlog()是可选的;它将由syslog()在必要时自动调用.

我将此解释为说,syslog将检测文件描述符是否在其下关闭。显然没有。需要在linux上使用一个显式的closelog()来告诉syslog描述符已关闭。

还有一件事仍然让我感到困惑:不使用closelog()可以阻止第一个分叉进程(控制器)甚至打开和使用日志文件。以下分叉进程可以使用syslog或日志文件,没有任何问题。也许在文件系统中存在一些缓存效应,使得第一个分叉进程有一个不可靠的“概念”,其中有哪些文件描述符可用,而下一组分叉进程被延迟到不受此影响吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-08-20 22:42:27

syslog(3)可能会使一个文件描述符保持syAdd.1-d的套接字打开;在它的脚下关闭它可能会导致问题。封闭(3)呼叫可能会有所帮助。

票数 6
EN

Stack Overflow用户

发布于 2010-08-20 22:42:53

文件描述符3的特殊方面是,它通常是分配新文件描述符的系统调用返回的第一个文件描述符,因为0、1和2通常设置为stdin、stdout和stderr。

这意味着,如果您调用的任何库函数为了执行其功能而为其内部目的分配文件描述符,它将得到fd 3。

openlog(3)库调用需要打开/dev/log才能与syslog守护进程通信。如果随后关闭所有文件描述符,则如果不以某种方式编写syslog库函数,则可能会中断它们。

票数 15
EN

Stack Overflow用户

发布于 2010-08-20 23:52:46

在Linux上调试此代码的方法是使用strace跟踪正在进行的实际系统调用;然后,对syslog使用文件描述符变得显而易见:

代码语言:javascript
复制
$ cat syslog_test.c
#include <stdio.h>
#include <syslog.h>

int main(void)
{
    openlog("test", LOG_PID, LOG_LOCAL0);
    syslog(LOG_ERR, "waaaaaah");
    closelog();
    return 0;
}
$ gcc -W -Wall -o syslog_test syslog_test.c
$ strace ./syslog_test
...
socket(PF_FILE, SOCK_DGRAM, 0)          = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
connect(3, {sa_family=AF_FILE, path="/dev/log"}, 16) = 0
send(3, "<131>Aug 21 00:47:52 test[24264]"..., 42, MSG_NOSIGNAL) = 42
close(3)                                = 0
exit_group(0)                           = ?
Process 24264 detached
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3535282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档