【Linux】文件操作系統調用


一. 文件描述符

  在Linux下使用文件描述符來表示設備文件和普通文件。文件描述符是一個整型的數據,所有對文件的操作都通過文件描述符實現。文件描述符的范圍是0~OPEN_MAX,系統中有3個已經分配的文件描述符,即標准輸入、標准輸出、和標准錯誤,他們的文件描述符的值分別為0、1、2。

  文件描述符是文件系統中連接用戶空間和內核空間的樞紐。當打開一個或者創建一個文件時,內核空間創建相應的結構,並生成一個整型的變量傳遞給用戶空間的對應進程,進程用這個文件描述符來對文件進行操作。

二. 打開、創建文件open()函數

1.函數原型

頭文件:<fcntl.h>

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode); 

open()函數根據用戶設置的標志flags和模式mode在路徑pathname下建立或者打開一個文件。當函數成功時,返回一個整型的文件描述符,出錯時返回-1.

 

2.flags

文件的打開標志flags用於設置文件打開后允許的操作方式。

  flags的取值:

    O_RDONLY:只讀

    O_WRONLY:只寫

    O_RDWR:讀寫

    O_APPEND:對文件的讀寫追加到文件的尾端

    O_CREAT:文件不存在則創建它,同時第三個參數mode需要設定新文件的權限.

    O_TRUNC:將文件的長度斷為0。常用來對文件進行清空。

3.mode

參數mode用於表示打開文件的權限,mode必須結合flags的O_CREAT使用,否則無效。

  mode的取值:

    S_IRWXU:用戶(文件所有者)有讀、寫、執行的權限

    S_IRUSR:用戶對文件有讀的權限

    S_IWUSR:用戶對文件有寫的權限

    S_IXUSR:用戶對文件又執行的權限

    S_IRWXG:組用戶(文件所有者)有讀、寫、執行的權限

    S_IRGRP:組用戶對文件有讀的權限

    S_IWGRP:組用戶對文件有寫的權限

    S_IXGRP:組用戶對文件有執行的權限

    S_IRWXO:其他用戶(文件所有者)有讀、寫、執行的權限

    S_IROTH:其他用戶對文件有讀的權限

    S_IWOTH:其他用戶對文件有寫的權限

    S_IXOTH:其他用戶對文件有執行的權限

4.使用函數open()的例子

 

 1  #include<sys/types.h>
 2  #include<sys/stat.h>
 3  #include<fcntl.h>
 4  #include<stdio.h>
 5 
 6  int main(void)
 7  {
 8    int fd = -1;
 9    char filename[]="test.txt";
10    fd = open(filename,O_CREAT|O_RDWR,S_IRWXU);
11    if(fd==-1)
12      {
13        printf("Open file %s failure!,fd:%d\n",filename,fd);
14      }
15    else
16      {
17        printf("Open file %s success,fd:%d\n",filename,fd);
18      }
19    return 0;
20  }
21   

 

編譯執行后會在當前目錄下創建test.txt

 三. 關閉文件close()函數

1.函數原型

頭文件: <unistd.h>

#include<unistd.h>
int close(int fd);

 

close()函數關閉一個文件描述符,關閉以后此文件描述符不再指向任何文件,從而描述符可以再次使用。當函數執行成功的時候返回0,如果有錯誤發生,返回-1.

2.close()函數的例子

如果每次打開文件不關閉,則會將系統的文件描述符耗盡,導致不能再打開文件:

 1 #include<sys/types.h>
 2 #include<sys/stat.h>
 3 #include<fcntl.h>
 4 #include<stdio.h>
 5 #include<unistd.h>
 6 
 7 int main(void)
 8 {
 9     int i = 0;
10     int fd = 0;
11     for(i=1;fd>=0;i++)
12     {   
13         fd=open("test.txt",O_RDONLY);
14         if(fd>0)
15         {   
16             printf("fd:%d\n",fd);
17         }   
18         else
19         {   
20             printf("error,can't openf file \n");
21             exit(1);
22         }   
23     }   
24     return 0;
25 }

