文件I/O操作的系統(tǒng)調(diào)用,主要用到5個(gè)函數(shù):open()、read()、write()、lseek()和close()。這些函數(shù)的特點(diǎn)是不帶緩存,直接對(duì)文件(包括設(shè)備)進(jìn)行讀寫(xiě)操作。這些函數(shù)雖然不是ANSI C的組成部分,但是是Posix的組成部分。
基本文件操作
1.函數(shù)說(shuō)明
● open()函數(shù)用于打開(kāi)或創(chuàng)建文件,在打開(kāi)或創(chuàng)建文件時(shí)可以指定文件的屬性及用戶(hù)的權(quán)限等各種參數(shù)。
● close()函數(shù)用于關(guān)閉一個(gè)被打開(kāi)的文件。當(dāng)一個(gè)進(jìn)程終止時(shí),所有被它打開(kāi)的文件都由內(nèi)核自動(dòng)關(guān)閉,很多程序都使用這一功能而不顯式地關(guān)閉一個(gè)文件。
● read()函數(shù)用于將從指定的文件描述符中讀出的數(shù)據(jù)放到緩存區(qū)中,并返回實(shí)際讀入的字節(jié)數(shù)。若返回0,則表示沒(méi)有數(shù)據(jù)可讀,即已達(dá)到文件尾。讀操作從文件的當(dāng)前指針位置開(kāi)始。當(dāng)從終端設(shè)備文件中讀出數(shù)據(jù)時(shí),通常一次多讀一行。
● write()函數(shù)用于向打開(kāi)的文件寫(xiě)數(shù)據(jù),寫(xiě)操作從文件的當(dāng)前指針位置開(kāi)始,對(duì)磁盤(pán)文件進(jìn)行寫(xiě)操作,若磁盤(pán)已滿(mǎn)或超出該文件的長(zhǎng)度,則write()函數(shù)返回失敗。
● lseek()函數(shù)用于在指定的文件描述符中將文件指針定位到相應(yīng)的位置。它只能用在可定位(可隨機(jī)訪(fǎng)問(wèn))文件操作中。管道、套接字和大部分字符設(shè)備文件是不可定位的,所以在這些文件的操作中無(wú)法使用lseek()調(diào)用。
2.函數(shù)格式
open()函數(shù)的語(yǔ)法要點(diǎn)如表2.1所示。
表2.1 open()函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 |
#include <sys/types.h> /* 提供類(lèi)型pid_t的定義 */
#include <sys/stat.h>
#include <fcntl.h>
|
函數(shù)原型 |
int open(const char *pathname, int flags, int perms) |
函數(shù)傳入值 |
pathname |
被打開(kāi)的文件名(可包括路徑名) |
flag:文件打開(kāi)的方式 |
O_RDONLY:以只讀方式打開(kāi)文件 |
O_WRONLY:以只寫(xiě)方式打開(kāi)文件 |
O_RDWR:以讀/寫(xiě)方式打開(kāi)文件 |
O_CREAT:如果該文件不存在,就創(chuàng)建一個(gè)新的文件,并用第三個(gè)參數(shù)為其設(shè)置權(quán)限 |
O_EXCL:如果使用O_CREAT時(shí)文件存在,則可返回錯(cuò)誤消息。這一參數(shù)可測(cè)試文件是否存在。此時(shí)open是原子操作,防止多個(gè)進(jìn)程同時(shí)創(chuàng)建同一個(gè)文件 |
O_NOCTTY:使用本參數(shù)時(shí),若文件為終端,那么該終端不會(huì)成為調(diào)用open()的那個(gè)進(jìn)程的控制終端 |
O_TRUNC:若文件已經(jīng)存在,那么會(huì)刪除文件中的全部原有數(shù)據(jù),并且設(shè)置文件大小為0 |
O_APPEND:以添加方式打開(kāi)文件,在打開(kāi)文件的同時(shí),文件指針指向文件的末尾,即將寫(xiě)入的數(shù)據(jù)添加到文件的末尾 |
perms |
被打開(kāi)文件的存取權(quán)限
可以用一組宏定義:S_I(R/W/X)(USR/GRP/OTH)
其中R/W/X分別表示讀/寫(xiě)/執(zhí)行權(quán)限
USR/GRP/OTH分別表示文件所有者/文件所屬組/其他用戶(hù)
例如,S_IRUSR | S_IWUSR表示設(shè)置文件所有者的可讀可寫(xiě)屬性,八進(jìn)制表示法中0600也表示同樣的權(quán)限
|
函數(shù)返回值 |
成功:返回文件描述符
失。-1
|
在open()函數(shù)中,flag參數(shù)可通過(guò)“|”組合構(gòu)成,但前3個(gè)標(biāo)志常量(O_RDONLY、O_WRONLY及O_RDWR)不能相互組合。perms是文件的存取權(quán)限,既可以用宏定義表示法,也可以用八進(jìn)制表示法。
close()函數(shù)的語(yǔ)法要點(diǎn)如表2.2所示。
表2.2 close()函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 |
#include <unistd.h> |
函數(shù)原型 |
int close(int fd) |
函數(shù)輸入值 |
fd:文件描述符 |
函數(shù)返回值 |
0:成功
1:出錯(cuò)
|
read()函數(shù)的語(yǔ)法要點(diǎn)如表2.3所示。
表2.3 read()函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 |
#include <unistd.h> |
函數(shù)原型 |
ssize_t read(int fd, void *buf, size_t count) |
函數(shù)傳入值 |
fd:文件描述符 |
buf:指定存儲(chǔ)器讀出數(shù)據(jù)的緩沖區(qū) |
count:指定讀出的字節(jié)數(shù) |
函數(shù)返回值 |
成功:讀到的字節(jié)數(shù)
0:已到達(dá)文件尾
1:出錯(cuò)
|
在讀普通文件時(shí),若讀到要求的字節(jié)數(shù)前已到達(dá)文件的尾部,則返回的字節(jié)數(shù)會(huì)小于希望讀出的字節(jié)數(shù)。
write()函數(shù)的語(yǔ)法要點(diǎn)如表2.4所示。
表2.4 write()函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 |
#include <unistd.h> |
函數(shù)原型 |
ssize_t write(int fd, void *buf, size_t count) |
函數(shù)傳入值 |
fd:文件描述符 |
buf:指定存儲(chǔ)器寫(xiě)入數(shù)據(jù)的緩沖區(qū) |
count:指定讀出的字節(jié)數(shù) |
函數(shù)返回值 |
成功:已寫(xiě)的字節(jié)數(shù)
1:出錯(cuò)
|
在寫(xiě)普通文件時(shí),寫(xiě)操作從文件的當(dāng)前指針位置開(kāi)始。
lseek()函數(shù)的語(yǔ)法要點(diǎn)如表2.5所示。
表2.5 lseek()函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 |
#include <unistd.h>
#include <sys/types.h>
|
函數(shù)原型 |
off_t lseek(int fd, off_t offset, int whence) |
函數(shù)傳入值 |
fd:文件描述符 |
offset:偏移量,每一讀寫(xiě)操作所需要移動(dòng)的距離,單位是字節(jié),可正可負(fù)(向前移,向后移) |
|
whence: 當(dāng)前位置的基點(diǎn) |
SEEK_SET:當(dāng)前位置為文件的開(kāi)頭,新位置為偏移量的大小 |
SEEK_CUR:當(dāng)前位置為文件指針的位置,新位置為當(dāng)前位置加上偏移量 |
SEEK_END:當(dāng)前位置為文件的結(jié)尾,新位置為文件的大小加上偏移量的大小 |
函數(shù)返回值 |
成功:文件的當(dāng)前位移
1:出錯(cuò)
|
3.函數(shù)使用實(shí)例
下面實(shí)例中的open()函數(shù)帶有3個(gè)flag參數(shù):O_CREAT、O_TRUNC和O_WRONLY,這樣就可以對(duì)不同的情況指定相應(yīng)的處理方法。另外,這里對(duì)該文件的權(quán)限設(shè)置為0600。其源碼如下所示:
下面列出文件基本操作的實(shí)例,基本功能是從一個(gè)文件(源文件)中讀取后10KB數(shù)據(jù)并復(fù)制到另一個(gè)文件(目標(biāo)文件)。在實(shí)例中源文件是以只讀方式打開(kāi)的,目標(biāo)文件是以只寫(xiě)方式打開(kāi)(可以是讀/寫(xiě)方式)的。若目標(biāo)文件不存在,可以創(chuàng)建并設(shè)置權(quán)限的初始值為644,即文件所有者可讀可寫(xiě),文件所屬組和其他用戶(hù)只能讀。
讀者需要留意的地方是改變每次讀/寫(xiě)的緩存大。▽(shí)例中為1KB)會(huì)怎樣影響運(yùn)行效率。
/* 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 /* 每次讀/寫(xiě)緩存大小,影響運(yùn)行效率 */
#define SRC_FILE_NAME "src_file" /* 源文件名 */
#define DEST_FILE_NAME "dest_file" /* 目標(biāo)文件名 */
#define OFFSET 10240 /* 復(fù)制的數(shù)據(jù)大小 */
int main()
{
int src_file, dest_file;
unsigned char buff[BUFFER_SIZE];
int real_read_len;
/* 以只讀方式打開(kāi)源文件 */
src_file = open(SRC_FILE_NAME, O_RDONLY);
/* 以只寫(xiě)方式打開(kāi)目標(biāo)文件,若此文件不存在則創(chuàng)建該文件, 訪(fǎng)問(wèn)權(quán)限值為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);
}
/* 將源文件的讀/寫(xiě)指針移到后10KB的起始位置 */
lseek(src_file, -OFFSET, SEEK_END);
/* 讀取源文件的后10KB數(shù)據(jù)并寫(xiě)到目標(biāo)文件中,每次讀寫(xiě)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
本文選自華清遠(yuǎn)見(jiàn)嵌入式培訓(xùn)教材《從實(shí)踐中學(xué)嵌入式Linux應(yīng)用程序開(kāi)發(fā)》
熱點(diǎn)鏈接:
1、Linux系統(tǒng)調(diào)用及用戶(hù)編程接口(API)
2、什么是Linux系統(tǒng)調(diào)用,包括哪些內(nèi)容
3、Linux中的文件及文件描述符
4、Linux文件系統(tǒng)之虛擬文件系統(tǒng)(VFS)
5、嵌入式文件系統(tǒng)構(gòu)建
更多新聞>> |