




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、lseek不帶緩存的文件I/O操作本節主要介紹不帶緩存的文件I/O操作,主要用到5個函數:open、read、write、和close。這里的不帶緩存是指每一個函數都只調用系統中的一個函數。這些函數雖然不是ANSIC的組成部分,但是是POSIX的組成部分。631open和close(1)open和close函數說明open函數是用于打開或創建文件,在打開或創建文件時可以指定文件的屬性及用戶的權限等各種參數。close函數是用于關閉一個打開文件。當一個進程終止時,它所有已打開的文件都由內核自動關閉,很多程序都使用這一功能而不顯示地關閉一個文件。(2)open和close函數格式open函數的語法
2、格式如表6.1所示。表6.1open函數語法要點所需頭文件#include/提供類型pid_t的定義#include#include續表函數原型intopen(constchar*pathname,flags,intperms)pathname被打開的文件名(可包括路徑名)O_RDONLY:只讀方式打開文件O_WRONLY:可寫方式打開文件O_RDWR:讀寫方式打開文件O_CREAT:如果該文件不存在,就創建一個新的文件,并用第三個參數為其設置權限O_EXCL:如果使用O_CREAT時文件存在,則可返回錯誤消息。這一參數可測試文件是否存在O_NOCTTY:使用本參數時,如文件為終端,那么終端不
3、可以作為調用open()系統調用的那個進程的控制終端O_TRUNC:如文件已經存在,并且以只讀或只寫成功打開,那么會先全部刪除文件中原有數據flag:文件打開的方式O+APPEND:以添加方式打開文件,在打開文件的同時,文件指針指向文件的末尾函數傳入值perms被打開文件的存取權限,為8進制表示法函數返回值成功:返回文件描述符失敗:1在open函數中,flag參數可通過“|”組合構成,但前3個函數不能相互組合。perms是文件的存取權限,采用8進制表示法,相關內容讀者可參見第2章。close函數的語法格式如下表6.2所示。表6.2close函數語法要點嵌入式Linux應用程序開發詳解第6章、文
4、件IO編程所需頭文件#include函數原型intclose(intfd)函數輸入值fd:文件描述符函數返回值0:成功1:出錯open和close函數使用實例下面實例中的open函數帶有3個flag參數:O_CREAT、O_TRUNC和O_WRONLY,這樣就可以對不同的情況指定相應的處理方法。另外,這里對該文件的權限設置為0600。其丿、源碼如下所示:/*open.c*/#include#include#include#include#include#includeintmain(void)intfd;/*調用open函數,以可讀寫的方式打開,注意選項可以用“|”符號連接*/if(fd=op
5、en(/tmp/hello.c,O_CREAT|O_TRUNC|O_WRONLY,0600)0)perror(open:);exit(1);elseprintf(Openfile:hello.c%dn,fd);if(close(fd)0)perror(close:);exit(1);elseprintf(C);exit(0);root(none)1#./openOpenfile:hello.c3Closehello.croot(none)tmp#ls-l|grephello.c-rw1rootroot0Dec400:59hello.c經過交叉編譯后,將文件下載到目標板,則該可執行文件運行后就能
6、在目錄/tmp下新建一個hello.c的文件,其權限為0600。注意open函數返回的文件描述符一定是最小的未用文件描述符。由于一個進程在啟動時自動打開了0、1、2三個文件描述符,因此,該文件運行結果中返回的文件描述符為3。讀者可以嘗試在調用open函數之前,加依據close(O),則此后在open函數時返回的文件描述符為0(若關閉文件描述符1,則在執行時會由于沒有標準輸出文件而無法輸出)。632read、write和Iseekread、write和Iseek函數作用read函數是用于將指定的文件描述符中讀出數據。當從終端設備文件中讀出數據時,通常一次最多讀一行。write函數是用于向打開的文
7、件寫數據,寫操作從文件的當前位移量處開始。若磁盤已滿或超出該文件的長度,則write函數返回失敗。Iseek函數是用于在指定的文件描述符中將文件指針定位到相應的位置。read和write函數格式read函數的語法格式如下表6.3所示。表6.3read函數語法要點所需頭文件#incIude函數原型ssize_tread(intfd,void*buf,size_tcount)fd:文件描述符函數傳入值buf:指定存儲器讀出數據的緩沖區count:指定讀出的字節數函數返回值成功:讀到的字節數0:已到達文件尾1:出錯在讀普通文件時,若讀到要求的字節數之前已到達文件的尾部,則返回的字節數會小于希望讀出的
8、字節數。write函數的語法格式如下表6.4所示。表6.4write函數語法要點所需頭文件#incIude函數原型ssize_twrite(intfd,void*buf,size_tcount)嵌入式Linux應用程序開發詳解第6章、文件IO編程fd:文件描述符函數傳入值buf:指定存儲器寫入數據的緩沖區count:指定讀出的字節數函數返回值成功:已寫的字節數1:出錯在寫普通文件時,寫操作從文件的當前位移處開始。Iseek函數的語法格式如下表6.5所示。表6.5lseek函數語法要點所需頭文件#incIude#incIude函數原型off_tIseek(intfd,off_toffset,in
9、twhence)fd:文件描述符函數傳入值offset:偏移量,每一讀寫操作所需要移動的距離,單位是字節的數量,可正可負(向前移,向后移)續表SEEK_SET:當前位置為文件的開頭,新位置為偏移量的大小SEEK_CUR:當前位置為文件指針的位置,新位置為當前位置加上偏移量whence:當前位置的基點SEEK_END:當前位置為文件的結尾,新位置為文件的大小加上偏移量的大小函數返回值成功:文件的當前位移1:出錯(3)函數使用實例該示例程序首先打開上一節中創建的文件,然后對此文件進行讀寫操作(記得要將文件打開屬性改為可讀寫,將文件權限也做相應更改)。接著,寫入“HeIIo!Imwritingtot
10、hisfiIe!”,10此時文件指針位于文件尾部。接著在使用Iseek函數將文件指針移到文件開始處,并讀出個字節并將其打印出來。程序源代碼如下所示:/*write.c*/#incIude#incIude#incIude#incIude#incIude#incIude#incIude#defineMAXSIZEintmain(void)inti,fd,size,Ien;char*buf=HeIIo!ImwritingtothisfiIe!;charbuf_r10;len=strlen(buf);/*首先調用open函數,并指定相應的權限*/if(fd=open(/tmp/hello.c,O_CR
11、EAT|O_TRUNC|O_RDWR,0666)0)perror(open:);exit(1);elseprintf(openfile:hello.c%dn,fd);/*調用write函數,將buf中的內容寫入到打開的文件中*/if(size=write(fd,buf,len)0)perror(write:);exit(1);elseprintf(Write:%sn,buf);/*調用Isseek函數將文件指針移到文件起始,并讀出文件中的10個字節*/lseek(fd,0,SEEK_SET);if(size=read(fd,buf_r,10)0)perror(read:);exit(1);eI
12、seprintf(readformfiIe:%sn,buf_r);if(cIose(fd)0)perror(cIose:);exit(1);eIseprintf(CIoseheII);exit(0);root(none)1#./writeopenfiIe:heIIo.c3嵌入式Linux應用程序開發詳解第6章、文件IO編程Write:HeIIo!ImwritingtothisfiIe!readformfiIe:HeIIo!ImCIoseheIIo.croot(none)1#cat/tmp/heIIo.cHeIIo!ImwritingtothisfiIe!6.3.3fcntI(1)fcntI函數
13、說明前面的這5個基本函數實現了文件的打開、讀寫等基本操作,這一節將討論的是,在文件已經共享的情況下如何操作,也就是當多個用戶共同使用、操作一個文件的情況,這時,Linux通常采用的方法是給文件上鎖,來避免共享的資源產生競爭的狀態。文件鎖包括建議性鎖和強制性鎖。建議性鎖要求每個上鎖文件的進程都要檢查是否有鎖存在,并且尊重已有的鎖。在一般情況下,內核和系統都不使用建議性鎖。強制性鎖是由內核執行的鎖,當一個文件被上鎖進行寫入操作的時候,內核將阻止其他任何文件對其進行讀寫操作。采用強制性鎖對性能的影響很大,每次讀寫操作都必須檢查是否有鎖存在。在Linux中,實現文件上鎖的函數有lock和fcntl,其
14、中flock用于對文件施加建議性鎖,而fcntl不僅可以施加建議性鎖,還可以施加強制鎖。同時,fcntl還能對文件的某一記錄進行上鎖,也就是記錄鎖。記錄鎖又可分為讀取鎖和寫入鎖,其中讀取鎖又稱為共享鎖,它能夠使多個進程都能在文件的同一部分建立讀取鎖。而寫入鎖又稱為排斥鎖,在任何時刻只能有一個進程在文件的某個部分上建立寫入鎖。當然,在文件的同一部分不能同時建立讀取鎖和寫入鎖。注意fcntl是一個非常通用的函數,它還可以改變文件進程各方面的屬性,在本節中,主要介紹它建立記錄鎖的方法,關于它其他用戶感興趣的讀者可以參看fcntl手冊。(2)fcntl函數格式用于建立記錄鎖的fcntl函數格式如表6.
15、6所示。表6.6fcntl函數語法要點所需頭文件#include#include#include函數原型intfcnt1(intfd,intcmd,structflock*lock)fd:文件描述符F_DUPFD:復制文件描述符F_GETFD:獲得fd的close-on-exec標志,若標志未設置,則文件經過exec函數之后仍保持打開狀態F_SETFD:設置close-on-exec標志,該標志以參數arg的FD_CLOEXEC位決定F_GETFL:得到open設置的標志函數傳入值cmdF_SETFL:改變open設置的標志F_GETFK:根據lock描述,決定是否上文件鎖F_SETFK:設置
16、lock描述的文件鎖F_SETLKW:這是F_SETLK的阻塞版本(命令名中的W表示等待(wait)如果存在其他鎖,則調用進程睡眠;如果捕捉到信號則睡眠中斷F_GETOWN:檢索將收到SIGIO和SIGURG信號的進程號或進程組號F_SETOWN:設置進程號或進程組號Lock:結構為flock,設置記錄鎖的具體狀態,后面會詳細說明函數返回值成功:01:出錯這里,lock的結構如下所示:Structflockshortl_type;off_tl_start;shortl_whence;off_tl_len;pid_tl_pid;lock結構中每個變量的取值含義如表6.7所示。表6.7lock結構
17、變量取值F_RDLCK:讀取鎖(共享鎖)l_typeF_WRLCK:寫入鎖(排斥鎖)F_UNLCK:解鎖l_stat相對位移量(字節)SEEK_SET:當前位置為文件的開頭,新位置為偏移量的大小SEEK_CUR:當前位置為文件指針的位置,新位置為當前位置加上偏移量l_whence:相對位移量的起點(同lseek的whence)。SEEK_END:當前位置為文件的結尾,新位置為文件的大小加上偏移量的大小l_len加鎖區域的長度小技巧為加鎖整個文件,通常的方法是將l_start說明為0,l_whence說明為SEEK_SET,l_len說明為0。(3)fcntl使用實例下面首先給出了使用fcntl
18、函數的文件記錄鎖函數。在該函數中,首先給flock結構體的對應位賦予相應的值。接著使用兩次fcntl函數分別用于給相關文件上鎖和判斷文件是否可以上鎖,這里用到的cmd值分別為F_SETLK和F_GETLK。這個函數的源代碼如下所示:嵌入式Linux應用程序開發詳解第6章、文件IO編程/*lock_set函數*/voidlock_set(intfd,inttype)structflocklock;lock.l_whence=SEEK_SET;賦值lock結構體lock.l_start=0;lock.l_len=0;while(1)lock.l_type=type;/*根據不同的type值給文件上
19、鎖或解鎖*/if(fcntl(fd,F_SETLK,&lock)=0)if(lock.l_type=F_RDLCK)printf(readlocksetby%dn,getpid();elseif(lock.l_type=F_WRLCK)printf(writelocksetby%dn,getpid();elseif(lock.l_type=F_UNLCK)printf(releaselockby%dn,getpid();return;/*判斷文件是否可以上鎖*/fcntl(fd,F_GETLK,&lock);/*判斷文件不能上鎖的原因*/if(lock.l_type!=F_UNLCK)/*/該
20、文件已有寫入鎖*/if(lock.l_type=F_RDLCK)printf(readlockalreadysetby%dn,lock.l_pid);/*該文件已有讀取鎖*/elseif(lock.l_type=F_WRLCK)printf(writelockalreadysetby%dn,lock.l_pid);getchar();hello文件,之后對其上寫入鎖,下面的實例是測試文件的寫入鎖,這里首先創建了一個最后釋放寫入鎖。代碼如下所示:/*fcntl_write.c測試文件寫入鎖主函數部分*/#include#include#include#include#include#includ
21、eintmain(void)intfd;/*首先打開文件*/fd=open(hello,O_RDWR|O_CREAT,0666);if(fd0)perror(open);exit(1);/*給文件上寫入鎖*/lock_set(fd,F_WRLCK);getchar();/*給文件接鎖*/lock_set(fd,F_UNLCK);getchar();close(fd);exit(0);為了能夠使用多個終端,更好地顯示寫入鎖的作用,本實例主要在PC機上測試,讀者可將其交叉編譯,下載到目標板上運行。下面是在PC機上的運行結果。為了使程序有較大的靈活性,筆者采用文件上鎖后由用戶鍵入一任意鍵使程序繼續運
22、行。建議讀者開啟兩個終端,并且在兩個終端上同時運行該程序,以達到多個進程操作一個文件的效果。在這里,筆者首先運行終端一,請讀者注意終端二中的第一句。終端一:rootlocalhostfile#./fcntl_writewritelocksetby4994releaselockby4994終端二:rootlocalhostfile#./fcntl_writewritelockalreadysetby4994嵌入式Linux應用程序開發詳解第6章、文件IO編程writelocksetby4997releaselockby4997由此可見,寫入鎖為互斥鎖,一個時刻只能有一個寫入鎖存在。接下來的程序是
23、測試文件的讀取鎖,原理同上面的程序一樣。/*fcntl_read.c測試文件讀取鎖主函數部分*/#include#include#include#include#include#includeintmain(void)intfd;fd=open(hello,O_RDWR|O_CREAT,0666);if(fd0)perror(open);exit(1);/*給文件上讀取鎖*/lock_set(fd,F_RDLCK);getchar();/*給文件接鎖*/lock_set(fd,F_UNLCK);getchar();close(fd);exit(0);同樣開啟兩個終端,并首先啟動終端一上的程序,
24、其運行結果如下所示:終端一:rootlocalhostfile#./fcntl2readlocksetby5009releaselockby5009終端二:rootlocalhostfile#./fcntl2readlocksetby5010releaselockby5010讀者可以將此結果與寫入鎖的運行結果相比較,可以看出,讀取鎖為共享鎖,當進程5009已設定讀取鎖后,進程5010還可以設置讀取鎖。思考如果在一個終端上運行設置讀取鎖,則在另一個終端上運行設置寫入鎖,會有什么結果呢?6.3.4selectselect函數說明前面的fcntl函數解決了文件的共享問題,接下來該處理I/O復用的情況
25、了。總的來說,I/O處理的模型有5種。阻塞I/O模型:在這種模型下,若所調用的I/O函數沒有完成相關的功能就會使進程掛起,直到相關數據到才會出錯返回。如常見對管道設備、終端設備和網絡設備進行讀寫時經常會出現這種情況。非阻塞模型:在這種模型下,當請求的I/O操作不能完成時,則不讓進程睡眠,而且返回一個錯誤。非阻塞I/O使用戶可以調用不會永遠阻塞的I/O操作,如open、write和read。如果該操作不能完成,則會立即出錯返回,且表示該I/O如果該操作繼續執行就會阻塞。I/O多路轉接模型:在這種模型下,如果請求的I/O操作阻塞,且它不是真正阻塞I/O,而是讓其中的一個函數等待,在這期間,I/O還
26、能進行其他操作。如本節要介紹的select函數和poll函數,就是屬于這種模型。信號驅動I/O模型:在這種模型下,通過安裝一個信號處理程序,系統可以自動捕獲特定信號的到來,從而啟動I/O。這是由內核通知用戶何時可以啟動一個I/O操作決定的。異步I/O模型:在這種模型下,當一個描述符已準備好,可以啟動I/O時,進程會通知內核。現在,并不是所有的系統都支持這種模型。可以看到,select的I/O多路轉接模型是處理I/O復用的一個高效的方法。它可以具體設置每一個所關心的文件描述符的條件、希望等待的時間等,從select函數返回時,內核會通知用戶已準備好的文件描述符的數量、已準備好的條件等。通過使用s
27、elect返回值,就可以調用相應的I/O處理函數了。select函數格式Select函數的語法格式如表6.8所示。表6.8fcntl函數語法要點所需頭文件#include#include嵌入式Linux應用程序開發詳解第6章、文件IO編程#include函數原型intselect(intnumfds,fd_set*readfds,fd_set*writefds,fd_set*exeptfds,structtimeval*timeout)numfds:需要檢查的號碼最高的文件描述符加1readfds:由select()監視的讀文件描述符集合writefds:由select()監視的寫文件描述符集
28、合exeptfds:由select()監視的異常處理文件描述符集合NULL:永遠等待,直到捕捉到信號或文件描述符已準備好為止具體值:structtimeval類型的指針,若等待為timeout時間還沒有文件描符準備好,就立即返回函數傳入值timeout0:從不等待,測試所有指定的描述符并立即返回函數返回值成功:準備好的文件描述符1:出錯思考請讀者考慮一下如何確定最高的文件描述符?可以看到,select函數根據希望進行的文件操作對文件描述符進行了分類處理,這里,對文件描述符的處理主要涉及到4個宏函數,如表6.9所示。表6.9select文件描述符處理函數FD_ZERO(fd_set*set)清除
29、一個文件描述符集FD_SET(intfd,fd_set*set)將一個文件描述符加入文件描述符集中FD_CLR(intfd,fd_set*set)將一個文件描述符從文件描述符集中清除FD_ISSET(intfd,fd_set*set)測試該集中的一個給定位是否有變化一般來說,在使用select函數之前,首先使用FD_ZERO和FD_SET來初始化文件描述符集,在使用了select函數時,可循環使用FD_ISSET測試描述符集,在執行完對相關后文件描述符后,使用FD_CLR來清楚描述符集。另外,select函數中的timeout是一個structtimeval類型的指針,該結構體如下所示:str
30、ucttimevallongtv_sec;/*second*/longtv_unsec;/*andmicroseconds*/可以看到,這個時間結構體的精確度可以設置到微秒級,這對于大多數的應用而言已經足夠了。使用實例由于Select函數多用于I/O操作可能會阻塞的情況下,而對于可能會有阻塞I/O的管道、網絡編程,本書到現在為止還沒有涉及。因此,本例主要表現了如何使用select函數,而其中的I/O操作是不會阻塞的。本實例中主要實現將文件hello1里的內容讀出,并將此內容每隔10s寫入hello2中去。在這里建立了兩個描述符集,其中一個描述符集inset1是用于讀取文件內容,另一個描述符集i
31、nset2是用于寫入文件的。兩個文件描述符fdsO和fds1分別指向這一文件描述符。在首先初始化完各文件描述符集之后,就開始了循環測試這兩個文件描述符是否可讀寫,由于在這里沒有阻塞,所以文件描述符處于準備就緒的狀態。這時,就分別對文件描述符fds0和fsd1進行讀寫操作。該程序的流程圖如圖6.2所示。/*select.c*/#include#include#include#include#includeintmain(void)intfds2;charbuf7;inti,rc,maxfd;fd_setinset1,inset2;structtimevaltv;/*首先按一定的權限打開hello1文件*/if(fds0=
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 電商內容營銷策略升級:2025年種草經濟下的品牌形象塑造報告
- 環保產業園區的產業集聚與區域綠色旅游協同發展報告001
- 2025年醫院信息化建設:電子病歷系統智能藥物市場機遇優化報告
- 2025年醫院電子病歷系統優化與醫療信息化投資分析報告
- 2025年醫院電子病歷系統優化構建醫療信息化協同發展報告
- 2025年金融科技安全報告:網絡安全與數據保護的關鍵措施001
- 2025年互聯網廣告精準投放算法效果評測與廣告主滿意度調查報告
- 2025年醫藥流通行業供應鏈整合與成本控制戰略規劃與優化策略實施案例分析報告解讀
- 周瑜人物介紹
- 建筑信息模型(BIM)在全過程建筑工程抗震加固中的應用報告2025
- 【人教版】河北石家莊2024-2025學年 四年級下學期期末數學試題【一】有解析
- 施工費用控制管理制度
- 律師事務所數據管理制度
- 《資治通鑒》與為將之道知到課后答案智慧樹章節測試答案2025年春武警指揮學院
- 朗讀技巧之重音、停連、語速、語調、語氣、節奏要領方法指導
- 2023-浙江信息技術-學考總復習-知識點總結
- 2022-2023學年安徽省合肥市七年級下冊期末語文模擬試卷(含答案)
- 2022年《國民經濟行業分類》
- 集中控制中心建設(指揮中心建設)
- 施工導流圍堰工程實例講義課件(117頁配圖豐富)
- 清溪1井溢流事件壓封井搶險分析
評論
0/150
提交評論