共使用65535個文件描述符后將文件描述符耗盡:

1 ...
2 fd:65530
3 fd:65531
4 fd:65532
5 fd:65533
6 fd:65534
7 error,can't openf file 

所以,打開文件使用完畢后,要使用close()函數將文件關閉,釋放文件描述符。示例如下:

 1 #include<sys/types.h>
 2 #include<sys/stat.h>
 3 #include<fcntl.h>
 4 #include<stdio.h>
 5 #include<unistd.h>
 6 
 7 int main(void)
 8 {
 9  
10     int fd = -1;
11     char filename[]="test.txt";
12     fd = open(filename,O_CREAT|O_RDWR,S_IRWXU);
13     if(fd==-1)
14         {
15             printf("Open file %s failure!,fd:%d\n",filename,fd);
16         }
17     else
18         {
19             printf("Open file %s success,fd:%d\n",filename,fd);
20         }
21     //對文件進行讀寫的操作(略)
22     ...
23     
24  close(fd); 25     return 0;
26 }

四. 讀取文件read()函數

1.函數原型

頭文件: <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

 

read()函數從文件描述符fd對應的文件中讀取count字節,放到buf開始的緩沖區。如果count的值為0,read()函數返回0,不進行其他操作;讀取成功時,文件對應的讀取位置指針向后移動,移動的大小為讀取的字節數。

如果read()函數讀取成功,返回讀取的字節數;當返回值為-1的時候,讀取函數有錯誤發生;如果已經達到文件的末尾,返回0.

2. read()函數的例子

從test.txt中讀取數據,文件中存放的字符串 quick brown fox jump over the lazy dog。讀取后將數據打印出來:

 

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<sys/types.h>
 4 #include<sys/stat.h>
 5 #include<fcntl.h>
 6 
 7 int main(void)
 8 {
 9     int fd = -1,i;
10     ssize_t size =-1;
11     char buf[10];   
12     char filename[] = "test.txt";
13 
14     fd = open(filename,O_RDONLY);
15     if(-1==fd)
16     {   
17             printf("Open file %s failuer,fd:%d\n",filename,fd);
18     }else{
19 
20             printf("Open file %s success,fd:%d\n",filename,fd);
21     }   
22     //循環讀取數據,直到文件末尾或者出錯
23     while(size)
24     {   
25         size = read(fd,buf,10);
26         if(-1==size)
27         {   
28             close(fd);
29             printf("Read file %s error occurs\n",filename);
30             return -1; 
31         }else{
32             if(size>0)
33             {   
34                 printf("read %d bytes:",size);
35                 printf("\"");
36                 for(i =0;i<size;i++)
37                 {   
38                     printf("%c",*(buf+i));
39                 }   
40                 printf("\"\n");
41             }else{
42                 printf("reach the end of file \n");
43             }
44 
45         }
46     }
47     return 0;
48 }

 

輸出結果:

Open file test.txt success,fd:3
read 10 bytes:"quick brow"
read 10 bytes:"n fox jump"
read 10 bytes:"s over the"
read 10 bytes:" lazy dog
"
reach the end of file

五. 寫文件write()函數

1.函數原型

頭文件:<unistd.h> 

ssize_t write(int fd, const void *buf, size_t count);

 

與read()函數的含義類似,write()函數向文件描述符fd寫入數據,數據的大小有count指定,buf為要寫入數據的指針。寫入成功返回寫入數據的字節數,寫入出錯則返回-1。當操作的對象是普通文件時,寫文件的位置從文件的當前開始,如果在打開文件時指定了O_APPEND項,每次寫操作時,會將寫操作的位置移到文件的結尾處。

2.write()函數的例子

