题
我跟踪一个oracle过程,并发现它首先打开一个文件/etc/netconfig
作为文件句柄11
,然后通过调用参数256
fcntl
复制它作为F_DUPFD
,然后close
原始文件句柄11
。后来,它读取使用文件句柄256
。那么什么是复制的文件句柄的地步?为什么不只是在原来的文件处理工作?
12931: 0.0006 open("/etc/netconfig", O_RDONLY|O_LARGEFILE) = 11
12931: 0.0002 fcntl(11, F_DUPFD, 0x00000100) = 256
12931: 0.0001 close(11) = 0
12931: 0.0002 read(256, " # p r a g m a i d e n".., 1024) = 1024
12931: 0.0003 read(256, " t s t p i _ c".., 1024) = 215
12931: 0.0002 read(256, 0x106957054, 1024) = 0
12931: 0.0001 lseek(256, 0, SEEK_SET) = 0
12931: 0.0002 read(256, " # p r a g m a i d e n".., 1024) = 1024
12931: 0.0003 read(256, " t s t p i _ c".., 1024) = 215
12931: 0.0003 read(256, 0x106957054, 1024) = 0
12931: 0.0001 close(256) = 0
解决方案
顺便说一句,它们是文件的描述符而不是文件的手柄。后者是与fopen
及其兄弟使用而描述符是更UNIXy,使用具有C特征open
等人
有趣。我想到的唯一的原因是,一些其他的代码有特定需要的文件描述符是256,我怀疑只有甲骨文就知道了奇怪的原因。在任何情况下,你不能保证得到256,你得到的文件第一个可用的文件描述符大于或等于该数字。
这一点调查的(我不知道的每一个的有关UNIX的把我的头顶部的内脏小东西)属于一组重复的描述,例如,有属性文件位置和访问模式。有属于一个单文件描述符,重复即使其他属性,如在GNULib紧密on-exec标志。
做一个重复的(或者与dup
,dup2
或您的fcntl
)可以创建两个描述符,一个不同的文件描述符属性的方式,但我看不到是你的问题的情况下,因为第一个描述符封闭反正。正如你说的,为什么不直接使用低描述?
有趣的是,如果谷歌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个限度的其它文件。
不过说真的,这只是我的一部分凭空猜测(尽管我想认为这是比较聪明的猜测)。也请记住,这可能不是甲骨文自己这样做。访问netconfig东西在很多地方使用,因此它可能是一些底层库这样做,尤其是在事实上,大多数前面提到的网络点击率不是Oracle特有的(ftp
,remsh
等)光。
其他提示
在一些系统中,如Solaris,与文件标准I / O仅与文件描述符0-255,因为它的执行文件结构的使用8位整数不是int的工作原理。如果程序使用了大量的文件描述符,它使用fnctl是预留的文件描述符3-255有用(FD,F_DUPFD,256)。否则,像fopen()函数,freopen函数()和fdopen()函数将会失败,如果你有256个文件打开。
下面是需要保留的低编号的文件描述符的技术时的另一个例子。
假设一个进程打开了大量的文件描述符例如它接受超过1024个并发套接字连接。同时该过程还使用打开套接字连接和使用select()
,看是否套接字准备读或写的第三方库。此外,该第三方库与__FD_SETSIZE
集编译到1024(默认值)。
如果库中打开一个套接字时所有1024以下的文件描述符都在使用它,然后会得到一个描述符select()
和相关FD_ *宏无法应付。这将导致处理崩溃或未定义的行为。