fcntl函數功能與實際應用(linux下中斷實現、文件分別寫與接續寫)

fcntl函數功能與實際應用(linux下中斷實現、文件分別寫與接續寫)

原型:int fcntl(int fd, int cmd, ... /* arg */ );

可以出現如下幾種參數使用:
int fcntl(int fd, int cmd); 
int fcntl(int fd, int cmd, long arg); 
int fcntl(int fd, int cmd, struct flock *lock);
[描述]
fcntl()針對(文件)描述符提供控制。參數fd是被參數cmd操作(如下面的描述)的描述符。針對cmd的不同,fcntl能夠接受第三個參數int arg。
[返回值]
fcntl()的返回值與命令有關。如果出錯,所有命令都返回-1,如果成功則返回某個其他值。

 

fcntl函數有5種功能: 


1. 複製一個現有的描述符(cmd=F_DUPFD). (文件分別寫與接續寫)

(1)New_Fd = fcntl(Mouse_Fd, F_DUPFD); 函數功能是複製一個存在的文件描述符,這個新的文件描述符與Mouse_Fd指向同一個文件,分別使用這兩個fd向指向的同一文件寫內容時,爲接續寫,因爲這種方式複製的fd在操作寫內容時,文件指針會移動,可以理解爲每個fd操作後,會使用lseek函數將文件指針向後移動,所以內容不會被覆蓋,而是接續寫,這樣可以多線程同時寫一個文件,提高寫文件效率,迅雷就是採用接續寫的方式,分段接續寫。

(2)New_Fd = dup2(Mouse_Fd,16)等效於fcntl(Mouse_Fd, F_DUPFD, 16),也是複製fd,也是接續寫,16爲指定文件描述符值,即New_Fd  = 16,如果該值被使用了,返回-1。

(3)New_Fd = dup(Mouse_Fd)等效於fcntl(Mouse_Fd, F_DUPFD, 0);,與dup2不同的是,dup是系統分配一個fd,接續寫。

(4)open連續2次打開一個文件,也會得到2個文件描述符,但是,內容時分別寫,會覆蓋原來內容,沒有lseek機制。

(5)ret = lseek(fd,0,SEEK_END),該方式可以測量文件長度, lseek(fd,3,SEEK_SET),向後移動3個字符,移動文件指針。如果該文件開始爲空,後移3個字節後,這就是空洞文件的用法。


2. 獲得/設置文件描述符標記(cmd=F_GETFD或F_SETFD). 
(1)沒用過,不太瞭解,需要時應用了再補充吧


3. 獲得/設置文件狀態標記(cmd=F_GETFL或F_SETFL). 

(1)把鼠標的文件描述符設置爲可以接受異步IO,還可以設置成很多其他屬性,詳細看man手冊,所以操作都與下面代碼類似

          flag = fcntl(Mouse_Fd,F_GETFL);  //F_GETFL取得fd的文件狀態標誌

          flag |= O_ASYNC;

          fcntl(Mouse_Fd,F_SETFL,flag) ;   //F_SETFL設置給arg描述符狀態標誌

(2)fcntl的文件狀態標誌總共有7個:前三個屬性在open一個文件時可以選擇,fcntl不能更改

         O_RDONLY , O_WRONLY , O_RDWR , O_APPEND , O_NONBLOCK , O_SYNC和O_ASYNC

(3)可更改的幾個標誌如下面的描述:
         O_NONBLOCK   非阻塞I/O,如果read(2)調用沒有可讀取的數據,或者如果write(2)操作將阻塞,則read或write調用將返回-1和EAGAIN錯誤
         O_APPEND     強制每次寫(write)操作都添加在文件大的末尾,相當於open(2)的O_APPEND標誌
         O_DIRECT     最小化或去掉reading和writing的緩存影響。系統將企圖避免緩存你的讀或寫的數據。如果不能夠避免緩存,那麼它將最小化已經被緩存了的數據造成的影響。如果這個標誌用的不夠好,將大大的降低性能
         O_ASYNC      當I/O可用的時候,允許SIGIO信號發送到進程組,例如:當有數據可以讀的時候
 

4. 獲得/設置異步I/O所有權(cmd=F_GETOWN或F_SETOWN). 

什麼是異步通知呢?首先這個機制是通過linux內核實現的,所以我們需要將一個打開的文件進行異步IO處理,需要這個文件設備驅動本身是支持異步IO機制的,只有驅動實現了這套處理機制,內核才能操作。比如鼠標,鍵盤,等等輸入設備都是支持該機制,攝像頭不知道是否支持,如果支持就可以使用。

異步通知的意思就是,一旦設備就緒,則主動通知應用程序,應用程序 根本就不需要查詢設備狀態,類似於中斷的概念,一個進程收到一個信號與處理器收到一箇中斷請求可以說是一樣的。信號是異步的,一個進程不必通過任何操作來 等待信號的到達。下面我們就看一下在linux中機制的實現方式。

在linux中,異步通知是使用信號來實現的,而在linux,大概有30種信號,比如大家熟悉的ctrl+c的SIGINT信號,進程能夠忽略或者捕獲除過SIGSTOP和SIGKILL的全部信號,當信號背捕獲以後,有相應的函數來處理它。

(1)F_GETOWN   取得當前正在接收SIGIO或者SIGURG信號的進程id或進程組id,進程組id返回的是負值(arg被忽略)

(2)F_SETOWN   設置將接收SIGIO和SIGURG信號的進程id或進程組id,進程組id通過提供負值的arg來說明(arg絕對值的一個進程組ID),否則arg將被認爲是進程id

(3)把異步IO事件的介紹進程設置爲當前進程

        fcntl(Mouse_Fd,F_SETOWN,getpid());

(4)一旦鼠標發送IO事件,使用signal信號捕獲,並執行服務函數

        signal(SIGIO,func),func函數是我們自己定義編寫的功能函數,只是通過signal函數進行綁定,一旦信號發送,捕獲並執行func函數。


5. 獲得/設置記錄鎖(cmd=F_GETLK , F_SETLK或F_SETLKW).

(1)沒用過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章