linux 文件io实例代码,linux 文件IO(示例代码)
1、文件描述符
(1)文件描述符的本質(zhì)是一個(gè)數(shù)字,這個(gè)數(shù)字本質(zhì)上是進(jìn)程表中文件描述符表的一個(gè)表項(xiàng),進(jìn)程通過(guò)文件描述符作為index去索引查表得到文件表指針,再間接訪問(wèn)得到這個(gè)文件對(duì)應(yīng)的文件表。
(2)文件描述符這個(gè)數(shù)字是open系統(tǒng)調(diào)用內(nèi)部由操作系統(tǒng)自動(dòng)分配的,操作系統(tǒng)分配這個(gè)fd時(shí)也不是隨意分配,也是遵照一定的規(guī)律的,我們現(xiàn)在就要研究這個(gè)規(guī)律。
(3)操作系統(tǒng)規(guī)定,fd從0開(kāi)始依次增加。fd也是有最大限制的,在linux的早期版本中(0.11)fd最大是20,所以當(dāng)時(shí)一個(gè)進(jìn)程最多允許打開(kāi)20個(gè)文件。linux中文件描述符表是個(gè)數(shù)組(不是鏈表),所以這個(gè)文件描述符表其實(shí)就是一個(gè)數(shù)組,fd是index,文件表指針是value
(4)當(dāng)我們?nèi)pen時(shí),內(nèi)核會(huì)從文件描述符表中挑選一個(gè)最小的未被使用的數(shù)字給我們返回。也就是說(shuō)如果之前fd已經(jīng)占滿了0-9,那么我們下次open得到的一定是10.(但是如果上一個(gè)fd得到的是9,下一個(gè)不一定是10,這是因?yàn)榭赡芮懊娓〉囊粋€(gè)fd已經(jīng)被close釋放掉了)
(5)fd中0、1、2已經(jīng)默認(rèn)被系統(tǒng)占用了,因此用戶進(jìn)程得到的最小的fd就是3了。
(6)linux內(nèi)核占用了0、1、2這三個(gè)fd是有用的,當(dāng)我們運(yùn)行一個(gè)程序得到一個(gè)進(jìn)程時(shí),內(nèi)部就默認(rèn)已經(jīng)打開(kāi)了3個(gè)文件,這三個(gè)文件對(duì)應(yīng)的fd就是0、1、2。這三個(gè)文件分別叫stdin、stdout、stderr。也就是標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤。
(7)標(biāo)準(zhǔn)輸入一般對(duì)應(yīng)的是鍵盤(可以理解為:0這個(gè)fd對(duì)應(yīng)的是鍵盤的設(shè)備文件),標(biāo)準(zhǔn)輸出一般是LCD顯示器(可以理解為:1對(duì)應(yīng)LCD的設(shè)備文件)
(8)printf函數(shù)其實(shí)就是默認(rèn)輸出到標(biāo)準(zhǔn)輸出stdout上了。stdio中還有一個(gè)函數(shù)叫fpirntf,這個(gè)函數(shù)就可以指定輸出到哪個(gè)文件描述符中。
2、常用API
open、close、write、read、lseek
2.1OPEN
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
const char *pathname為需要打開(kāi)的文件、
flags通過(guò)一些宏設(shè)置讀寫權(quán)限
O_RDONLY、 O_WRONLY 、O_RDWR(只讀 只寫 讀寫)
O_APPEND?O_APPEND屬性去打開(kāi)文件時(shí),如果這個(gè)文件中本來(lái)是有內(nèi)容的,則新寫入的內(nèi)容會(huì)接續(xù)到原來(lái)內(nèi)容的后面
O_TRUNC ?O_TRUNC屬性去打開(kāi)文件時(shí),如果這個(gè)文件中本來(lái)是有內(nèi)容的,則原來(lái)的內(nèi)容會(huì)被丟棄。
O_CREAT ??O_CREAT若不存在則創(chuàng)建。open函數(shù)在使用O_CREAT標(biāo)志去創(chuàng)建文件時(shí),可以使用第三個(gè)參數(shù)mode來(lái)指定要?jiǎng)?chuàng)建的文件的權(quán)限。mode使用4個(gè)數(shù)字來(lái)指定權(quán)限的,其中后面三個(gè)很重要,對(duì)應(yīng)我們要?jiǎng)?chuàng)建的這個(gè)文件的權(quán)限標(biāo)志。譬如一般創(chuàng)建一個(gè)可讀可寫不可執(zhí)行的文件就用0666
O_EXCL ?加上O_EXCL如果文件已經(jīng)被打開(kāi)則打開(kāi)失敗
O_NONBLOCK 默認(rèn)為阻塞模式。添加這個(gè)設(shè)置為非阻塞模式
O_SYNC?write阻塞等待底層完成寫入才返回到應(yīng)用層。
2.2 read
ssize_t read(int fd, void *buf, size_t count);
2.3 write
ssize_t write(int fd, const void *buf, size_t count);
2.3lseek
執(zhí)行read與write函數(shù)都會(huì)使文件指針移動(dòng)。lseek函數(shù)可以調(diào)整文件指針。
off_t lseek(int fd, off_t offset, int whence);
參數(shù)解釋。第一個(gè)代表文件描述符、第二個(gè)代表移動(dòng)個(gè)數(shù)、第三個(gè)設(shè)置移動(dòng)頭。
lseek(fd, 0 ,SEEK_SET);//文件指針指向頭
SEEK_SET代表指向頭
SEEK_END代表尾部
SEEK_CUR代表當(dāng)前位置
3.3close
可以通過(guò)close關(guān)閉打開(kāi)的文件描述符。
3.4dup和dup2函數(shù)
(1)dup系統(tǒng)調(diào)用對(duì)fd進(jìn)行復(fù)制,會(huì)返回一個(gè)新的文件描述符(譬如原來(lái)的fd是3,返回的就是4)
(2)dup系統(tǒng)調(diào)用有一個(gè)特點(diǎn),就是自己不能指定復(fù)制后得到的fd的數(shù)字是多少,而是由操作系統(tǒng)內(nèi)部自動(dòng)分配的,分配的原則遵守fd分配的原則
(3)dup2和dup的作用是一樣的,都是復(fù)制一個(gè)新的文件描述符。但是dup2允許用戶指定新的文件描述符的數(shù)字。
3.5fcntl的原型和作用
fcntl函數(shù)是一個(gè)多功能文件管理的工具箱,接收2個(gè)參數(shù)+1個(gè)變參。第一個(gè)參數(shù)是fd表示要操作哪個(gè)文件,第二個(gè)參數(shù)是cmd表示要進(jìn)行哪個(gè)命令操作。變參是用來(lái)傳遞參數(shù)的,要配合cmd來(lái)使用。
4、標(biāo)準(zhǔn)IO庫(kù)介紹
4.1、標(biāo)準(zhǔn)IO和文件IO有什么區(qū)別
(1)看起來(lái)使用時(shí)都是函數(shù),但是:標(biāo)準(zhǔn)IO是C庫(kù)函數(shù),而文件IO是linux系統(tǒng)的API
(2)C語(yǔ)言庫(kù)函數(shù)是由API封裝而來(lái)的。庫(kù)函數(shù)內(nèi)部也是通過(guò)調(diào)用API來(lái)完成操作的,但是庫(kù)函數(shù)因?yàn)槎嗔艘粚臃庋b,所以比API要更加好用一些。
(3)庫(kù)函數(shù)比API還有一個(gè)優(yōu)勢(shì)就是:API在不同的操作系統(tǒng)之間是不能通用的,但是C庫(kù)函數(shù)在不同操作系統(tǒng)中幾乎是一樣的。所以C庫(kù)函數(shù)具有可移植性而API不具有可移植性。
(4)性能上和易用性上看,C庫(kù)函數(shù)一般要好一些。譬如IO,文件IO是不帶緩存的,而標(biāo)準(zhǔn)IO是帶緩存的,因此標(biāo)準(zhǔn)IO比文件IO性能要更高。
4.2、常用標(biāo)準(zhǔn)IO函數(shù)介紹
(1)常見(jiàn)的標(biāo)準(zhǔn)IO庫(kù)函數(shù)有:fopen、fclose、fwrite、fread、ffulsh、fseek
#include #include#include#include#include#include
int main(int argc , char *argv[])
{int fd=-1; //fd 文件描述符
char buf[100]={0};//字符緩沖區(qū)
char writebuf[20]="ilovezw";//字符緩沖區(qū)
intret;//第一步打開(kāi)//fd = open ("a.txt",O_RDWR|O_APPEND);
fd = open ("a.txt",O_RDWR);if(-1 ==fd)
{
perror("文件打開(kāi)錯(cuò)誤");
_exit(-1);
}else{
printf("文件打開(kāi)成功,fd=%d.\n",fd);
}//lseek(fd, 3 ,SEEK_SET);//光標(biāo)位移3//第二步讀寫
ret=write(fd,writebuf,strlen(writebuf));//寫函數(shù)
if(-1==ret)
{//printf("write error");
perror("write error");
_exit(-1);
}else{
printf("ret=%d\n",ret);//lseek(fd, -ret ,SEEK_SET);//光標(biāo)位移3
}
lseek(fd,0 ,SEEK_SET);//文件指針指向頭
ret=read(fd,buf,20);//讀文件
if(-1==ret)
{//printf("read error");
perror("read error");
_exit(-1);
}else{
printf("ret=%d,a.txt=%s\n",ret,buf);
}//第三步關(guān)閉
close(fd);return 0;
}
/*標(biāo)準(zhǔn)IO
*/
#include#include#include
int main(int argc,char *argv[])
{
FILE*fp =NULL;char buf[10];
fp= fopen("1.txt","r+");if(NULL ==fp)
{
perror("fopen");
exit(-1);
}
memset(buf,0,sizeof(buf));
fwrite("12345",1,5,fp);
fseek( fp,0, SEEK_SET );
fread(buf,1,5,fp);
printf("%s\n",buf);
fclose(fp);return 0;
}
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的linux 文件io实例代码,linux 文件IO(示例代码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux+卸载+gpm服务,Linux
- 下一篇: linux cut性能,Linux cu