初級文件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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM