Article Title: Quickly disable all open file descriptors. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
During the implementation of the daemon, a standard step is to disable all currently opened file descriptors. APUE provides the following methods:
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;
}
Whether or not when lim. rlim_curr is RLIM_INFINITY, only whether the first 1024 file descriptors are sufficient is disabled. Simply traversing all file descriptors that may be opened is uncomfortable. Fortunately, the current system calls are very fast. Otherwise, who knows how long it will take to call such a multi-system call. In addition, usually, when the daemon starts, there are not many file descriptors to open, so it is not worth a week for a few descriptors. As a result, I turned my evil little brain and made the following strange tricks:
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;
}
There are no secrets in front of the Code. Test procedure:
# 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;
}
Test results:
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