- 论坛徽章:
- 0
|
本帖最后由 ChiyuT 于 2011-08-31 20:36 编辑
今天被这个诡异的问题弄得茶不思来饭不想, 哪位达人能够拯救我!!
问题如下:
主程序是一段很简单的代码,我放到最前边。里边的 daemon_init 和各种打印函数都是直接照抄的《UNIX网络编程》第一卷中的附录D,我放到后边,大家有兴趣的可以自己研究。- #include <stdio.h>
- #include <syslog.h>
- #include <unistd.h>
- #include <signal.h>
- #include <string.h>
- #include <fcntl.h>
- #include <stdarg.h>
- #include <syslog.h>
- #include <stdlib.h>
- #include <errno.h>
- int main(int argc, char * argv[])
- {
- daemon_init(argv[0], 0);
-
- int fd = open("tmp1", O_RDWR | O_CREAT | O_TRUNC, 0666);
- err_ret("fd = %d\n", fd);
- write(fd, "hello world!", strlen("hello world!"));
- fd = open("tmp2", O_RDWR | O_CREAT | O_TRUNC, 0666);
- err_ret("fd = %d\n", fd);
- return 0;
- }
复制代码 然后我检查log,记录如下:- 7444 Aug 31 20:23:44 localhost ./daemon[5901]: fd = 3: Bad file descriptor
- 7445 Aug 31 20:23:44 localhost ./daemon[5901]: fd = 5: Bad file descriptor
复制代码 问题一:
为什么文件描述符不是连续的? 4 跑到哪儿去了????Bad file descriptor该怎么理解? 我确实在tmp1里边看到了我写入的内容。
继续,如果我将 daemon_init 中下边代码注释掉,即不关闭所继承的文件描述符。- /* Close off file descriptors */
- for (i = 0; i < MAXFD; i++) {
- close(i);
- }
复制代码 运行,再次检查log,记录如下:- 7448 Aug 31 20:29:27 localhost ./daemon[6100]: fd = 6: Success
- 7449 Aug 31 20:29:27 localhost ./daemon[6100]: fd = 8: Success
复制代码 问题二:
为什么文件描述符不是连续的?为什么是从6开始?3、4、5都跑哪儿去了? 7 又跑到哪儿去了???? 这次为什么是Success ??
相关代码:- #define MAXFD 64
- #define MAXLINE 4096
- int daemon_proc;
- static void err_doit(int, int, const char *, va_list);
- /*
- * Nonfatal error related to a system call,
- * print a message and return.
- */
- void err_ret(const char * fmt, ...)
- {
- va_list ap;
-
- va_start(ap, fmt);
- err_doit(1, LOG_INFO, fmt, ap);
- va_end(ap);
- return;
- }
- /*
- * Fatal error related to a system call,
- * print a message and terminate.
- */
- void err_sys(const char * fmt, ...)
- {
- va_list ap;
-
- va_start(ap, fmt);
- err_doit(1, LOG_ERR, fmt, ap);
- va_end(ap);
- exit(1);
- }
- /*
- * Fatal error related to a system call,
- * print a message, dump core, and terminate.
- */
- void err_dump(const char * fmt, ...)
- {
- va_list ap;
-
- va_start(ap, fmt);
- err_doit(1, LOG_ERR, fmt, ap);
- va_end(ap);
- abort();
- exit(1);
- }
- /*
- * Nonfatal error unrelated to a system call,
- * print a message and return
- */
- void err_msg(const char * fmt, ...)
- {
- va_list ap;
-
- va_start(ap, fmt);
- err_doit(0, LOG_INFO, fmt, ap);
- va_end(ap);
- return;
- }
- /*
- * Fatal error unrelated to a system call,
- * print a message and terminate.
- */
- void err_quit(const char * fmt, ...)
- {
- va_list ap;
-
- va_start(ap, fmt);
- err_doit(0, LOG_ERR, fmt, ap);
- va_end(ap);
- exit(1);
- }
- /*
- * Print a message and return to caller,
- * caller specifies "errnoflag" and "level".
- */
- static void err_doit(int errnoflag, int level, const char * fmt, va_list ap)
- {
- int errno_save, n;
- char buf[MAXLINE + 1];
- errno_save = errno; /* Value caller might want printed. */
- #ifdef HAVE_VSNPRINTF
- vsnprintf(buf, MAXLINE, fmt, ap);
- #else
- vsprintf(buf, fmt, ap); /* This is not safe */
- #endif
- n = strlen(buf);
- if (errnoflag) {
- snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
- }
- strcat(buf, "\n");
- if (daemon_proc) {
- syslog(level, buf);
- } else {
- fflush(stdout); /* In case stdout and stderr are the same */
- fputs(buf, stderr);
- fflush(stderr);
- }
- return;
- }
- int daemon_init(const char * name, int facility)
- {
- int i;
- pid_t pid;
- struct sigaction sa_dae;
- if ((pid = fork()) < 0) {
- return -1;
- } else if (pid) {
- _exit(0); /* Parent terminates */
- }
- /* Child 1 continue... */
- if (setsid() < 0) { /* Become session leader */
- return -1;
- }
-
- sa_dae.sa_handler = SIG_IGN;
- if ((sigaction(SIGHUP, &sa_dae, NULL)) < 0) {
- perror("sigaction");
- return -1;
- }
- if ((pid = fork()) < 0) {
- return -1;
- } else if (pid) {
- _exit(0); /* Child 1 terminates */
- }
- /* Child 2 continues... */
- daemon_proc = 1;
- // chdir("/"); /* Change working directory */
- /* Close off file descriptors */
- for (i = 0; i < MAXFD; i++) {
- close(i);
- }
- /* Redirect stdin, stdout, and stderr to /dev/null */
- open("/dev/null", O_RDONLY);
- open("/dev/null", O_RDWR);
- open("/dev/null", O_RDWR);
- openlog(name, LOG_PID, facility);
- return 0; /* Success */
- }
-
复制代码 |
|