向test.txt末尾中寫入數據 quick brown fox jumps over the lazy dog。

 

 1 #include<sys/types.h>
 2 #include<sys/stat.h>
 3 #include<stdio.h>
 4 #include<unistd.h>
 5 #include<fcntl.h>
 6 
 7 int main(void)
 8 {
 9     int fd = -1,i;
10     ssize_t size =-1;
11     int input =0; 
12     
13     char buf[] = "quick brown box jumps over the lazy dog";
14     char filename[] = "test.txt";
15     
16     fd = open(filename,O_RDWR|O_APPEND);
17     if(-1==fd)
18     {   
19         printf("Open file %s faliluer, fd: %d\n",filename,fd);
20     }else{
21         printf("Open file %s success, fd:%d\n,=",filename,fd);
22     }   
23     size = write(fd,buf,strlen(buf));
24     printf("write %d bytes to file %s\n",size,filename);
25     
26     close(fd);
27     return 0;
28 }

 

執行前,test.txt中的內容:

1 quick brown box jumps over the lazy dog

執行后,test.txt中的內容:

1 quick brown box jumps over the lazy dog
2 quick brown box jumps over the lazy dog

 六. 文件偏移lseek()函數

文件偏移量指的是當前文件操作位置相對於文件開始位置的偏移。當打開一個文件時,如果沒有指定O_APPEND參數,文件的偏移量為0。如果指定了O_APPEND選項,文件的偏移量與文件的長度相等,即文件的當前操作位置移到了末尾。

1. 函數原型

頭文件:<unistd.h>

off_t lseek( int fildes, off_t offset, int whence)

 

函數對文件描述符fildes所代表的文件,按照操作模式whence和偏移量的大小off_t,重新設定文件偏移量。如果lseek()函數操作成功,則返回新的文件偏移量的值;如果失敗返回-1。由於文件的偏移量可以為負值,判斷lseek()是否操作成功時,不要使用小於0的判斷,要使用是否等於-1來判斷。參數offet和whence搭配使用,具體含義如下:

  whence值為SEEK_SET時,offset為相對文件開始處的值;

  whence值為SEEK_CUR時,offset為相對當前位置的值;

  whence值為SEEK_END時,offset為相對文件結尾的值;

2. lseek()函數的通用例子

首先打開文本test.txt,然后將偏移量定位到離開始處10字節處,寫入字符串“0123456”。

 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<unistd.h>
 5 #include<fcntl.h>
 6 
 7 int main(void)
 8 {
 9     int fd =-1;
10     ssize_t size = -1; 
11     off_t offset = -1; 
12 
13     char buf[]="0123456";
14     char filename[]="test.txt";
15     
16     fd = open(filename,O_RDWR);
17     if(-1==fd)
18     {   
19         printf("Open file %s failure,fd:%d",filename,fd);
20         return -1; 
21     }   
22     offset = lseek(fd,10,SEEK_SET);
23     if(-1==offset)
24     {   
25         printf("lseek file %s failure,fd:%d",filename,fd);
26         return -1; 
27     }   
28     size = write(fd,buf,strlen(buf));
29     if(size!=strlen(buf))
30     {   
31         printf("write file %s failure,fd:%d",filename,fd);
32         return -1; 
33     }   
34     close(fd);
35     return 0;
36 }

執行前test.txt內容:

1 quick brown box jumps over the lazy dog

執行后test.txt內容:

1 quick brow0123456umps over the lazy dog

如果偏移量的設置超出文件的大小,會造成文件空洞。即文件尾部到設置位置之間被"\0"填充。

七. 獲取文件狀態fstat()函數

在程序設計的時候經常要用到文件的一些特征值,如文件的所有者,文件的修改時間、文件的大小等。stat()函數、fstat()函數和lstat()函數可以獲得文件的狀態。

1. 函數原型

頭文件:<sys/stat.h>

1 int stat(const char *path, struct stat *buf);
2 int fstat(int filedes, struct stat *buf);
3 int lstat(const char *path, struct stat *buf);

 

函數的第一個參數時文件描述的參數,可以為文件描述符或文件的路徑(含文件名),buf為指向struct stat結構體的指針,獲得的狀態從這個參數中傳回。當函數執行成功時返回0,執行失敗返回-1。

