1. 程式人生 > >3.3Apue檔案IO——fcntl函式及其使用示例

3.3Apue檔案IO——fcntl函式及其使用示例

為什麼要使用fcntl函式

假設我們已經打開了一個檔案,那麼當我想修改已開啟檔案的屬性時,就可以利用fcntl函式直接改變已開啟檔案的屬性,而不用關閉然後重新開啟來設定

fcntl函式

原型:
在這裡插入圖片描述
當第二個引數取不同的值時,fcntl有不同的功能:
cmd=F_DUPFD或F_DUPFD_CLOEXEC複製一個已有的描述符,返回新的檔案描述符
cmd=F_GETFD或F_SETFD:獲取/設定檔案描述符標誌
cmd=F_GETFL或F_SETFL:獲取檔案狀態標誌(如O_RDONLY、O_WRONLY、O_RDWR等,這三個值互斥一個檔案的訪問方式只能取這幾個值之一

,因此需要用遮蔽字O_ACCMODE取得訪問方式位,然後與這幾個值比較)。設定檔案狀態時將檔案狀態標誌設定為第三個引數的值(可更改的幾個標誌O_APPENDO_NONBLOCK等)
cmd=F_GETOWN或F_SETOWN:獲取/設定非同步IO所有權:即獲取當前接收SIGIO和SIGURG訊號的程序ID或程序組ID。設定接收SIGIO和SIGURG訊號的程序ID或程序組ID
cmd=F_GETLCK或F_SETLK或F_SETLKW:獲取/設定記錄鎖

fcntl使用示例

示例1:獲取檔案hello的狀態標誌
在這裡插入圖片描述

/// for read()
#include <unistd.h>
/// for open() #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> /// for exit() #include <stdlib.h> #define BUFFERSIZE 1024 int main(int argc, char *argv[]) { int ret; int fd = atoi(argv[1]); if ((ret = fcntl(fd, F_GETFL)) < 0) { perror("fcntl() error!"
); exit(1); } switch (ret & O_ACCMODE) { case O_RDONLY: puts("O_RDONLY");break; case O_WRONLY: puts("O_WRONLY");break; case O_RDWR: puts("O_RDWR");break; default: break; } if(ret & O_APPEND) puts("O_APPEND"); if(ret & O_NONBLOCK) puts("O_NONBLOCK"); if(ret & O_TRUNC) puts("O_TRUNC"); return 0; }

示例2:修改狀態標誌的正確方式
首先要獲得現在的標誌值,然後按照期望修改它,最後才是設定新的標誌值
如果只是執行F_SETFD或F_SETFL,這樣會關閉以前的標誌位
示例中的ret |= flags用於設定flags標誌
如果是ret &= ~flags則用於取消flags標誌

void set_fl(int fd, int flgs) {
    int ret;
    if ((ret = fcntl(fd, F_GETFL)) < 0)
        perror("fcntl() error!");
    
    ret |= flags;   /// turn on flags
    
    if (fcntl(fd, F_SETFL, ret) < 0)
        perror("fcntl() error!");
}