企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 简介 dup() 和 dup2() 是两个非常有用的系统调用,都是用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件。 这个过程类似于现实生活中的配钥匙,钥匙相当于文件描述符,锁相当于文件,本来一个钥匙开一把锁,相当于,一个文件描述符对应一个文件,现在,我们去配钥匙,通过旧的钥匙复制了一把新的钥匙,这样的话,旧的钥匙和新的钥匙都能开启这把锁。 对比于 dup(), dup2() 也一样,通过原来的文件描述符复制出一个新的文件描述符,这样的话,原来的文件描述符和新的文件描述符都指向同一个文件,我们操作这两个文件描述符的任何一个,都能操作它所对应的文件。 # dup函数 ~~~ #include <unistd.h> ​ int dup(int oldfd); 功能: 通过 oldfd 复制出一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符,最终 oldfd 和新的文件描述符都指向同一个文件。 参数: oldfd : 需要复制的文件描述符 oldfd 返回值: 成功:新文件描述符 失败: -1 ~~~ ![](https://img.kancloud.cn/d8/7b/d87bcea273964cc0ee8877d30b9f8a51_861x334.png) ~~~ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> //文件描述符复制 int main(void) { int fd = -1; int newfd = -1; //1. 打开文件 fd = open("txt", O_RDWR | O_CREAT, 0644); if (-1 == fd) { perror("open"); return 1; } //2. 复制文件描述符 //newfd = dup(fd); newfd = 10; //如果newfd文件描述符已经与其它文件关联, 那么先close, 然后在使用该数字 newfd = dup2(fd, newfd); if (-1 == newfd) { perror("dup"); return 1; } printf("fd : %d newfd: %d\n", fd, newfd); //3. 关闭文件 close(fd); close(newfd); return 0; } ~~~ # dup2函数 ~~~ #include <unistd.h> ​ int dup2(int oldfd, int newfd); 功能: 通过 oldfd 复制出一个新的文件描述符 newfd,如果成功,newfd 和函数返回值是同一个返回值,最终 oldfd 和新的文件描述符 newfd 都指向同一个文件。 参数: oldfd : 需要复制的文件描述符 newfd : 新的文件描述符,这个描述符可以人为指定一个合法数字(0 - 1023),如果指定的数字已经被占用(和某个文件有关联),此函数会自动关闭 close() 断开这个数字和某个文件的关联,再来使用这个合法数字。 返回值: 成功:返回 newfd 失败:返回 -1 ~~~ ~~~ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> //文件描述符复制 int main(void) { int fd = -1; int newfd = -1; //1. 打开文件 Ctrl + P fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644); if (-1 == fd) { perror("open"); return 1; } //2. 复制文件描述符 //newfd = dup(fd); //newfd = 10; //如果newfd文件描述符已经与其它文件关联, 那么先close, 然后在使用该数字 newfd = dup2(fd, newfd); if (-1 == newfd) { perror("dup"); return 1; } printf("fd : %d newfd: %d\n", fd, newfd); write(fd, "123456789", 9); write(newfd, "ABCDEFGHI", 9); //3. 关闭文件 close(fd); close(newfd); return 0; } ~~~ 示例分析 ![](https://img.kancloud.cn/86/30/8630e56731d76c822204c4fa6ed473df_503x444.png) # fcnlt函数 ~~~ #include <unistd.h> #include <fcntl.h> ​ int fcntl(int fd, int cmd, ... /* arg */); 功能:改变已打开的文件性质,fcntl针对描述符提供控制。 参数: fd:操作的文件描述符 cmd:操作方式 arg:针对cmd的值,fcntl能够接受第三个参数int arg。 返回值: 成功:返回某个其他值 失败:-1 fcntl函数有5种功能: 1) 复制一个现有的描述符(cmd=F_DUPFD) 2) 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD) 3) 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL) 4) 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN) 5) 获得/设置记录锁(cmd=F_GETLK, F_SETLK或F_SETLKW) ~~~ ~~~ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> //文件描述符复制 int main(void) { int fd = -1; int ret = -1; //1. 打开文件 Ctrl + P fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644); if (-1 == fd) { perror("open"); return 1; } //2. 获取文件状态标志 ret = fcntl(fd, F_GETFL); if (-1 == ret) { perror("fcntl"); return 1; } if (ret & O_NONBLOCK) { printf("设置为非阻塞...\n"); } else { printf("设置为阻塞...\n"); } //设置为非阻塞 ret |= O_NONBLOCK; ret = fcntl(fd, F_SETFL, ret); if (-1 == ret) { perror("fcntl"); return 1; } //2. 获取文件状态标志 ret = fcntl(fd, F_GETFL); if (-1 == ret) { perror("fcntl"); return 1; } if (ret & O_NONBLOCK) { printf("设置为非阻塞...\n"); } else { printf("设置为阻塞...\n"); } //3. 关闭文件 close(fd); return 0; } ~~~