我的工作,那將在Linux和Mac OS X上運行的服務器應用程序它是這樣的:linux上的文件描述符3有什麼特別之處?
- 啓動主要應用
- 控制器進程的叉
- 調用lock_down()在控制過程中
- 再次叉終止主要應用
- 控制器進程,然後,創建工作進程
- 最終控制器保持分叉更多的工作呃進程
我可以使用多種方法(例如,系統日誌或文件),但現在我正在思考syslog。 「有趣的是」在控制器進程中沒有系統日誌輸出,除非我在下面包含#ifdef部分。
工作人員可以在Mac OS X和Linux中完美處理日誌,無論是否具有下面的ifdef'ed部分。該控制器還可以在沒有#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;
}
camh很接近,但是使用closelog()是這樣做的想法,所以榮譽歸功於jilles。除了在syslogs腳下關閉文件描述符之外,還有其他的東西必須繼續。爲了使代碼工作,我添加了一個調用closelog()只是在循環之前:
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或日誌文件而不會造成問題。也許文件系統中存在一些緩存效應,使第一個分支進程具有哪個文件描述符可用的不可靠「想法」,而下一組分支進程是否被充分延遲以不受此影響?
+1 //'deep magic ...':-)當你擁有Linux內核時,誰需要Harry Potter? – 2010-08-20 22:33:23
那麼在那一點上fd 3上的內容是什麼? – Gilles 2010-08-20 22:42:14
@David。與內核無關。內核中甚至沒有fd 0,1和2。 – camh 2010-08-20 23:59:07