<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      APUE學(xué)習(xí)筆記之文件IO(三)

      本文記錄《UNIX環(huán)境高級編程》第3版中第3章文件IO的一些知識點。


      文件描述符

      對于內(nèi)核而言,所有打開的文件都通過文件描述符引用。文件描述符是一個非負(fù)整數(shù)。當(dāng)打開一個現(xiàn)有文件或創(chuàng)建一個新文件時,內(nèi)核向進(jìn)程返回一個文件描述符。當(dāng)讀、寫一個文件時,使用opencreat返回的文件描述符標(biāo)識該文件,將其作為參數(shù)傳送給readwrite

      按照慣例,UNIX系統(tǒng)shell把文件描述符0與進(jìn)程的標(biāo)準(zhǔn)輸入關(guān)聯(lián),文件描述符1與標(biāo)準(zhǔn)輸出關(guān)聯(lián),文件描述符2與標(biāo)準(zhǔn)錯誤關(guān)聯(lián)。這是各種shell以及很多應(yīng)用程序使用的慣例,與UNIX內(nèi)核無關(guān)。

      在符合POSIX.1的應(yīng)用程序中,幻數(shù)0、1、2雖然已被標(biāo)準(zhǔn)化,但應(yīng)當(dāng)把它們替換成符號常量STDIN_FILENO、STDOUT_FILENOSTDERR_FILENO以提高可讀性。這些常量都在頭文件<unistd.h>中定義。


      函數(shù)open和openat

      調(diào)用openopenat函數(shù)可以打開或創(chuàng)建一個文件。

      #include <fcntl.h>
      int open(const char *path, int oflag,... /* mode_t mode */);
      int openat(int fd, const char *path, int oflag, ... /* mode_t mode */ );
      // 兩函數(shù)的返回值:若成功,返回文件描述符;若出錯,返回?1
      

      將最后一個參數(shù)寫為...,ISO C用這種方法表明余下的參數(shù)的數(shù)量及其類型是可變的。對于open函數(shù)而言,僅當(dāng)創(chuàng)建新文件時才使用最后這個參數(shù)。

      path參數(shù)是要打開或創(chuàng)建文件的名字。oflag參數(shù)可用來說明此函數(shù)的多個選項。用下列一個或多個常量進(jìn)行“或”運算構(gòu)成oflag參數(shù)(這些常量在頭文件<fcntl.h>中定義)。

      • O_RDONLY 只讀打開。

      • O_WRONLY 只寫打開。

      • O_RDWR 讀、寫打開。

      • O_EXEC 只執(zhí)行打開。

      • O_SEARCH 只搜索打開(應(yīng)用于目錄)。

      在這5個常量中必須指定一個且只能指定一個。下列常量則是可選的。

      • O_APPEND 每次寫時都追加到文件的尾端。

      • O_CLOEXECFD_CLOEXEC常量設(shè)置為文件描述符標(biāo)志。

      • O_CREAT 若此文件不存在則創(chuàng)建它。使用此選項時,open函數(shù)需同時說明第3個參數(shù)mode(openat函數(shù)需說明第4個參數(shù)mode),用mode指定該新文件的訪問權(quán)限位。

      • O_DIRECTORY 如果path引用的不是目錄,則出錯。

      • O_EXCL 如果同時指定了O_CREAT,而文件已經(jīng)存在,則出錯。用此可以測試一個文件是否存在,如果不存在,則創(chuàng)建此文件,這使測試和創(chuàng)建兩者成為一個原子操作。

      • O_NOCTTY 如果path引用的是終端設(shè)備,則不該將設(shè)備分配作為此進(jìn)程的控制終端。

      • O_NOFOLLOW 如果path引用的是一個符號鏈接,則出錯。

      • O_NONBLOCK 如果path引用的是一個FIFO、一個塊特殊文件或一個字符特殊文件,則此選項為文件的本次打開操作和后續(xù)的I/O操作設(shè)置非阻塞方式。

      • O_SYNC 使每次write等待物理I/O操作完成,包括由該write操作引起的文件屬性更新所需的I/O。

      • O_TRUNC 如果此文件存在,而且為只寫或讀-寫成功打開,則將其長度截斷為0。

      openopenat函數(shù)返回的文件描述符一定是最小的未用描述符數(shù)值。例如,一個應(yīng)用程序可以先關(guān)閉標(biāo)準(zhǔn)輸出(通常是文件描述符1),然后打開另一個文件,執(zhí)行打開操作前就能了解到該文件一定會在文件描述符1上打開。


      函數(shù)close

      可調(diào)用close函數(shù)關(guān)閉一個打開文件。

      #include <unistd.h>
      int close (int fd); //返回值:若成功,返回0;若出錯,返回?1
      

      關(guān)閉一個文件時還會釋放該進(jìn)程加在該文件上的所有記錄鎖。當(dāng)一個進(jìn)程終止時,內(nèi)核自動關(guān)閉它所有的打開文件。很多程序都利用了這一功能而不顯式地用close關(guān)閉打開文件。


      函數(shù)lseek

      每個打開文件都有一個與其相關(guān)聯(lián)的“當(dāng)前文件偏移量”(current file offset)。它通常是一個非負(fù)整數(shù),用以度量從文件開始處計算的字節(jié)數(shù)(本節(jié)稍后將對“非負(fù)”這一修飾詞的某些例外進(jìn)行說明)。通常,讀、寫操作都從當(dāng)前文件偏移量處開始,并使偏移量增加所讀寫的字節(jié)數(shù)。按系統(tǒng)默認(rèn)的情況,當(dāng)打開一個文件時,除非指定O_APPEND選項,否則該偏移量被設(shè)置為0。

      可以調(diào)用lseek顯式地為一個打開文件設(shè)置偏移量。

      #include <unistd.h>
      off_t lseek(int fd, off_t offset, int whence);
      // 返回值:若成功,返回新的文件偏移量;若出錯,返回為?1
      

      對參數(shù)offset的解釋與參數(shù)whence的值有關(guān)。

      • 若whence是SEEK_SET,則將該文件的偏移量設(shè)置為距文件開始處offset個字節(jié)。
      • 若whence是SEEK_CUR,則將該文件的偏移量設(shè)置為其當(dāng)前值加offset,offset可為正或負(fù)。
      • 若whence是SEEK_END,則將該文件的偏移量設(shè)置為文件長度加offset,offset可正可負(fù)。

      lseek成功執(zhí)行,則返回新的文件偏移量,為此可以用下列方式確定打開文件的當(dāng)前偏移量:

      off_t currpos;
      currpos = lseek(fd, 0, SEEK_CUR);
      

      這種方法也可用來確定所涉及的文件是否可以設(shè)置偏移量。如果文件描述符指向的是一個管道、FIFO或網(wǎng)絡(luò)套接字,則lseek返回?1,并將errno設(shè)置為ESPIPE。

      通常,文件的當(dāng)前偏移量應(yīng)當(dāng)是一個非負(fù)整數(shù),但是,某些設(shè)備也可能允許負(fù)的偏移量。但對于普通文件,其偏移量必須是非負(fù)值。因為偏移量可能是負(fù)值,所以在比較lseek的返回值時應(yīng)當(dāng)謹(jǐn)慎,不要測試它是否小于0,而要測試它是否等于?1。

      因為偏移量(off_t)是帶符號數(shù)據(jù)類型,所以文件的最大長度會減少一半。例如,若off_t是32位整型,則文件最大長度是\(2^{31}-1\)個字節(jié)。

      lseek僅將當(dāng)前的文件偏移量記錄在內(nèi)核中,它并不引起任何I/O操作。然后,該偏移量用于下一個讀或?qū)懖僮鳌?/p>

      文件偏移量可以大于文件的當(dāng)前長度,在這種情況下,對該文件的下一次寫將加長該文件,并在文件中構(gòu)成一個空洞,這一點是允許的。位于文件中但沒有寫過的字節(jié)都被讀為0。

      文件中的空洞并不要求在磁盤上占用存儲區(qū)。具體處理方式與文件系統(tǒng)的實現(xiàn)有關(guān),當(dāng)定位到超出文件尾端之后寫時,對于新寫的數(shù)據(jù)需要分配磁盤塊,但是對于原文件尾端和新開始寫位置之間的部分則不需要分配磁盤塊。


      函數(shù)read

      調(diào)用read函數(shù)從打開文件中讀數(shù)據(jù)。

      #include <unistd.h>
      ssize_t read(int fd, void *buf, size_t nbytes);
      //返回值:讀到的字節(jié)數(shù),若已到文件尾,返回0;若出錯,返回?1
      //如read成功,則返回讀到的字節(jié)數(shù)。如已到達(dá)文件的尾端,則返回0。
      

      有多種情況可使實際讀到的字節(jié)數(shù)少于要求讀的字節(jié)數(shù):

      • 讀普通文件時,在讀到要求字節(jié)數(shù)之前已到達(dá)了文件尾端。例如,若在到達(dá)文件尾端之前有30個字節(jié),而要求讀100個字節(jié),則read返回30。下一次再調(diào)用read時,它將返回0(文件尾端)。
      • 當(dāng)從終端設(shè)備讀時,通常一次最多讀一行。
      • 當(dāng)從網(wǎng)絡(luò)讀時,網(wǎng)絡(luò)中的緩沖機制可能造成返回值小于所要求讀的字節(jié)數(shù)。
      • 當(dāng)從管道或FIFO讀時,如若管道包含的字節(jié)少于所需的數(shù)量,那么read將只返回實際可用的字節(jié)數(shù)。
      • 當(dāng)從某些面向記錄的設(shè)備(如磁帶)讀時,一次最多返回一個記錄。
      • 當(dāng)一信號造成中斷,而已經(jīng)讀了部分?jǐn)?shù)據(jù)量時。

      函數(shù)write

      調(diào)用write函數(shù)向打開文件寫數(shù)據(jù)。

      #include <unistd.h>
      ssize_t write(int fd, const void *buf, size_t nbytes);
      // 返回值:若成功,返回已寫的字節(jié)數(shù);若出錯,返回?1
      

      其返回值通常與參數(shù)nbytes的值相同,否則表示出錯。write出錯的一個常見原因是磁盤已寫滿,或者超過了一個給定進(jìn)程的文件長度限制。

      對于普通文件,寫操作從文件的當(dāng)前偏移量處開始。如果在打開該文件時,指定了O_APPEND選項,則在每次寫操作之前,將文件偏移量設(shè)置在文件的當(dāng)前結(jié)尾處。在一次成功寫之后,該文件偏移量增加實際寫的字節(jié)數(shù)。


      I/O的效率

      下面的程序使用readwrite函數(shù)復(fù)制一個文件。

      #include "apue.h"
      
      #define BUFFSIZE 4096
      
      int main(void){
        int n;
        char buf[BUFFSIZE];
        while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
        {
          if(write(STDOUT_FILENO, buf, n) != n)
            err_sys("write error");
        }
        if(n < 0)
          err_sys("read error");
      
        exit(0);
      }
      

      如何選取BUFFSIZE值?在回答此問題之前,先用各種不同的BUFFSIZE值來運行此程序。下圖顯示了用20種不同的緩沖區(qū)長度,讀516 581 760字節(jié)的文件所得到的結(jié)果。

      Linux上用不同緩沖長度進(jìn)行讀操作的時間結(jié)果

      用上面的程序讀文件,其標(biāo)準(zhǔn)輸出被重新定向到/dev/null上。此測試所用的文件系統(tǒng)是Linux ext4文件系統(tǒng),其磁盤塊長度為4096字節(jié)(磁盤塊長度由st_blksize表示)。這也證明了圖中系統(tǒng)CPU時間的幾個最小值差不多出現(xiàn)在BUFFSIZE為4096及以后的位置,繼續(xù)增加緩沖區(qū)長度對此時間幾乎沒有影響。

      大多數(shù)文件系統(tǒng)為改善性能都采用某種預(yù)讀(read ahead)技術(shù)。當(dāng)檢測到正進(jìn)行順序讀取時,系統(tǒng)就試圖讀入比應(yīng)用所要求的更多數(shù)據(jù),并假想應(yīng)用很快就會讀這些數(shù)據(jù)。預(yù)讀的效果可以從圖中看出,緩沖區(qū)長度小至32字節(jié)時的時鐘時間與擁有較大緩沖區(qū)長度時的時鐘時間幾乎一樣。


      文件共享

      UNIX系統(tǒng)支持在不同進(jìn)程間共享打開文件。在介紹dup函數(shù)之前,先要說明這種共享。為此先介紹內(nèi)核用于所有I/O的數(shù)據(jù)結(jié)構(gòu)。

      內(nèi)核使用3種數(shù)據(jù)結(jié)構(gòu)表示打開文件,它們之間的關(guān)系決定了在文件共享方面一個進(jìn)程對另一個進(jìn)程可能產(chǎn)生的影響。

      (1)每個進(jìn)程在進(jìn)程表中都有一個記錄項,記錄項中包含一張打開文件描述符表,可將其視為一個矢量,每個描述符占用一項。與每個文件描述符相關(guān)聯(lián)的是:

      a.文件描述符標(biāo)志(close_on_exec)

      b.指向一個文件表項的指針。

      (2)內(nèi)核為所有打開文件維持一張文件表。每個文件表項包含:

      a.文件狀態(tài)標(biāo)志(讀、寫、添寫、同步和非阻塞等);

      b.當(dāng)前文件偏移量;

      c.指向該文件v節(jié)點表項的指針。

      (3)每個打開文件(或設(shè)備)都有一個 v 節(jié)點(v-node)結(jié)構(gòu)。v節(jié)點包含了文件類型和對此文件進(jìn)行各種操作函數(shù)的指針。對于大多數(shù)文件,v節(jié)點還包含了該文件的i節(jié)點(i-node,索引節(jié)點)。這些信息是在打開文件時從磁盤上讀入內(nèi)存的,所以,文件的所有相關(guān)信息都是隨時可用的。例如,i節(jié)點包含了文件的所有者、文件長度、指向文件實際數(shù)據(jù)塊在磁盤上所在位置的指針等。

      Linux沒有使用v節(jié)點,而是使用了通用i節(jié)點結(jié)構(gòu)。雖然兩種實現(xiàn)有所不同,但在概念上, v節(jié)點與i節(jié)點是一樣的。兩者都指向文件系統(tǒng)特有的i節(jié)點結(jié)構(gòu)。

      下圖顯示了一個進(jìn)程對應(yīng)的3張表之間的關(guān)系。該進(jìn)程有兩個不同的打開文件:一個文件從標(biāo)準(zhǔn)輸入打開(文件描述符0),另一個從標(biāo)準(zhǔn)輸出打開(文件描述符為1)。

      打開文件的內(nèi)核數(shù)據(jù)結(jié)構(gòu)

      如果兩個獨立進(jìn)程各自打開了同一文件,則有下圖中所示的關(guān)系。

      兩個獨立進(jìn)程各自打開同一個文件

      我們假定第一個進(jìn)程在文件描述符3上打開該文件,而另一個進(jìn)程在文件描述符4上打開該文件。打開該文件的每個進(jìn)程都獲得各自的一個文件表項,但對一個給定的文件只有一個v節(jié)點表項。之所以每個進(jìn)程都獲得自己的文件表項,是因為這可以使每個進(jìn)程都有它自己的對該文件的當(dāng)前偏移量。

      給出了這些數(shù)據(jù)結(jié)構(gòu)后,現(xiàn)在對前面所述的操作進(jìn)一步說明。

      • 在完成每個write后,在文件表項中的當(dāng)前文件偏移量即增加所寫入的字節(jié)數(shù)。如果這導(dǎo)致當(dāng)前文件偏移量超出了當(dāng)前文件長度,則將i節(jié)點表項中的當(dāng)前文件長度設(shè)置為當(dāng)前文件偏移量(也就是該文件加長了)。

      • 如果用O_APPEND標(biāo)志打開一個文件,則相應(yīng)標(biāo)志也被設(shè)置到文件表項的文件狀態(tài)標(biāo)志中。每次對這種具有追加寫標(biāo)志的文件執(zhí)行寫操作時,文件表項中的當(dāng)前文件偏移量首先會被設(shè)置為i節(jié)點表項中的文件長度。這就使得每次寫入的數(shù)據(jù)都追加到文件的當(dāng)前尾端處。

      • 若一個文件用lseek定位到文件當(dāng)前的尾端,則文件表項中的當(dāng)前文件偏移量被設(shè)置為i節(jié)點表項中的當(dāng)前文件長度(注意,這與用O_APPEND標(biāo)志打開文件是不同的)。

      • lseek函數(shù)只修改文件表項中的當(dāng)前文件偏移量,不進(jìn)行任何I/O操作。

      注意,文件描述符標(biāo)志和文件狀態(tài)標(biāo)志在作用范圍方面的區(qū)別,前者只用于一個進(jìn)程的一個描述符,而后者則應(yīng)用于指向該給定文件表項的任何進(jìn)程中的所有描述符。


      原子操作

      函數(shù)preadpwrite

      Single UNIX Specification包括了XSI擴(kuò)展,該擴(kuò)展允許原子性地定位并執(zhí)行I/O。preadpwrite就是這種擴(kuò)展。

      #include <unistd.h>
      ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
      // 返回值:讀到的字節(jié)數(shù),若已到文件尾,返回0;若出錯,返回?1
      
      ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
      // 返回值:若成功,返回已寫的字節(jié)數(shù);若出錯,返回?1
      

      調(diào)用pread相當(dāng)于調(diào)用lseek后調(diào)用read,但是pread又與這種順序調(diào)用有下列重要區(qū)別。

      • 調(diào)用pread時,無法中斷其定位和讀操作。

      • 不更新當(dāng)前文件偏移量。

      調(diào)用pwrite相當(dāng)于調(diào)用lseek后調(diào)用write,但也與它們有類似的區(qū)別。

      一般而言,原子操作(atomic operation)指的是由多步組成的一個操作。如果該操作原子地執(zhí)行,則要么執(zhí)行完所有步驟,要么一步也不執(zhí)行,不可能只執(zhí)行所有步驟的一個子集。


      函數(shù)dup和dup2

      下面兩個函數(shù)都可用來復(fù)制一個現(xiàn)有的文件描述符。

      #include <unistd.h>
      int dup(int fd);
      int dup2(int fd, int fd2);
      // 兩函數(shù)的返回值:若成功,返回新的文件描述符;若出錯,返回?1
      

      dup返回的新文件描述符一定是當(dāng)前可用文件描述符中的最小數(shù)值。對于 dup2,可以用fd2參數(shù)指定新描述符的值。如果fd2已經(jīng)打開,則先將其關(guān)閉。如若fd等于fd2,則dup2返回fd2,而不關(guān)閉它。

      這些函數(shù)返回的新文件描述符與參數(shù)fd共享同一個文件表項,如圖所示。

      dup(1)后的內(nèi)核數(shù)據(jù)結(jié)構(gòu)

      在此圖中,假定進(jìn)程啟動時執(zhí)行了:newfd = dup(1);

      當(dāng)此函數(shù)開始執(zhí)行時,假定下一個可用的描述符是3(這是非??赡艿?,因為0,1和2都由shell打開)。因為兩個描述符指向同一文件表項,所以它們共享同一文件狀態(tài)標(biāo)志(讀、寫、追加等)以及同一當(dāng)前文件偏移量。

      復(fù)制一個描述符的另一種方法是使用fcntl函數(shù)。實際上,調(diào)用dup(fd);等效于fcntl (fd, F_DUPFD, 0);而調(diào)用dup2(fd, fd2);等效于close(fd2); fcntl(fd, F_DUPFD, fd2);


      函數(shù)sync、fsync和fdatasync

      傳統(tǒng)的UNIX系統(tǒng)實現(xiàn)在內(nèi)核中設(shè)有緩沖區(qū)高速緩存或頁高速緩存,大多數(shù)磁盤I/O都通過緩沖區(qū)進(jìn)行。當(dāng)我們向文件寫入數(shù)據(jù)時,內(nèi)核通常先將數(shù)據(jù)復(fù)制到緩沖區(qū)中,然后排入隊列,晚些時候再寫入磁盤。這種方式被稱為延遲寫(delayed write)。

      通常,當(dāng)內(nèi)核需要重用緩沖區(qū)來存放其他磁盤塊數(shù)據(jù)時,它會把所有延遲寫數(shù)據(jù)塊寫入磁盤。為了保證磁盤上實際文件系統(tǒng)與緩沖區(qū)中內(nèi)容的一致性,UNIX系統(tǒng)提供了syncfsyncfdatasync三個函數(shù)。

      #include<unistd.h>
      int fsync(int fd);
      int fdatasync(int fd);
      // 返回值:若成功,返回0;若出錯,返回?1
      void sync(void);
      

      sync只是將所有修改過的塊緩沖區(qū)排入寫隊列,然后就返回,它并不等待實際寫磁盤操作結(jié)束。

      通常,稱為update的系統(tǒng)守護(hù)進(jìn)程周期性地調(diào)用(一般每隔30秒)sync函數(shù)。這就保證了定期沖洗(flush)內(nèi)核的塊緩沖區(qū)。

      fsync函數(shù)只對由文件描述符fd指定的一個文件起作用,并且等待寫磁盤操作結(jié)束才返回。fsync可用于數(shù)據(jù)庫這樣的應(yīng)用程序,這種應(yīng)用程序需要確保修改過的塊立即寫到磁盤上。

      fdatasync函數(shù)類似于fsync,但它只影響文件的數(shù)據(jù)部分。而除數(shù)據(jù)外,fsync還會同步更新文件的屬性。


      函數(shù)fcntl

      fcntl函數(shù)可以改變已經(jīng)打開文件的屬性。

      #include<fcntl.h>
      int fcntl(int fd, int cmd, ... /* int arg */);
      // 返回值:若成功,則依賴于cmd(見下);若出錯,返回?1
      

      在本節(jié)的各實例中,第3個參數(shù)總是一個整數(shù),與上面所示函數(shù)原型中的注釋部分對應(yīng)。但是在說明記錄鎖時,第3個參數(shù)則是指向一個結(jié)構(gòu)的指針。

      fcntl函數(shù)有以下5種功能。

      (1)復(fù)制一個已有的描述符(cmd=F_DUPFD或F_DUPFD_CLOEXEC)。

      (2)獲取/設(shè)置文件描述符標(biāo)志(cmd=F_GETFD或F_SETFD)。

      (3)獲取/設(shè)置文件狀態(tài)標(biāo)志(cmd=F_GETFL或F_SETFL)。

      (4)獲取/設(shè)置異步I/O所有權(quán)(cmd=F_GETOWN或F_SETOWN)。

      (5)獲取/設(shè)置記錄鎖(cmd=F_GETLK、F_SETLK或F_SETLKW)。

      先說明這11種cmd中的前8種。我們將討論與進(jìn)程表項中各文件描述符相關(guān)聯(lián)的文件描述符標(biāo)志以及每個文件表項中的文件狀態(tài)標(biāo)志。

      • F_DUPFD 復(fù)制文件描述符fd。新文件描述符作為函數(shù)值返回。它是尚未打開的各描述符中大于或等于第3個參數(shù)值(取為整型值)中各值的最小值。新描述符與 fd共享同一文件表項。但是,新描述符有它自己的一套文件描述符標(biāo)志,其 FD_CLOEXEC 文件描述符標(biāo)志被清除(這表示該描述符在exec時仍保持有效,將在第8章對此進(jìn)行討論)。

      • F_DUPFD_CLOEXEC 復(fù)制文件描述符,設(shè)置與新描述符關(guān)聯(lián)的FD_CLOEXEC文件描述符標(biāo)志的值,返回新文件描述符。

      • F_GETFD 對應(yīng)于fd的文件描述符標(biāo)志作為函數(shù)值返回。當(dāng)前只定義了一個文件描述符標(biāo)志 FD_CLOEXEC。

      • F_SETFD 對于fd設(shè)置文件描述符標(biāo)志。新標(biāo)志值按第3個參數(shù)(整型值)設(shè)置。

      要知道,很多現(xiàn)有的與文件描述符標(biāo)志有關(guān)的程序并不使用常量FD_CLOEXEC,而是將此標(biāo)志設(shè)置為0(系統(tǒng)默認(rèn),在exec時不關(guān)閉)或1(在exec時關(guān)閉)。

      • F_GETFL 對應(yīng)于fd的文件狀態(tài)標(biāo)志作為函數(shù)值返回。我們在說明open函數(shù)時,已描述了文件狀態(tài)標(biāo)志。它們列在圖中。
      對于fcntl的文件狀態(tài)標(biāo)志
      • F_SETFL 將文件狀態(tài)標(biāo)志設(shè)置為第3個參數(shù)的值(取為整型值)??梢愿牡膸讉€標(biāo)志是:O_APPEND、O_NONBLOCKO_SYNCO_DSYNC、O_RSYNC、O_FSYNCO_ASYNC

      • F_GETOWN 獲取當(dāng)前接收SIGIOSIGURG信號的進(jìn)程ID或進(jìn)程組ID。

      • F_SETOWN 設(shè)置接收SIGIOSIGURG信號的進(jìn)程ID或進(jìn)程組ID。正的arg指定一個進(jìn)程ID,負(fù)的arg表示等于arg絕對值的一個進(jìn)程組ID。

      fcntl的返回值與命令有關(guān)。如果出錯,所有命令都返回-1,如果成功則返回某個其他值。下列4個命令有特定返回值:F_DUPFDF_GETFD、F_GETFL以及F_GETOWN。第1個命令返回新的文件描述符,第2個和第3個命令返回相應(yīng)的標(biāo)志,最后一個命令返回一個正的進(jìn)程ID或負(fù)的進(jìn)程組ID。


      函數(shù)ioctl

      ioctl函數(shù)一直是I/O操作的雜物箱。不能用本章中其他函數(shù)表示的I/O操作通常都能用ioctl表示。

      #include <unistd.h>  /* System V */
      #include <sys/ioctl.h> /* BSD and Linux */
      int ioctl(int fd, int request, ...);
      // 返回值:若出錯,返回?1;若成功,返回其他值
      

      對于ISO C原型,它用省略號表示其余參數(shù)。但是,通常只有另外一個參數(shù),它常常是指向一個變量或結(jié)構(gòu)的指針。

      在此原型中,我們表示的只是ioctl函數(shù)本身所要求的頭文件。通常,還要求另外的設(shè)備專用頭文件。例如,除POSIX.1所說明的基本操作之外,終端I/O的ioctl命令都需要頭文件<termios.h>。

      磁帶操作使我們可以在磁帶上寫一個文件結(jié)束標(biāo)志、倒帶、越過指定個數(shù)的文件或記錄等,用本章中的其他函數(shù)(readwrite、lseek等)都難于表示這些操作,所以,對這些設(shè)備進(jìn)行操作最容易的方法就是使用ioctl


      posted @ 2025-10-09 22:36  Invinc-Z  閱讀(6)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产漂亮白嫩美女在线观看| 成人自拍小视频在线观看| 亚洲av永久无码精品水牛影视| 国产乱沈阳女人高潮乱叫老| 日韩国产精品中文字幕| 日本一区二区三区四区黄色| 中国熟妇毛多多裸交视频| 久久天天躁狠狠躁夜夜躁2o2o| 无套内谢少妇一二三四| 大城县| 国产69精品久久久久久| 色噜噜久久综合伊人一本| 国产色a在线观看| 亚洲国内精品一区二区| 国产亚洲欧洲av综合一区二区三区 | 40岁大乳的熟妇在线观看| 98精品全国免费观看视频| 99热这里只有成人精品国产 | 欧美日韩中文国产一区| 最新国产精品好看的精品| 中文字幕一区日韩精品| 吉川爱美一区二区三区视频 | 国产精品免费久久久免费| www插插插无码免费视频网站 | 久久亚洲精品11p| 熟女一区二区中文在线| 富源县| 亚洲欧洲精品一区二区| 欧美人禽zozo动人物杂交| 加勒比精品一区二区三区| 一面膜上边一面膜下边视频| 精品无人码麻豆乱码1区2区| 亚洲国产精品成人av网| 40岁大乳的熟妇在线观看| 久久无码专区国产精品| 91高清免费国产自产拍| 久久99热只有频精品8| 亚洲区成人综合一区二区| 一本精品99久久精品77| 国产中文三级全黄| 久久人人妻人人爽人人爽|