初级文件IO——fcntl 和 ioctl
在初级文件IO里面这两个函数的用法比较复杂,单独记录下
fcntl
原型
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );
功能
fcntl函数其实是File Control的缩写,通过fcntl可以设置、或者修改已打开的文件性质。
参数
fd:指向打开文件
cmd:控制命令,通过指定不同的宏来修改fd所指向文件的性质。
F_DUPFD
复制描述符,可用来用来模拟dup和dup2,后面会有例子对此用法进行说明。
使用此参数时,fcntl会从文件描述符资源池中选择一个文件描述符,该文件描述符≥参数arg。如果arg是0,表示第三个参数用不到。
返回值:返回复制后的新文件描述
F_GETFL、F_SETFL
获取、设置文件状态标志,比如在open时没有指定O_APPEND,可以使用fcntl函数来补设。
返回值:返回文件的状态
什么时候需要fcntl来补设?
当文件描述符不是你自己open得到,而是调用别人给的函数,别人的函数去open某个文件,然后再将文件描述符返回给你用,在这种情况下,我们是没办法去修改被人的函数,在他调用的open函数里补加文件状态标志。此时就可以使用fcntl来补设了,使用fcntl补设时,你只需要知道文件描述符即可。
F_GETFD、F_SETFD
读取、设置文件描述标识
F_GETOWN、F_SETOWN
F_GETLK 或 F_SETLK 或 F_SETLKW
返回值
调用成功:返回值视具体参数而定
调用失败:返回-1,并把错误号设置给errno。
代码演示
fcntl 模拟dup和dup2
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <errno.h> 7 8 int main(void) 9 { 10 int fd = 0; 11 12 fd = open("./file.txt", O_RDWR); 13 if(-1 == fd) 14 { 15 printf("open fail: %d\n", errno); 16 return 0; 17 } 18 19 /* 模拟dup */ 20 //close(1); 21 //dup(fd); 22 23 //close(1); 24 //fcntl(fd, F_DUPFD, 0); 25 26 /* 模拟dup2 */ 27 //dup2(fd, 1); 28 close(1); 29 fcntl(fd, F_DUPFD, 1); 30 31 printf("hello world!!\n"); 32 33 return 0; 34 }
虽然fcntl()可以模拟文件描述符复制,但实际应用中还是使用dup、dup2
fcntl补设O_APPEND文件状态标志
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <errno.h> 7 8 int open_fun1(void) 9 { 10 int fd = open("./file.txt", O_RDWR); 11 if(-1 == fd) 12 { 13 printf("open fail: %d\n", errno); 14 return 0; 15 } 16 return fd; 17 } 18 19 int open_fun2(void) 20 { 21 int fd = open("./file.txt", O_RDWR); 22 if(-1 == fd) 23 { 24 printf("open fail: %d\n", errno); 25 return 0; 26 } 27 return fd; 28 } 29 30 int main(void) 31 { 32 int fd1 = 0; 33 int fd2 = 0; 34 int flag = 0; 35 36 fd1 = open_fun1(); 37 fd2 = open_fun2(); 38 39 /* 直接制定F_SETFL时,会直接使用新的标志,去修改掉就的标志 40 返回的是新设置的标志 41 */ 42 flag = O_WRONLY|O_TRUNC|O_APPEND; 43 fcntl(fd1, F_SETFL, flag); 44 45 /* 保留原有标志,然后在原有标志的基础上,叠加新标志 */ 46 flag = fcntl(fd2, F_GETFL, 0);//获取原有标志 47 flag = flag | O_TRUNC | O_APPEND;//叠加 48 fcntl(fd2, F_SETFL, flag); //设置回去 49 50 while(1) 51 { 52 write(fd1, "hello\n", 6); 53 sleep(1); 54 write(fd2, "world\n", 6); 55 } 56 57 return 0; 58 }
ioctl
XXXX
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决