in reply to Duping filehandles
It is impossible to dupe a filehandle that way in Unix. The only thing you can do is to open the same filename multiple times.
Le me elaborate. There are two easy ways you can copy a filehandle in unix (there are others in fact): you can copy it explicitly with the dup, dup2, or fcntl F_DUPFD calls; or it can be copied implicitly if you fork.
However, when a handle is copied this way, they will share most of their properties, which means you'll have only one file position, so if you read/write/seek on one of them, that will affect both handle's file position the same way. They also share the so called "file status flags" and the fcntl locks.
The duplicated filehandles can be closed separately, and they also have a single flag that can be set separately: this is the file descriptor flag FD_CLOEXEC, which determines if the filehandle would be closed on exec.
You can read more of these properties from the glibc info, or the man pages fcntl(2), dup(2), dup2(2).
Dominus explains quite clearly why file positions have to be shared by dupe filehandles in slide 21 of Internals of Familiar Unix Commands. While he only mentions fork, this applies to dup2 too, as when a shell starts a program redirected to a file, it has to dup2 the filehandle to the proper filedescriptor number (0 for stdin, 1 for stdout).
Now let me say a few words about perl. In perl, you don't directly manipulate file descriptors: you have filehandles (IO handles), so that output can be buffered.
Basically we have this. Let's say you open a file with
Then we have a scalar $F which is pointing to a perl filehandle object, which is pointing to a filedescriptor (which is just a number in userspace, but refers to a structure in kernel space), which filedescriptor structure is pointing to a file status structure.open $F, ">", "filename" or die;
If you say $G = $F, you just copy the refernce to the filehandle object, and the two references are completely identical. If you close $G, then $F gets closed too, but if you don't, you have to both $F = 0; and $G = 0; to get the filedescriptor closed implicitly by the refcounter. If you binmode $F, then $G gets binmoded too.
If you instead say open $H, ">&=", $F or die;, then the filehandle object is copied but the filedescriptor is the same. In this case, you can close $F and $H separately (either implicitly by refcount or the close function) but only if both are closed will perl really close the underlying filedescriptor. You can binmode $F and $H separately, and this won't affect the other one. $F and $H will share the same fileno, and the same file position (tell).
You can open $I, ">&", $F or die;, which is different from the above only by an equals sign. This is indistinguishable from the above as long as you only use the handles from perl and you don't fork or exec. However, here a new filedescriptor gets created (with dup), and you can set the FD_CLOEXEC flag separately so that a fork-execed process would inherit one of the descriptors but not the other. $F and $I will be two filehandles pointing to two different filedescriptors which point to the same file status structure. Thus, they can be binmoded separately, they have different filenos, but they share the same file position.
The only way you can create a new file status flag to a the same file is a real open, such as open $J, ">", "filename" or die;. Only then will $J and $F have different file positions in the same file, and will they be so that if you lock a part of the file with fcntl, you can not write that part of the file with the other, nor can you unlock that part with the other filehandle.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Duping filehandles
by creamygoodness (Curate) on Jan 20, 2006 at 16:53 UTC | |
|
Re^2: Duping filehandles
by ff (Hermit) on Jun 16, 2006 at 14:12 UTC |