APUE says
fd = open("/dev/fd/0", mode); is equivalent to fd = dup (0);, and mode is completely ignored. It seems this is the case in Solaris, but wrong in Linux. (I don’t have access to other Unices at this moment.)A test program:
01 #include <unistd.h>
02 #include <fcntl.h>
03
04 int main ()
05 {
06 close (0);
07 printf ("%d\n", open ("a.txt", O_RDONLY)); // Should be 0
08 //int f2 = open ("/dev/fd/0", O_WRONLY);
09 int f2 = dup(0);
10 printf ("%d\n", f2);
11 write (f2, "Hello world\n", 12);
12 return 0;
13 }Let’s run the program with an empty
a.txt. Certainly the write function in Line 11 is going to fail.Now, let’s comment out Line 9 and uncomment line 8 and try it again.
First I ran it in Solaris, the
write call still failed. The behavior is like what APUE tells us.Try it again in Linux - It was successful!
It seems that in Linux,
/dev/fd/0 is considered by open as nothing but a normal symlink to a.txt. So it returns a completely new descriptor instead of a duplicate of the old.Let’s try it again with a shell script:
rm -f a.txt touch a.txt exec 0<a.txt exec 3>/dev/fd/0 echo 'Hello world' >&3 cat a.txt
Run it in Linux (with DASH or BASH): Both outputed ‘Hello world’.
Run it in Solaris (with Bourne shell and BASH): Both failed, outputting nothing (Bourne shell) or failing with ‘Bad file number’ (BASH).
Conclusion:
(1) Solaris handles
/dev/fd/.. specially, as APUE tells us;(2) Linux simply consider
/dev/fd/0 a symlink to the actual file.(I’ll try later how Linux handles
open("/dev/fd/0",mode) if the descriptor is an anonymous pipe or socket or something else that a normal symlink is unable to link to.Kernels used in the above tests:
Linux:
Linux desktop 2.6.28-gentoo #4 SMP Mon Jan 12 17:39:23 CST 2009 x86_64 Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz GenuineIntel GNU/LinuxSolaris:
SunOS caesar 5.8 Generic_117350-51 sun4u sparc SUNW,Ultra-80 Solaris


try opening /proc/PID/fd/FD
ReplyDelete