# 系統程式設計 - `dup2(2)` [TOC] ## 課程影片 ### 系統程式設計 2018 - W3 3 (38:50 ~ FIN) {%youtube D4DmVDYsdkY %} ## 例子 這其實是小考範例: ```c #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd; fd = open("file", O_WRONLY|O_CREAT|O_TRUNC, 0666); printf("Hello your world!\n"); dup2(fd, 1); close(fd); printf("Hello my world!\n"); return 0; } ``` ## 冷知識 ### `dup2` 是在 `dup3` 裡面的 `do_dup2` 做的 如果去追蹤上面的程式碼執行,會得到像下面的結果: ```c 3d... 0.870 us | post_ttbr_update_workaround(); 3d... | do_el0_svc() { 3d... | el0_svc_common.constprop.0() { 3.... | invoke_syscall() { 3.... | __arm64_sys_dup3() { 3.... | ksys_dup3() { 3.... 2.092 us | _raw_spin_lock(); 3...1 2.092 us | expand_files(); 3...1 2.093 us | _raw_spin_unlock(); 3.... + 14.648 us | } 3.... + 18.740 us | } 3.... + 23.037 us | } 3d... + 27.204 us | } 3d... + 28.426 us | } ``` 可以發現其實用到的是 [`ksys_dup3()`](https://elixir.bootlin.com/linux/latest/source/fs/file.c#L1159)。不過如果去查 `ksys_dup3` 的實作,又會發現裡面其實是在 `do_dup2()`: ```c static int ksys_dup3(unsigned int oldfd, unsigned int newfd, int flags) { int err = -EBADF; struct file *file; struct files_struct *files = current->files; if ((flags & ~O_CLOEXEC) != 0) return -EINVAL; if (unlikely(oldfd == newfd)) return -EINVAL; if (newfd >= rlimit(RLIMIT_NOFILE)) return -EBADF; spin_lock(&files->file_lock); err = expand_files(files, newfd); file = files_lookup_fd_locked(files, oldfd); if (unlikely(!file)) goto Ebadf; if (unlikely(err < 0)) { if (err == -EMFILE) goto Ebadf; goto out_unlock; } return do_dup2(files, file, newfd, flags); Ebadf: err = -EBADF; out_unlock: spin_unlock(&files->file_lock); return err; } ```