col*_*ing 19 c c++ linux macos
我正在开发一个可以在Linux和Mac OS X上运行的服务器应用程序.它是这样的:
我可以使用几种方法(例如syslog或文件)进行日志记录,但是现在我正在思考syslog."有趣"的是,除非我在下面包含#ifdef部分,否则在控制器进程中看不到任何syslog输出.
无论是否有ifdef'ed部分,工作人员都可以在Mac OS X和Linux中完美地处理日志.控制器也可以在没有#ifdef'ed部分的情况下在Mac OS X中完美记录,但是在linux上,如果我想从控制器进程看到syslog(或者那个日志文件)的任何输出,则需要ifdef.
那么,为什么呢?
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;
}
Run Code Online (Sandbox Code Playgroud)
camh很接近,但是使用closelog()就是这个想法,所以荣誉归于jilles.除了从syslogs脚下关闭文件描述符之外,还有其他事情必须继续.为了使代码工作,我在循环之前添加了对closelog()的调用:
closelog();
for (n = 0; n < rl.rlim_max; n++) {
if (close(n) && (EBADF != errno))
return EXIT_FAILURE;
}
Run Code Online (Sandbox Code Playgroud)
我依靠对手册页的逐字理解,说:
openlog()的使用是可选的; 如有必要,它将由syslog()自动调用...
我将此解释为说syslog会检测文件描述符是否在其下关闭.显然它没有.需要在linux上使用显式的closelog()来告诉syslog描述符已关闭.
还有一件令我困惑的事情是,不使用closelog()会阻止第一个分叉进程(控制器)甚至打开并使用日志文件.以下分叉进程可以使用syslog或日志文件,没有任何问题.也许在文件系统中存在一些缓存效果,这使得第一个分叉进程具有哪个文件描述符可用的不可靠"想法",而下一组分叉进程被充分延迟而不受此影响?
cam*_*amh 14
文件描述符3的特殊之处在于它通常是从分配新文件描述符的系统调用返回的第一个文件描述符,因为通常为stdin,stdout和stderr设置0,1和2.
这意味着如果您调用的任何库函数为其内部目的分配文件描述符以执行其功能,则它将获得fd 3.
openlog(3)库调用需要打开/dev/log才能与syslog守护进程通信.如果随后关闭所有文件描述符,则可能会破坏syslog库函数(如果它们不是以处理它的方式编写的).
在Linux上调试它的方法是用来strace跟踪正在进行的实际系统调用; 然后使用syslog的文件描述符变得很明显:
$ 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10409 次 |
| 最近记录: |