fstat區別於另外兩個系統調用的地方在於,fstat系統調用接受的是 一個“文件描述符”,而另外兩個則直接接受“文件全路徑”。文件描述符是需要我們用open系統調用后才能得到的,而文件全路經直接寫就可以了。stat和lstat的區別:當文件是一個符號鏈接時,lstat返回的是該符號鏈接本身的信息;而stat返回的是該鏈接指向的文件的信息。

結構體struct stat 為一個描述文件狀態的結構,定義如下:

 1 struct stat {
 2         mode_t     st_mode;       //文件對應的模式,文件,目錄等
 3         ino_t      st_ino;       //inode節點號
 4         dev_t      st_dev;        //設備號碼
 5         dev_t      st_rdev;       //特殊設備號碼
 6         nlink_t    st_nlink;      //文件的連接數
 7         uid_t      st_uid;        //文件所有者
 8         gid_t      st_gid;        //文件所有者對應的組
 9         off_t      st_size;       //普通文件,對應的文件字節數
10         time_t     st_atime;      //文件最后被訪問的時間
11         time_t     st_mtime;      //文件內容最后被修改的時間
12         time_t     st_ctime;      //文件狀態改變時間
13         blksize_t st_blksize;    //文件內容對應的塊大小
14         blkcnt_t   st_blocks;     //偉建內容對應的塊數量
15       };

2.stat()函數的例子

 獲取當前文件夾下test.txt文件的狀態,並打印部分信息。

 1 #include<sys/stat.h>
 2 #include<sys/types.h>
 3 #include<unistd.h>
 4 #include<stdio.h>
 5 
 6 int main(void)
 7 {
 8     struct stat st; 
 9     
10     if(-1==stat("test.txt",&st))
11     {   
12         printf("get file status failure\n");
13         return -1; 
14     }   
15     printf("此文件的大小:%d\n",st.st_size);
16     printf("此文件的租后修改時間:%d\n",st.st_mtime);
17     printf("此文件的節點:%d\n",st.st_ino);
18     printf("此文件的保護模式:%d\n",st.st_mode);
19 }

輸出:

此文件的大小:40
此文件的租后修改時間:1462535869
此文件的節點:917523
此文件的保護模式:33216

 

八. 建立內存映射函數mmap()

mmap()函數將普通文件映射到內存中,普通文件被映射到進程地址空間后,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。 mmap()系統調用使得進程之間通過映射同一個普通文件實現共享內存。

mmap()映射后,讓用戶程序直接訪問設備內存,相比較在用戶控件和內核空間互相拷貝數據,效率更高。在要求高性能的應用中比較常用。mmap映射內存必須是頁面大小的整數倍,面向流的設備不能進行mmap,mmap的實現和硬件有關。

 1.函數原型

mmap()函數

頭文件:<sys/mman.h>

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)

 

參數說明:

  start:映射區的起始地址,通常為NULL(或0),表示由系統自己決定映射到什么地址。

  length:映射數據的長度,即文件需要映射到內存中的數據的大小。

  prot:映射區保護方式,取一下某個值或者它們的組合:

    PROT_EXEC:映射區可被執行

    PROT_READ:映射區可讀取

    PROT_WRITE:映射區可寫入

    PROT_NONE:映射區不可訪i問

  flags:指定映射對象的類型,映射選項和映射頁是否可以共享。它的值可以是一個或者多個以下位的組合:

    MAP_FIXED:如果參數start指定了用於需要映射到的地址,而所指的地址無法成功建立映射,則映射失敗。通常不推薦使用此設置,而將start設置為null(或0),由系統自動選 取映射地址。

    MAP_SHARED:共享映射區域,映射區域允許其他進程共享,對映射區域寫入數據將會寫入到原來的文件中。

    MAP_RIVATE:對映射區域進行寫入操作時會產生一個映射文件的復制,即寫入復制(copy on write),而讀操作不會影響此復制。對此映射區的修改不會寫回原來的文件,即不會影響原來文件的內容。

    MAP_ANONYMOUS:建立匿名映射。映射區不與任何文件關聯,而且映射區無法與其他進程共享。

    MA_DENYWRITE:對文件的寫入操作將被禁止,不允許直接對文件進行操作。

    MAP_LOCKED:將映射區鎖定,防止頁面被交換出內存。

    參數flags必須為MAP_SHARED或者MAP_PRIVATE二者之一的類型。MAP_SHARED類型表示多個進程使用的是一個內存映射的副本,任何一個進程都可對此映射進行修改,其他的進程對其修改是可見的。而MAP_PRIVATE則是多個進程使用的文件內存映射,在寫入操作后,會復制一個副本給修改的進程,多個進程之間的副本是不一致的。

  fd:文件描述符,一般由open()函數返回。

  offse:被映射數據在文件中的起點。

 

