Linux什么是文件IO,linux中文件IO
一. linux常用文件IO接口
1.1. 文件描述符
1.1.1.?文件描述符的本質(zhì)是一個數(shù)字,這個數(shù)字本質(zhì)上是進程表中文件描述符表的一個表項,進程通過文件描述符作為index去索引查表得到文件表指針,再間接訪問得到這個文件對應(yīng)的文件表。
1.1.2.?文件描述符這個數(shù)字是open系統(tǒng)調(diào)用內(nèi)部由操作系統(tǒng)自動分配的,操作系統(tǒng)分配這個fd時也不是隨意分配,也是遵照一定的規(guī)律的:fd從0開始依次增加。fd也是有最大限制的,在linux的早期版本中(0.11)fd最大是20,所以當(dāng)時一個進程最多允許打開20個文件。linux中文件描述符表是個數(shù)組(不是鏈表),所以這個文件描述符表其實就是一個數(shù)組,fd是index,文件表指針是value。當(dāng)我們?nèi)pen時,內(nèi)核會從文件描述符表中挑選一個最小的未被使用的數(shù)字給我們返回。
1.1.3.?fd中0、1、2已經(jīng)默認被系統(tǒng)占用了,因此用戶進程得到的最小的fd就是3了。這三個文件對應(yīng)的fd就是0、1、2。這三個文件分別叫stdin、stdout、stderr。也就是標準輸入、標準輸出、標準錯誤。
1.2.?open
1.2.1.?在linux系統(tǒng)中要操作一個文件,一般是先open打開一個文件,得到一個文件描述符,然后對文件進行讀寫操作(或其他操作),最后close關(guān)閉文件即可
1.2.2.?文件平時是存在塊設(shè)備中的文件系統(tǒng)中的,我們把這種文件叫靜態(tài)文件。當(dāng)我們?nèi)pen打開一個文件時,linux內(nèi)核做的操作包括:內(nèi)核在進程中建立了一個打開文件的數(shù)據(jù)結(jié)構(gòu),記錄下我們打開的這個文件;內(nèi)核在內(nèi)存中申請一段內(nèi)存,并且將靜態(tài)文件的內(nèi)容從塊設(shè)備中讀取到內(nèi)存中特定地址管理存放(叫動態(tài)文件)。
1.2.3.?打開文件后,以后對這個文件的讀寫操作,都是針對內(nèi)存中這一份動態(tài)文件的,而并不是針對靜態(tài)文件的。當(dāng)我們對動態(tài)文件進行讀寫后,此時內(nèi)存中的動態(tài)文件和塊設(shè)備中的靜態(tài)文件就不同步了,當(dāng)我們close關(guān)閉動態(tài)文件時,close內(nèi)部內(nèi)核將內(nèi)存中的動態(tài)文件的內(nèi)容去更新(同步)塊設(shè)備中的靜態(tài)文件。這樣做主要由于:塊設(shè)備本身有讀寫限制(回憶NnadFlash、SD等塊設(shè)備的讀寫特征),本身對塊設(shè)備進行操作非常不靈活。而內(nèi)存可以按字節(jié)為單位來操作,而且可以隨機操作(內(nèi)存就叫RAM,random),很靈活。所以內(nèi)核設(shè)計文件操作時就這么設(shè)計了。
1.3.?read
ssize_t read(int fd,void *buf,size_t count);
@H_404_4@
View Code
@H_404_4@
a. fd表示要讀取哪個文件,fd一般由前面的open返回得到
b.?buf是應(yīng)用程序自己提供的一段內(nèi)存緩沖區(qū),用來存儲讀出的內(nèi)容
c.?count是我們要讀取的字節(jié)數(shù)
d.?返回值ssize_t類型是linux內(nèi)核用typedef重定義的一個類型(其實就是int),返回值表示成功讀取的字節(jié)數(shù)。
1.4. write
ssize_t write(int fd,const void *buf,size_t count);
@H_404_4@
View Code
@H_404_4@
1.4.1.?寫入用write系統(tǒng)調(diào)用,write的原型和理解方法和read相似
1.5.?lseek
off_t lseek(int fd,off_t offset,int whence);
@H_404_4@
View Code
@H_404_4@
1.5.1.?文件指針:當(dāng)我們要對一個文件進行讀寫時,一定需要先打開這個文件,所以我們讀寫的所有文件都是動態(tài)文件。動態(tài)文件在內(nèi)存中的形態(tài)就是文件流的形式。
1.5.2.?在動態(tài)文件中,我們會通過文件指針來表征這個正在操作的位置。所謂文件指針,就是我們文件管理表這個結(jié)構(gòu)體里面的一個指針。所以文件指針其實是vnode中的一個元素。這個指針表示當(dāng)前我們正在操作文件流的哪個位置。這個指針不能被直接訪問,linux系統(tǒng)用lseek函數(shù)來訪問這個文件指針。
1.5.3.?當(dāng)我們打開一個空文件時,默認情況下文件指針指向文件流的開始。所以這時候去write時寫入就是從文件開頭開始的。write和read函數(shù)本身自帶移動文件指針的功能,所以當(dāng)我write了n個字節(jié)后,文件指針會自動向后移動n位。如果需要人為的隨意更改文件指針,那就只能通過lseek函數(shù)了
1.5.4.?用lseek計算文件長度(length?=?lseek(fd,SEEK_END))
1.6. close
int close(int fd);
@H_404_4@
View Code
@H_404_4@
1.6.1. 關(guān)閉打開的文件
PS:實時查man手冊
(1)當(dāng)我們寫應(yīng)用程序時,很多API原型都不可能記得,所以要實時查詢,用man手冊
(2)man 1 xx查linux shell命令,man 2 xxx查API, man 3 xxx查庫函數(shù)
二.?open函數(shù)的flag詳解
2.1.?讀寫權(quán)限
a.?O_RDONLY就表示以只讀方式打開,
b.?O_WRONLY表示以只寫方式打開,
c.?O_RDWR表示以可讀可寫方式打開
2.2.?打開存在并有內(nèi)容的文件時
2.3.?打開不存在的文件時
2.4.?O_NONBLOCK
2.5.?O_SYNC
三.?文件讀寫的一些細節(jié)
3.1.?errno
3.2.?perror
3.3.?文件IO效率和標準IO
四.?退出進程方式
4.1. 在main(main函數(shù)由其父進程調(diào)用,故返回后進程就over)用return,一般原則是程序正常終止return 0,如果程序異常終止則return -1。
4.2. 正式終止進程(程序)應(yīng)該使用exit或者_exit或者_Exit之一。
五.?文件共享的實現(xiàn)方式
#include #include#include#include#include#include
int main(int argc,char *argv[])
{int fd1 = -1,fd2 = -1; //fd 就是file descriptor,文件描述符
char buf[100] = {0};char writebuf[20] = "l love linux";int ret = -1;//第一步:打開文件
fd1 = open("a.txt",O_RDWR);
fd2= open("a.txt",O_RDWR);//fd = open("a.txt",O_RDONLY);
if ((-1 == fd1) || (fd2 == -1)) //有時候也寫成: (fd < 0)
{//printf("\n");
perror("");//return -1;
_exit(-1);
}else{
printf("文件打開成功,fd1 = %d. fd2 = %d.\n",fd1,fd2);
}#if 0
//第二步:讀寫文件//write(fd,writebuf,strlen(writebuf));if (ret < 0)
{//printf("write失敗.\n");
perror("write失敗");
_exit(-1);
}else{
printf("write成功,寫入了%d個字符\n",ret);
}#endif
#if 1
while(1)
{//0,sizeof(buf));
ret= read(fd1,buf,2);if (ret < 0)
{
printf("read失敗\n");
_exit(-1);
}else{//printf("實際讀取了%d字節(jié).\n",ret);
printf("fd1:[%s].\n",buf);
}
sleep(1);//sizeof(buf));
ret= read(fd2,ret);
printf("fd2:[%s].\n",buf);
}
}#endif
//第三步:關(guān)閉文件
close(fd1);
close(fd2);
_exit(0);
}
@H_404_4@
View Code
@H_404_4@
@H_404_4@
相關(guān)文章
猜你在找的Linux相關(guān)文章
禁止軟件升級 sudo echo 軟件包名 hold | sudo dpkg --set-selections 取消軟件禁止升級的限制 sudo echo 軟件包名 install | sudo dp
譯 原文作者:Bobbin Zachariah 原文鏈接:https://linoxide.com/linux-command/essential-linux-basic-commands/ @ 在本
規(guī)則包含兩個部分,一個是依賴關(guān)系,一個是生成目標的方法。在Makefile中,規(guī)則的順序是很重要的,因為,Makefile中只應(yīng)該有一個最終目標,其它的目標都是被這個目標所連帶出來的,所以一定要讓make知道你的最終目標是什么。一般來說,定義在Makefile中的目標可能會有很多,但是第一條規(guī)則中的目標將被確立為最終的目標。如果第一條規(guī)則中的目標有很多個,那么,第一個
#!/bin/bashname=Tomif grep "$name" databasefile > /dev/null 2>&1then?? :else?? echo "$1 not found in databasefile"?? exit 1fi#!/bin/bash# Scriptname: nosyecho -e "Ar
1、name=${name2:-word}當(dāng)name2這個變量已經(jīng)設(shè)置過了(就是說name2這個變量設(shè)置過值),則把它的值賦值給name。如果name2這個變量沒有設(shè)置過值,則把word當(dāng)作name的值。2、name=${name2:=word}當(dāng)name2這個變量已經(jīng)設(shè)置過了,就把name2的值賦值給name這個變量,如果name2沒有設(shè)置過,則把word賦值給name23
/etc/init.d 這個目錄是用來存放系統(tǒng)或服務(wù)器以System V模式啟動的腳本,這在以System V模式啟動或初始化的系統(tǒng)中常見。比如Fedora/RedHat;/etc/xinit.d 如果服務(wù)器是通過xinetd模式運行的,它的腳本要放在這個目錄下。有些系統(tǒng)沒有這個目錄, 比如Slackware,有些老的版本也沒有。在Rehat/Fedora中比較新的版
在POSIX shell中,命令的結(jié)果可以通過%>;的形式來定義(其中%表示文件描述符:1為標準輸出stdout、2為標準錯誤 stderr)! 系統(tǒng)默認%值是1,也就是1>;,而1>;可以簡寫為>;,也就是默認為>;。而stdout的默認目標是終端(這點不用驗證吧)。另外,stderr的默認目標我個人認為也是終端,比如:#abcddcbash: abcddcba: not
總結(jié)
以上是生活随笔為你收集整理的Linux什么是文件IO,linux中文件IO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux7双网卡设置,Centos 7
- 下一篇: linux 服务器基本信息,查看linu