Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1990008
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: LINUX

2010-08-12 16:42:40

守护进程的实现过程中,有一个标准步骤就是关闭当前打开的所有文件描述符。APUE上给的做法是:

int close_all_fd(void)
{
        struct rlimit lim;
        unsigned int i;

        if (getrlimit(RLIMIT_NOFILE, &lim) < 0)
                return -1;
        if (lim.rlim_cur == RLIM_INFINITY)
                lim.rlim_cur = 1024;
        for (i = 0; i < lim.rlim_cur; i ++) {
#ifdef MYPERF
                if (i == 1)
                        continue;
#endif
                if (close(i) < 0 && errno != EBADF)
                        return -1;
        }

        return 0;
}


且不论当lim.rlim_curr为RLIM_INFINITY的时候,只关闭前1024个文件描述符是否充分,单单这个遍历所有可能打开的文件描述符就有些让人觉得不爽。值得庆幸的是现在的系统调用都很快,不然这么多系统调用谁知道会耗费多久时间啊。并且,通常情况下,守护进程启动的时候,打开的文件描述符就不多,为了少数几个描述符就如此大费周章不值当。故而我又转动我邪恶的小脑瓜,捣鼓出了以下奇技淫巧:

int close_all_fd(void)
{
        DIR *dir;
        struct dirent *entry, _entry;
        int retval, rewind, fd;

        dir = opendir("/dev/fd");
        if (dir == NULL)
                return -1;

        rewind = 0;
        while (1) {
                retval = readdir_r(dir, &_entry, &entry);
                if (retval != 0) {
                        errno = -retval;
                        retval = -1;
                        break;
                }
                if (entry == NULL) {
                        if (!rewind)
                                break;
                        rewinddir(dir);
                        rewind = 0;
                        continue;
                }
                if (entry->d_name[0] == '.')
                        continue;
                fd = atoi(entry->d_name);
                if (dirfd(dir) == fd)
                        continue;
#ifdef MYPERF
                if (fd == 1)
                        continue;
#endif
                retval = close(fd);
                if (retval != 0)
                        break;
                rewind = 1;
        }

        closedir(dir);

        return retval;
}


代码面前了无秘密,故不再费口舌解释。上测试程序:

#define MYPERF

int close_all_fd()
{
        ...
}

int main(void)
{
        struct timeval tv1, tv2, tv;

        gettimeofday(&tv1, NULL);
        close_all_fd();
        gettimeofday(&tv2, NULL);

        timersub(&tv2, &tv1, &tv);
        printf("%ld.%06ld\n", tv.tv_sec, tv.tv_usec);

        return 0;
}


测试结果:

xiaosuo@gentux test $ ./apue.out
0.000147
xiaosuo@gentux test $ ./mine.out
0.000123
xiaosuo@gentux test $ ./apue.out
0.000150
xiaosuo@gentux test $ ./mine.out
0.000109
xiaosuo@gentux test $ ./apue.out
0.000156
xiaosuo@gentux test $ ./mine.out
0.000109

阅读(10236) | 评论(3) | 转发(0) |
0

上一篇:accept filter

下一篇:全国哀悼日

给主人留下些什么吧!~~

riaqn2013-05-10 11:23:26

所以这本书叫APUE而不是APLE,因为你的方法只对于Linux适用,在其他任何UNIX下都没有这个文件夹。大师的代码岂是你能质疑的。

xiaosuo2010-08-12 21:37:23

很明显,你没有看懂代码。/dev/fd这个目录下的文件是当前进程打开的文件描述符,他们是指向真实文件(socket,pipe,普通文件等)的链接,和/proc/self/fd一样,实际上/dev/fd就是指向/proc/self/fd的链接,至少在Linux系统是这样。所以read这个目录就能知道当前文件打开了哪些文件描述符,也就能更有针对性地关闭文件描述符了。 xiaosuo@gentux ~ $ ls -l /dev/fd lrwxrwxrwx 1 root root 13 Aug 10 14:49 /dev/fd -> /proc/self/fd xiaosuo@gentux ~ $ ls -l /dev/fd/ total 0 lrwx------ 1 xiaosuo xiaosuo 64 Aug 12 21:37 0 -> /dev/pts/6 lrwx------ 1 xiaosuo xiaosuo 64 Aug 12 21:37 1 -> /dev/pts/6 lrwx------ 1 xiaosuo xiaosuo 64 Aug 12 21:37 2

chinaunix网友2010-08-12 18:26:33

只关闭了fd目录下的几个描述符,其他的没有关闭啊