mmap()執行成功后返回映射區的起始地址,執行失敗返回-1.

munmap()函數

頭文件:<sys/mman.h>

int munmap(void *start, size_t length);

 

munmap()函數的作用是解除mmap()函數的映射關系。參數start時mmap()函數成功后的返回值,即映射的內存地址;length為映射區的長度。

 

函數執行成功返回0,執行失敗返回-1。

msync()函數

頭文件:<sys/mman.h>

int msync ( void * start , size_t length, int flags) 
 
msync()函數被稱為刷新變化函數,一般來說,進程在映射空間的對共享內容的改變並不直接寫回到磁盤文件中,往往在調用munmap()后才執行該操作。可以通過調用msync()函數來實現磁盤文件內容與共享內存區中的內容一致,即同步操作。
 
參數說明:
  start:映射區的起始地址,即mmap()函數的返回值。
  length:映射空間的大小
  flags:刷新參數:
    MS_ASYNC:異步,調用會立即返回,不等到更新的完成。
    MS_SYNC:同步,調用會等到更新之后返回。
    MS_INVALIDATE:通知使用該共享區域的進程,數據已經改變。在共享內容更改之后,使得文件的其他映射失效,從而使得共享該文件的其他進程去重新獲取最新值。
 
函數執行成功返回0,失敗返回-1。
 
 建立文件的內存映射的流程:
  首先使用open()函數打開一個文件,當操作成功后會返回一個文件描述符;
  使用mmap()函數將此文件描述符所代表的文件映射到一個地址空間,如果映射成功,會返回一個映射地址執政;
  對文件的操作可以通過mmap()映射得到的地址來進行,包括讀數據、寫數據、偏移等,與一般的指針操作相同,不過要注意不要進行越界訪問;
  當對文件操作完畢后,需要使用munmap()函數將mmap()映射的地址取消;
  使用close()函數關閉文件。
 
2. mmap()函數和munmap()函數的例子
 1 #include<sys/types.h>
 2 #include<sys/stat.h>
 3 #include<fcntl.h>
 4 #include<sys/mman.h>
 5 #include<string.h>
 6 #include<stdio.h>
 7 #define FILELENGTH 800
 8 
 9 int main(void)
