當前位置:
首頁 > 知識 > Linux下的文件I/O編程

Linux下的文件I/O編程

(一).open()打開文件

#include

#include

#include

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

參數1:pathname,文件所在路徑

參數2:flags,文件許可權,相對於程序進程

常見宏為:O_WRONLY,O_RDONLY,O_RDWR,O_EXCL,O_APPEND,O_DUMP

參數3:mode,當創建文件時候使用,一般為umask的值。

返回值: 成功返迴文件描述符,否則返回-1.

(二)close,關閉一個文件。參數為文件描述符

#include

int close(int fd);

(三)write,向文件中寫數據

#include

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

fd: 文件描述符

buf:存儲將要寫的數據

count: 寫入的長度,以位元組為單位

返回值:寫入成功時,返回寫入的字元長度,否則返回-1。

(四)read,讀文件中數據

#include

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

fd: 文件描述符

buf:存儲將要讀入的數據

count: 讀出的長度,以位元組為單位

返回值:讀成功時,返回讀出的字元長度,否則返回-1。

例如:

#include

(五)lseek,修改文件偏移量

#include

#include

ff_t lseek(int fd, off_t offset, int whence);

fd: 文件描述符

offset:將要偏移 的位元組數。

whence:從那開始偏移,宏定義如下:

SEEK_END 文件末尾

SEEK_CUR 當前偏移量位置

SEEK_SET 文件開頭位置

注意:當偏移量大於文件長度時,產生空洞,空洞是由所設置的偏移量超過文件尾端,並寫了一些數據造成了,其從原文件尾端到新偏移的位置之間即是產生的空洞。空洞不佔用磁碟空間,可以使用:

du filename #查看文件所佔實際磁碟空間

ls filename #實際文件的大小

例如:

#include

#include

#include

#include

#include

#include

#define BUFF 12

int main()

{

char str1[BUFF] = "jigntikai";

char str2[BUFF] = "wojisuhihawe";

int fd;

if ( (fd = open("a.txt",O_WRONLY|O_CREAT,0744)) =

{

perror("open file fail
");

exit(EXIT_FAILURE);

}

if( write(fd,str1,BUFF) == -1 )

{

perror("write fial fail
");

exit(EXIT_FAILURE);

}

if( lseek(fd,1024,SEEK_END) == -1 )

{

perror("lseek fail
");

}

write(fd,str2,BUFF);

return 0;

}

(六)access 判斷文件是否具有讀,寫,可執行或者是否存在

#include

int access(const char *pathname, int mode);

pathname: 文件名

mode 可以選擇以下宏:

F_OK 文件是否存在

R_OK 文件否具有讀許可權

X_OK 文件否具有可執行許可權

W_OK 文件否具有寫許可權

返回值:滿足mode中的參數並且正確執行則返回0 ,否則返回-1。

(七)dup或dup2,創建一個文件描述符,其指向同一個文件表

#include

int dup(int oldfd);

oldfd:原來的文件描述符

newfd:指定新的文件描述符數值,如果該描述已經存在則先將其關閉,若oldfd等於newfd,ze返回newfd,而不關閉。

在此簡單介紹一下文件的內核結構:首先計算機系統中有一個進程表,其中的每個進程表項,該表項中有一個打開文件描述符表,該打開的文件描述表中有很多文件描述符表項,每項包括兩部分:文件描述符標誌與文件指針,其中文件指針指向一個文件表,文件表中存放著文件的狀態標誌即是否可讀是否可寫,當前文件的偏移量,還有一個v節點指針,指針v節點指針指向一個v節點表,v節點表主要存放文件的所有者,文件長度,文件的設備以及文件實際數據塊在磁碟上的位置等一系列信息。可能這樣描不太清楚,下面用一張圖來描述:

(八)sync與fsync

(對於以下會主要是針對的內核緩衝)由於io操作會首先將數據放入內核緩衝區,所以在寫的時候如果出現系統故障則緩衝區的數據可能會丟失,所以為了防止這種情況發生,以上兩個函數使得內核緩衝區的數據立即寫入磁碟。

#include

void sync(void);將所有緩衝排入寫隊列,然後立即返回

int fsync(int fd);將所有緩衝排入寫隊列,直到該緩衝去的數據寫入磁碟後才返回。

int fdatasync(int fd);幾乎和fsync函數相同,只是fdatasync(int fd)函數隻影響數據部分,而fsync還會同步更新文件的屬性。

(九)fcntl函數,該函數可以改變已經發開文件的性質

#include

#include

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

fd:文件描述符

cmd 指明該函數執行什麼功能

F_DUPFD 賦值文件描述符,功能相當於dup和dup2函數。例如:

dup(fd)等價於

fcntl(fd,F_DUPFD,0)

dup2(oldfd,newfd)等價於

close(newfd);

fcntl(oldfd,F_DUPFD,newfd);

F_GETFD 的到文件描述符標誌,當前之定義一個文件描述符標誌,FD_CLOSEEXEC.此時第三個參數被忽視。

F_SETFD 設置文件描述符標誌,設置的值是函數的第三個參數,其一般可設置為0表示關閉,1表示打開。

F_SETFL 設置文件狀態標誌,其值放在函數的第三個參數,和open函數第二個參數的值一樣的。

F_GETFL 得到文件狀態標誌。此時第三個參數被忽視。

arg 可選參數,根據第二個參數填寫。

返回值:出錯返回-1,否則哈返達到的標誌。

例如:

#include

#include

#include

#include

int main(int argc,char * argv[])

{

int fd;

int val=3;

if( (fd = open(argv[1],O_RDWR|O_APPEND)) == -1 )//測試一下是否可以同時檢測出文件的讀寫屬性

{

exit(2);

}

if( val = fcntl(fd,F_GETFL,0) == -1 )

{

exit(1);

}

printf("%d
",val);

printf("%d %d %d
",O_RDONLY,O_WRONLY,O_RDWR);

int n = val & O_ACCMODE;

if( n == O_RDONLY)

printf("read
");

if(O_WRONLY & val )

printf("write
");

if( n == O_RDWR)

printf("read and write
");

}

(十)最後再說一下Linux緩衝的問題吧

linux中有兩個級別的緩衝:IO緩衝與內核緩衝

(1)IO緩衝:對於標準IO操作,都會有一個緩衝區,當用戶想要寫數據時,首先將數據寫入緩衝區,待緩衝區滿之後才能調用系統函數寫入內核緩衝區。當用戶想讀取數據時,首先向內核讀取一定的數據放入IO緩衝區,讀操作從緩衝區中讀數據,當讀完IO緩衝區的數據時,才能再讀取數據到IO緩衝區。

目的:減少對磁碟的讀寫次數,提高工作效率。

(2)內核緩衝區:操作系統內核部分也有緩衝,其與IO緩衝區是不同的,其主要區別用一張圖表示:


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Linux資訊速推 的精彩文章:

害慘了Linux:Systemd 可被嫌棄

TAG:Linux資訊速推 |