我跟踪了一个oracle进程,发现它首先打开一个文件/etc/netconfig
作为文件句柄11
,然后通过使用参数{调用256
将其复制为fcntl
{1}},然后F_DUPFD
原始文件句柄close
。稍后它使用文件句柄11
读取。那么复制文件句柄有什么意义呢?为什么不只是处理原始文件句柄?
256
答案 0 :(得分:5)
在某些系统上,如Solaris,带有FILE的标准I / O仅适用于文件描述符0-255,因为它的FILE结构实现使用的是8位整数而不是int。如果程序使用大量文件描述符,则使用fnctl(fd,F_DUPFD,256)保留文件描述符3-255很有用。否则,如果打开256个文件,fopen(),freopen()和fdopen()等函数将失败。
答案 1 :(得分:4)
另外,它们是文件描述符而不是文件句柄。后者是与fopen
及其兄弟一起使用的C特征,而描述符更为UNIXy,与open
等人一起使用。
有趣。想到的唯一原因是,其他一些代码对文件描述符的特定需求为256.我怀疑只有Oracle会知道这个奇怪的原因。在任何情况下,你都不能保证得到256,你得到的文件第一个可用的文件描述符大于或等于那个数字。
从一些调查(我不知道关于UNIX的内部的每一个小东西),有一些属性属于一组重复的描述符,如文件位置和访问模式。还有其他属性属于单个文件描述符,即使是重复的,例如GNULib中的close-on-exec标志。
执行重复(使用dup
,dup2
或fcntl
)可能是一种创建两个描述符的方法,一个具有不同的文件描述符属性,但我看不到因为第一个描述符无论如何都是关闭的。如你所说,为什么不使用低描述符?
有趣的是,如果你google for netconfig f_dupfd
,你会看到fcntl
失败的类似痕迹,并继续以低描述符读取该文件,所以我对此事的想法是这是尝试尽可能保留低文件描述符。例如:
4327: open("/etc/netconfig", O_RDONLY|O_LARGEFILE) = 4
4327: fcntl(4, F_DUPFD, 0x00000100) Err#22 EINVAL
4327: read(4, " # p r a g m a i d e n".., 1024) = 1024
4327: read(4, " t s t p i _ c".., 1024) = 215
4327: read(4, 0x00296B80, 1024) = 0
4327: lseek(4, 0, SEEK_SET) = 0
4327: read(4, " # p r a g m a i d e n".., 1024) = 1024
4327: read(4, " t s t p i _ c".., 1024) = 215
4327: read(4, 0x00296B80, 1024) = 0
4327: close(4) = 0
也许该软件的某个文件描述符的字节数组有限,因此它会尝试将其他文件移到255限制以上。
但实际上,这只是我自己的猜测(尽管我认为这是相对聪明的猜测)。还要记住,Oracle本身可能不会这样做。 netconfig的东西在很多地方使用,因此它可能是一些底层库,特别是考虑到上述大多数网页命中都不是特定于Oracle的事实(ftp
,{{ 1}}等等。)
答案 2 :(得分:2)
这是另一个需要保留低编号文件描述符的技术的例子。
假设进程打开大量文件描述符,例如它接受超过1024个同时套接字连接。同时,该过程还使用第三方库来打开套接字连接并使用select()
来查看套接字是否已准备好进行读取或写入。此外,第三方库编译时__FD_SETSIZE
设置为1024(默认值)。
如果库在使用1024以下的所有文件描述符时打开套接字,那么它将获得select()
和关联的FD_ *宏无法处理的描述符。这将导致进程崩溃或未定义的行为。