10 {
11     int fd = -1; 
12     char buf1[] = "Linux Command line and shell Scripting bible";
13     char buf2[]= "a";
14     char *addr = NULL;
15     ssize_t size = -1; 
16     off_t cur_pos = 0;
17     //打開文件,將文件的長度縮小為0
18     fd = open("mmap.txt",O_RDWR|O_CREAT, S_IRWXU);
19     if(-1==fd)
20     {   
21         return -1; 
22     }   
23     cur_pos = lseek(fd,FILELENGTH-1, SEEK_SET); 
24     size = write(fd,buf2,strlen(buf2));//隨意寫入一個字符,此時文件長度為800
25     if(1==size)
26     {   
27         printf("write success\n");
28     }   
29     
30     //將文件mmap.txt中的數據段從開頭到1M的數據映射到內存中,對文件的操作立刻顯示在文件上,可讀寫.
31     addr = (char *)mmap(NULL, FILELENGTH, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 
32     if((char *)-1 == addr)
33     {   
34         printf("mmap failure !\n");
35         close(fd);
36         return -1; 
37     }   
38     //將buf中的字符串復制到映射區域中,起始位置為addr偏移16
39     memcpy(addr +16 ,buf ,strlen(buf));
40     munmap(addr,FILELENGTH);//取消內存映射
41     close(fd);//關閉文件
42     return 0;
43 }

運行結果是生成一個mmap.txt文件並填充一下內容:

^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@Linux Command line and shell Scripting bible^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@a

 

九. 文件屬性fcntl()函數

  fcntl()函數用於獲得和改變已經打開文件的性質。

1.函數原型

頭文件:<fcntl.h>

int fcntl(int fd, int cmd);
int fcnt(int fd, int cmd, long arg);
int fcnt(int fd, int cmd, struct flock *lock);

參數說明:

  fd:文件描述符

  cmd:操作命令

  arg:供命令使用的參數

  lock:同上

返回值:

  fcntl()的返回值與命令有關。如果出錯,所有命令返回-1,如果成功則返回某個其他值。下列三個命令有特定的返回值:

    F_DUPFD:返回新的文件描述符

    F_GETFD:返回相應標志

    F_GETFL,F_GETOWN:返回一個正的進程ID或負的進程組ID

fcntl()函數有5種功能:

  1.復制一個現有的描述符(cmd = F_DUPFD)

  2.獲得/設置文件描述符標記(cmd = F_GETFD或F_SETFD)

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

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

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

  詳細的介紹請參考另一篇博文:httpc://blog.csdn.net/pbymw8iwm/article/details/7974789

2. fcntl()函數的例子 

如下代碼為修改文件狀態值的一個實例,在文本文件fcntl.txt中的內容是"1234567890abcdefg",打開文件fcntl.txt時設置為O_RDWR,此時文件的偏移量位於文件開頭,修改狀態值的時候增加O_APPEND項,此時文件的偏移量移到文件末尾,寫入字符串FCNTL,然后關閉。

 

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<fcntl.h>
 4 #include<stdio.h>
 5 #include<string.h>
 6 
 7 int main(void)
 8 {
 9     int flags = -1; 
10     char buf[] = "FCNTL";
11     int fd = open("fcntl.txt",O_RDWR);
12     flags  = fcntl(fd, F_GETFL, 0); 
13     
14     flags |= O_APPEND;
15     flags = fcntl(fd, F_SETFL, flags);
16     if(flags<0)
17     {   
18         printf("failure to use fcntl\n");
19         return -1; 
20     }   
21 
22     write(fd, buf, strlen(buf));
23     close(fd);
24     return 0;
25 } 

 

十. 設備文件輸入輸出控制ioctl()函數

 ioctl()函數通過對文件描述符的發送命令來控制設備。

1.函數原型

頭文件:<sys/ioctl.h>

int ioctl(int d, int rquest, ...);

 

ioctl()函數通過對文件描述符發送特定的命令來控制文件描述符所代表的設備。參數d時一個已經打開的設備。通常情況下ioctl()函數出錯會返回-1,成功返回0或者大於1的值,取決於對應設備的驅動程序對命令的處理。

使用ioctl()像其他的系統調用一樣:打開文件,發送命令,查詢結果。ioctl()函數像一個雜貨鋪,對設備的控制通常都通過這個函數來執行。具體對設備的操作方式取決於設備驅動程序的編寫。

2.ioctl()函數的例子

下面是一個控制CDROM打開的簡單程序,因為CDROM控制程序的數據結構在頭文件<liinux/cdrom.h>中,所以要包含此文件。

 1 #include <Linux/cdrom.h>
 2 #include <stdio.h>
 3 #include <fcntl.h>
 4 
 5 int main(void)
 6 {
 7     int fd = open("/dev/cdrom",O_RDONLY);
 8     if(fd<0)
 9     {   
10         printf("Open cdrom failure\n");
11     }    
12     if(!ioctl(fd, CDROMEJECT,NULL))
13     {   
14         printf("成功彈出 CDROM\n");
15     }else{
16         printf("彈出 CDROM失敗");
17     }   
18     close(fd)
19     return 0;
20 }

 

 

 

 

 

 

 

 

 

 

  


免責聲明!

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



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