初级文件IO——fcntl 和 ioctl

在初级文件IO里面这两个函数的用法比较复杂,单独记录下

fcntl

原型

#include <unistd.h>
#include <fcntl.h>
        
int fcntl(int fd, int cmd, ... /* arg */ );
View Code

功能

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 }
View Code

虽然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 }
View Code

ioctl

XXXX

 

猜你喜欢

转载自www.cnblogs.com/kelamoyujuzhen/p/9688307.html