因为这个dup的行为,就是为文件的操作,多设置几个文件描述符,看似没有什么太大的用途。
插曲(#有时在写代码的时候,也有遇到过唯独缺1的情况,从数数的习惯上来说,不科学,但从脑子意识上来说没有任何数字的那个就是第一个。老大,老二,老三,唯缺老一)
正规的解答,有可能多个线程会使用这个文件描述符来做一下同一个文件的操作。这种能解释的通吗?这种也是可能,但是应该没有人真正使用这种方式,因为可能面临多种同步问题。
下面这个链接有说明一个原因为什么要是有dup这种函数:因为老系统里的文件描述符的范围是0-255,导致一些函数比如fopen、freopen函数失败。当然这些都是老系统的问题,新的系统没有问题。
https://stackoverflow.com/questions/2619693/whats-the-purpose-of-fcntl-with-parameter-f-dupfd
On some systems, like Solaris, standard I/O with FILE only works with file descriptors 0-255 because its implementation of the FILE structure uses an 8-bit integer instead of int. If a program uses a lot of file descriptors, it’s useful to reserve file descriptors 3-255 using fnctl(fd, F_DUPFD, 256). Otherwise, functions like fopen(), freopen() and fdopen() will fail if you have 256 files open.
标准输入输出,所对应的file descriptor,是0、1、2,如果想将其他的文件描述符对应到这几个上,也需要使用dup。然后这样对于这个线程来说,这个标准输入与输出就映射到其他的文件描述符,方便实现相关功能,管道,socket pair,线程间通信。
2809 dup2(7, 0 <unfinished ...>
2809 <... dup2 resumed>) = 0
2809 dup2(7, 1 <unfinished ...>
2809 <... dup2 resumed>) = 1
2809 dup2(7, 2 <unfinished ...>
2809 <... dup2 resumed>) = 2
比如openssh,如果你要是使用strace去做sshd、ssh的跟踪,就会发现里面的dup函数调用非常多。都不知道为什么这个dup来,dup去的,有啥意思?有啥优势?可能需要查看相关代码的修改历史。
比如下面的操作,第一步,用openat打开一个只读的文件,第二步lseek,第三步,用读写打开,再dup。
2809 openat(AT_FDCWD, "/var/run/utmp", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 5
2809 _llseek(5, 0, [0], SEEK_SET) = 0
2809 access("/var/run/utmpx", F_OK) = -1 ENOENT (No such file or directory)
2809 openat(AT_FDCWD, "/var/run/utmp", O_RDWR|O_LARGEFILE|O_CLOEXEC) = 7
2809 dup2(7, 5) = 5