|     文(wen)件I/O操作(zuo)的(de)(de)系統調用,主要用到5個函數:open()、read()、write()、lseek()和close()。這些(xie)函數的(de)(de)特點是(shi)不帶緩存(cun),直接對文(wen)件(包(bao)括設備)進行(xing)讀寫操作(zuo)。這些(xie)函數雖然不是(shi)ANSI C的(de)(de)組成(cheng)部分,但是(shi)是(shi)Posix的(de)(de)組成(cheng)部分。     基本文件操作     1.函數說明● open()函數用于打開或創建文件,在打開或創建文件時可以指定文件的屬性及用戶的權限等各種參數。
 ● close()函數用于關閉一個被打開的文件。當一個進程終止時,所有被它打開的文件都由內核自動關閉,很多程序都使用這一功能而不顯式地關閉一個文件。
 ● read()函數用于將從指定的文件描述符中讀出的數據放到緩存區中,并返回實際讀入的字節數。若返回0,則表示沒有數據可讀,即已達到文件尾。讀操作從文件的當前指針位置開始。當從終端設備文件中讀出數據時,通常一次多讀一行。
 ● write()函數用于向打開的文件寫數據,寫操作從文件的當前指針位置開始,對磁盤文件進行寫操作,若磁盤已滿或超出該文件的長度,則write()函數返回失敗。
 ● lseek()函數(shu)用于在指定(ding)的(de)文(wen)件(jian)描述(shu)符(fu)中將(jiang)文(wen)件(jian)指針定(ding)位(wei)到相應(ying)的(de)位(wei)置。它只(zhi)能用在可定(ding)位(wei)(可隨機訪問)文(wen)件(jian)操作中。管(guan)道、套接(jie)字(zi)和大部分(fen)字(zi)符(fu)設備文(wen)件(jian)是不可定(ding)位(wei)的(de),所(suo)以在這些文(wen)件(jian)的(de)操作中無法使用lseek()調用。
     2.函數格式     open()函數的語法要點(dian)如表2.1所示。 表2.1  open()函數語法(fa)要點 
    
    | 所需頭文件 | #include <sys/types.h>  /* 提供類型pid_t的定義 */ #include <sys/stat.h>
 #include <fcntl.h>
 |  
    | 函數原型 | int open(const char *pathname, int flags, int perms) |  
    | 函數傳入值 | pathname | 被打開的文件名(可包括路徑名) |  
    | flag:文件打開的方式 | O_RDONLY:以只讀方式打開文件 |  
    | O_WRONLY:以只寫方式打開文件 |  
    | O_RDWR:以讀/寫方式打開文件 |  
    | O_CREAT:如果該文件不存在,就創建一個新的文件,并用第三個參數為其設置權限 |  
    | O_EXCL:如果使用O_CREAT時文件存在,則可返回錯誤消息。這一參數可測試文件是否存在。此時open是原子操作,防止多個進程同時創建同一個文件 |  
    | O_NOCTTY:使用本參數時,若文件為終端,那么該終端不會成為調用open()的那個進程的控制終端 |  
    | O_TRUNC:若文件已經存在,那么會刪除文件中的全部原有數據,并且設置文件大小為0 |  
    | O_APPEND:以添加方式打開文件,在打開文件的同時,文件指針指向文件的末尾,即將寫入的數據添加到文件的末尾 |  
    | perms | 被打開文件的存取權限 可以用一組宏定義:S_I(R/W/X)(USR/GRP/OTH)
 其中R/W/X分別表示讀/寫/執行權限
 USR/GRP/OTH分別表示文件所有者/文件所屬組/其他用戶
 例如,S_IRUSR | S_IWUSR表示設置文件所有者的可讀可寫屬性,八進制表示法中0600也表示同樣的權限
 |  
    | 函數返回值 | 成功:返回文件描述符 失敗:-1
 |      在open()函數(shu)中,flag參數(shu)可(ke)通過“|”組合構成(cheng),但(dan)前3個(ge)標(biao)志常量(liang)(O_RDONLY、O_WRONLY及(ji)O_RDWR)不能相互(hu)組合。perms是文件(jian)的存(cun)取權(quan)限(xian),既(ji)可(ke)以(yi)(yi)用(yong)宏定義表示法(fa),也可(ke)以(yi)(yi)用(yong)八進制表示法(fa)。     close()函數的語法要點如表2.2所示。 表2.2  close()函(han)數語法要(yao)點(dian) 
    
    | 所需頭文件 | #include <unistd.h> |  
    | 函數原型 | int close(int fd) |  
    | 函數輸入值 | fd:文件描述符 |  
    | 函數返回值 | 0:成功 1:出錯
 |      read()函數(shu)的語法要點如表2.3所示(shi)。 表2.3  read()函數語(yu)法要點 
    
    | 所需頭文件 | #include <unistd.h> |  
    | 函數原型 | ssize_t read(int fd, void *buf, size_t count) |  
    | 函數傳入值 | fd:文件描述符 |  
    | buf:指定存儲器讀出數據的緩沖區 |  
    | count:指定讀出的字節數 |  
    | 函數返回值 | 成功:讀到的字節數 0:已到達文件尾
 1:出錯
 |      在讀(du)(du)(du)普通(tong)文件(jian)時(shi),若(ruo)讀(du)(du)(du)到要求的(de)字節數前已(yi)到達文件(jian)的(de)尾部(bu),則返(fan)回的(de)字節數會小(xiao)于(yu)希望讀(du)(du)(du)出(chu)的(de)字節數。     write()函數的語法要點如表2.4所示。 表2.4  write()函數(shu)語(yu)法(fa)要點 
    
    | 所需頭文件 | #include <unistd.h> |  
    | 函數原型 | ssize_t write(int fd, void *buf, size_t count) |  
    | 函數傳入值 | fd:文件描述符 |  
    | buf:指定存儲器寫入數據的緩沖區 |  
    | count:指定讀出的字節數 |  
    | 函數返回值 | 成功:已寫的字節數 1:出錯
 |      在寫普通文件時(shi),寫操(cao)作從(cong)文件的當前指(zhi)針位置(zhi)開始(shi)。     lseek()函(han)數(shu)的(de)語法要(yao)點如表2.5所示。 表2.5  lseek()函數語(yu)法要(yao)點(dian) 
    
    | 所需頭文件 | #include <unistd.h> #include <sys/types.h>
 |  
    | 函數原型 | off_t lseek(int fd, off_t offset, int whence) |  
    | 函數傳入值 | fd:文件描述符 |  
    | offset:偏移量,每一讀寫操作所需要移動的距離,單位是字節,可正可負(向前移,向后移) |  
    |  | whence: 當前位置的基點
 | SEEK_SET:當前位置為文件的開頭,新位置為偏移量的大小 |  
    | SEEK_CUR:當前位置為文件指針的位置,新位置為當前位置加上偏移量 |  
    | SEEK_END:當前位置為文件的結尾,新位置為文件的大小加上偏移量的大小 |  
    | 函數返回值 | 成功:文件的當前位移 1:出錯
 |      3.函數使用實(shi)例     下面(mian)實例中的(de)open()函數帶有3個flag參數:O_CREAT、O_TRUNC和O_WRONLY,這(zhe)(zhe)樣就可(ke)以對不同(tong)的(de)情況指定相(xiang)應的(de)處理方法。另外,這(zhe)(zhe)里對該文件的(de)權限設置為0600。其源碼如下所(suo)示:     下面列出(chu)文(wen)(wen)件(jian)(jian)(jian)(jian)基(ji)(ji)本操作的(de)實例,基(ji)(ji)本功能是(shi)從(cong)一(yi)個文(wen)(wen)件(jian)(jian)(jian)(jian)(源文(wen)(wen)件(jian)(jian)(jian)(jian))中讀(du)(du)取(qu)后10KB數據(ju)并復制到(dao)另一(yi)個文(wen)(wen)件(jian)(jian)(jian)(jian)(目(mu)標(biao)文(wen)(wen)件(jian)(jian)(jian)(jian))。在實例中源文(wen)(wen)件(jian)(jian)(jian)(jian)是(shi)以(yi)只讀(du)(du)方(fang)式打開(kai)的(de),目(mu)標(biao)文(wen)(wen)件(jian)(jian)(jian)(jian)是(shi)以(yi)只寫方(fang)式打開(kai)(可(ke)以(yi)是(shi)讀(du)(du)/寫方(fang)式)的(de)。若目(mu)標(biao)文(wen)(wen)件(jian)(jian)(jian)(jian)不存在,可(ke)以(yi)創(chuang)建(jian)并設(she)置權限的(de)初始值為644,即文(wen)(wen)件(jian)(jian)(jian)(jian)所(suo)有者可(ke)讀(du)(du)可(ke)寫,文(wen)(wen)件(jian)(jian)(jian)(jian)所(suo)屬組和其他用戶只能讀(du)(du)。     讀者需要留意的地方(fang)是(shi)改變(bian)每次讀/寫的緩(huan)存大小(實例中為1KB)會怎(zen)樣影響運(yun)行效率。     /* copy_file.c */#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 
 #define	BUFFER_SIZE	1024				/* 每次讀/寫緩存大小,影響運行效率 */
 #define SRC_FILE_NAME	"src_file"		/* 源文件名 */
 #define DEST_FILE_NAME	"dest_file"	/* 目標文件名 */
 #define OFFSET		10240			/* 復制的數據大小 */
 
 int main()
 {
 int src_file, dest_file;
 unsigned char buff[BUFFER_SIZE];
 int real_read_len;
 
 /* 以只讀方式打開源文件 */
 src_file = open(SRC_FILE_NAME, O_RDONLY);
 
 /* 以只寫方式打開目標文件,若此文件不存在則創建該文件, 訪問權限值為644 */
 dest_file = open(DEST_FILE_NAME, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|
 S_IRGRP|S_IROTH);
 if (src_file < 0 || dest_file < 0)
 {
 printf("Open file error\n");
 exit(1);
 }
 
 /* 將源文件的讀/寫指針移到后10KB的起始位置 */
 lseek(src_file, -OFFSET, SEEK_END);
 
 /* 讀取源文件的后10KB數據并寫到目標文件中,每次讀寫1KB */
 while ((real_read_len = read(src_file, buff, sizeof(buff))) > 0)
 {
 write(dest_file, buff, real_read_len);
 }
 close(dest_file);
 close(src_file);
 return 0;
 }
 
 $ ./copy_file
 $ ls -lh  dest_file
 -rw-r--r-- 1 david root 10K 14:06 dest_file
     本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》    熱點(dian)鏈接:          
         1、Linux系統調用及用戶編程接口(API)2、什么是Linux系統調用,包括哪些內容
 3、Linux中的文件及文件描述符
 4、Linux文件系統之虛擬文件系統(VFS)
 5、嵌入式文件系統構建
 
 更多新聞>>  |