dup is used for duplicate a file descriptor.
#include <unistd.h>
int dup(int oldfd);
The dup() system call allocates a new file descriptor that refers to the same open file description as the descriptor oldfd.
(The new file descriptor number is guaranteed to be the lowest-numbered file descriptor that was unused in the calling process.)
The two file descriptors refer to the same open file description. so the old and new file descriptors may be used interchangeably.
The two file descriptors share file offset and file status flags.
The two file descriptors do not share file descriptor flags.
: On success, these system calls return the new file descriptor.
On error, -1 is returned, and errno is set to indicate the error.
🏊 example 1
#include <stdio.h>
#include <unistd.h>
int main(){
int new;
char buff[5];
new = dup(STDIN_FILENO);
read(STDIN_FILENO, buff, 5);
printf("from fd %d : %s \n", STDIN_FILENO, buff);
read(new, buff, 5);
printf("from fd %d : %s \n", new, buff);
}
--terminal--
INPUT 1234567890
OUTPUT from fd 0 : 12345
from fd 3 : 67890
After using read func successfully, file offset is changed.
STDIN_FILENO and new file description are using same file offset. so when one of them changes the file offset, the other file descriptor read file with changed file offset.
🏊 example 2
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int old_fd = open("test.txt", O_RDONLY);
int new_fd = dup(old_fd);
char buff[5];
read(old_fd, buff, 5);
printf("from fd %d : %s \n", old_fd, buff);
close(old_fd);
read(new_fd, buff, 5);
printf("from fd %d : %s \n", new_fd, buff);
close(new_fd);
}
-file test.txt-
1234567890
2345678901
--terminal--
OUTPUT from fd 3 : 12345
from fd 4 : 67890
The two file descriptors do not share file descriptor flags.
old_fd is cloesed, new_fd works well though.
int dup2(int oldfd, int newfd);
The dup2() system call allocates a new file descriptor that refers to the same open file description as the descriptor oldfd.
it uses the file descriptor number specified in newfd.
If the file descriptor newfd was previously open, it is closed before being reused; the close is performed silently (i.e., any errors during the close are not reported by dup2()).
If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.
If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.
: On success, these system calls return the new file descriptor.
On error, -1 is returned, and errno is set to indicate the error.
🏊 example 1
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int used_fd = dup(STDOUT_FILENO);
write(used_fd, "TEST 1\n", 7);
int old_fd = open("test.txt", O_RDONLY);
int new_fd = dup2(old_fd, used_fd);
char buff[5];
printf("used_fd : %d new_fd : %d\n", used_fd, new_fd);
read(old_fd, buff, 5);
printf("from fd %d : %s \n", old_fd, buff);
read(new_fd, buff, 5);
printf("from fd %d : %s \n", new_fd, buff);
write(used_fd, "TEST 2\n", 7);
close(old_fd);
close(new_fd);
}
-file test.txt-
1234567890
2345678901
--terminal--
OUTPUT TEST 1
used_fd : 3 new_fd : 3
from fd 4 : 12345
from fd 3 : 67890
As explained earlier, since new_fd duplicates the old file descriptor with new number which same as open_fd's number by using dup2, open_fd is closed. so second write isn't wokring.
🏊 example 2
int main(){
int open_fd = open("test.txt", O_RDONLY);
char buff[6];
if (read(open_fd, buff, 5) < 0){
printf("open_fd read 1 fail\n");
}
else {
printf("from fd %d : %s \n", open_fd, buff);
}
close(open_fd);
if (read(open_fd, buff, 5) < 0){
printf("open_fd read 2 fail\n");
}
else {
printf("from fd %d : %s \n", open_fd, buff);
}
printf("%s\n", strerror(errno));
}
--terminal--
OUTPUT from fd 3 : 12345
open_fd read 2 fail
Bad file descriptor
↑ for checking what error occurs when using closed file descriptor.
int main(){
int new_fd = dup2(-1, 5);
printf("new_fd : %d\n\n", new_fd);
char buff[6];
if (read(new_fd, buff, 5) < 0)
printf("read fail\n");
else
printf("from fd %d : %s \n", new_fd, buff);
printf("%s\n", strerror(errno));
}
--terminal--
OUTPUT new_fd : -1
read fail
Bad file descriptor
set up the oldfd with not a valid file descriptor, dup2 returns -1. read's return value is also -1 so everything isn't working.
The steps of closing and reusing the file descriptor newfd are performed atomically. This is important, because trying to implement equivalent functionality using close(2) and dup() would be subject to race conditions, whereby newfd might be reused between the two steps. Such reuse could happen because the main program is interrupted by a signal handler that allocates a file descriptor, or because a parallel thread allocates a file descriptor.