What is the purpose of fcntl with F_DUPFD parameter
I followed the oracle process and found first the file /etc/netconfig
as a file descriptor 11
and then duplicate it as 256
by calling fcntl
with a parameter F_DUPFD
and then the close
original file descriptor 11
. It is later read using a file descriptor 256
. So what's the point of duplicating a file descriptor? Why not just work with the source file descriptor?
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
source to share
As an aside, they are file descriptors, not file descriptors. The latter are a C function used with fopen
and its siblings, while descriptors are more UNIXy, for use with open
et al.
Interesting. The only reason that comes to mind is that some other piece of code has a specific need for a file descriptor, which should be 256. I suspect that only Oracle will know the bizarre reasons for this. In any case, you are not guaranteed to get 256, you will get a file with the first available file descriptor greater than or equal to this number.
From a bit of research (I don’t know every little detail about UNIX internals from my head), there are attributes that belong to the group of duplicate descriptors, such as file position and access mode. There are other attributes that refer to the same file descriptor, even if they are duplicated, such as the exec-level close flag in GNULib.
Performing a duplicate (or by using the dup
, dup2
, or fcntl
) can be a way of creating two handles with different attributes of a file descriptor, but I do not see that this is the case in your question, as the first descriptor is still closed. As you say, why not just use a low descriptor?
Interestingly, if you google for netconfig f_dupfd
, you will see similar traces where it fcntl
fails and it continues to read that file with a low descriptor, so my thoughts on this are that this is trying to keep as few file descriptors as possible. For instance:
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
Perhaps the software has a file descriptor byte array somewhere limited, so it tries to move other files above the 255 limit.
But really, this is just guesswork on my part (although I would like to think about it as a relatively reasonable guess). Also keep in mind that maybe Oracle doesn't do this. Netconfig material is used in many places, so it may be some core library that does this, especially in light of the fact that most of the above-mentioned web-hits were not specific to the Oracle ( ftp
, remsh
and so on).
source to share
On some systems, such as Solaris, standard I / O with FILE only works on file descriptors 0-255 because its implementation of the FILE structure uses an 8-bit integer instead of an int. If your program uses multiple file descriptors, it is useful to reserve file descriptors 3-255 using fnctl (fd, F_DUPFD, 256). Otherwise, functions like fopen (), freopen (), and fdopen () will crash if you have 256 files open.
source to share
Here is another example where you need the technique to reserve the lowest numbered file descriptor.
Suppose a process is opening a large number of file descriptors, for example. it accepts over 1024 concurrent socket connections. At the same time, the process also uses a third party library that opens socket connections and uses select()
to find out if the sockets are ready for reading or writing. In addition, the third party library was compiled with __FD_SETSIZE
set to 1024 (the default).
If a library opens a socket when all file descriptors below 1024 are in use, it will get a descriptor that macros select()
and associated FD_ * cannot handle . This will crash the process or undefined.
source to share