Linux 系统应用编程——文件I/O
?Linux操作系統(tǒng)是基于文件概念的。文件是以字符序列構(gòu)成的信息載體。根據(jù)這一點(diǎn),可以把I/O設(shè)備當(dāng)做文件來處理,因此,在磁盤上的普通文件進(jìn)行交互所用的統(tǒng)一系統(tǒng)調(diào)用可以直接用于I/O設(shè)備。這樣大大簡化了系統(tǒng)對于不同設(shè)備的處理,提高了效率。Linux中的文件主要分為6種:普通文件、目錄文件、符號鏈接文件、管道文件、套接字文件和設(shè)備文件。
?????? 那么,內(nèi)核如何區(qū)分和引用特定的文件呢?這里用到了一個(gè)重要的概念——文件描述符。對于Linux而言,所有的設(shè)備和文件的操作都是通過文件描述符來進(jìn)行的。文件描述符是一個(gè)非負(fù)的整數(shù),它是一個(gè)索引值,并指向在內(nèi)核中每個(gè)進(jìn)程打開文件的記錄表。當(dāng)打開一個(gè)現(xiàn)存文件或創(chuàng)建一個(gè)新文件時(shí),內(nèi)核就向進(jìn)程返回一個(gè)文件描述符;讀寫文件時(shí),需要把文件描述符作為參數(shù)傳遞給相應(yīng)的函數(shù)。
?????? 通常,一個(gè)進(jìn)程啟動(dòng)時(shí),都會打開3個(gè)流:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤。這3個(gè)流分別對應(yīng)文件描述符0、1? 和 2(對應(yīng)的宏分別是STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO)。
????? 基于文件描述符的I/O操作雖然不鞥直接移植到類Linux以外的系統(tǒng)上去(如Windows),但它往往是實(shí)現(xiàn)某些I/O操作的唯一途徑,如Linux中底層文件操作函數(shù)、多路I/O、TCP/IP套接字編程接口等。同時(shí),他們也很好地兼容POSIX標(biāo)準(zhǔn),因此,可以很方便地移植到任何POSIX平臺上。基于文件描述符的I/O操作是Linux中最常用的操作之一。
????? 文件I/O相關(guān)函數(shù):open() 、read() 、write() 、lseek() 和close() 。這些函數(shù)的特點(diǎn)是不帶緩沖,直接對文件(包括設(shè)備)進(jìn)行讀寫操作。這些函數(shù)不是ANSI C的組成部分,而是POSIX相關(guān)標(biāo)準(zhǔn)來定義。
1、文件打開與和關(guān)閉
???????open()函數(shù)用于創(chuàng)建或打開文件,在打開或創(chuàng)建文件時(shí)可以指定文件打開方式及文件的訪問權(quán)限。
??????? 函數(shù)原型如下:
[cpp]?view plaincopy1)pathname: 被打開的文件名(可包括路徑名)
2)flags(文件打開方式,這里介紹幾個(gè)常用的)
O_RDONLY???只讀
O_WRONLY??只寫
O_RDWR?????? 可讀可寫
這三者必有其一
O_CREAT??? 如果文件不存在,就創(chuàng)建一個(gè)新文件,并用第三個(gè)參數(shù)為其設(shè)置權(quán)限;
O_TRUNC????若文件已經(jīng)存在,那么會刪除文件中的全部原有數(shù)據(jù),并且設(shè)置文件大小為0;
O_APPEND? 以添加方式打開文件,在寫文件時(shí),文件讀寫文職自動(dòng)指向文件的末尾,即將寫入的數(shù)據(jù)添加到文件的末尾;
3)perms 新建文件的存取權(quán)限
????? close()函數(shù)用于關(guān)閉一個(gè)被打開的文件。當(dāng)一個(gè)進(jìn)程終止時(shí),所有打開的文件都有內(nèi)核自動(dòng)關(guān)閉。很多程序都利用這一特性而不顯示地關(guān)閉一個(gè)文件。
函數(shù)原型:
[cpp]?view plaincopy?
2、文件讀寫
???????read()函數(shù)從文件中讀取數(shù)據(jù)存放到緩沖區(qū)中,并返回實(shí)際讀取的字節(jié)數(shù)。若返回0,則表示沒有數(shù)據(jù)可讀,即已達(dá)到文件尾。讀操作從文件的當(dāng)前讀寫位置開始讀取數(shù)據(jù),當(dāng)前讀寫位置自動(dòng)往后移動(dòng)。
函數(shù)原型:
[cpp]?view plaincopy函數(shù)傳入值:
fd? 文件描述符;
buf 指定存儲器讀取數(shù)據(jù)的緩沖區(qū);
count? 指定讀出的字節(jié)數(shù);
函數(shù)返回值:
成功:讀到的字節(jié)數(shù);
0:已到達(dá)文件尾;
-1:出錯(cuò);
在讀到普通文件時(shí),若讀到要求的字節(jié)數(shù)之前已到達(dá)問價(jià)你的尾部,則返回的字節(jié)數(shù)會小于指定讀出的字節(jié)數(shù);
????????write()函數(shù)將數(shù)據(jù)寫入文件中,并返回實(shí)際寫入的字節(jié)數(shù)。寫操作從文件的當(dāng)前讀寫位置開始寫入。對磁盤文件進(jìn)行寫操作時(shí),若磁盤已滿,write()函數(shù)返回失敗;
函數(shù)原型:
[cpp]?view plaincopy函數(shù)傳入值:
fd? 文件描述符
buf? 指定存儲器寫入數(shù)據(jù)的緩沖區(qū)
count? 指定讀出的字節(jié)數(shù)
函數(shù)返回值:
成功:已寫的字節(jié)數(shù)
-1:出錯(cuò)
下面寫個(gè)簡單小程序,實(shí)現(xiàn)copy程序,完成文件的復(fù)制,代碼如下:
[cpp]?view plaincopy執(zhí)行結(jié)果如下:
[cpp]?view plaincopy我們可以看到,原來file2.c并不存在,執(zhí)行完程序后,file2.c存在,且大小和file1.c相同;
?
3、文件定位
?????? lseek()函數(shù)對文件當(dāng)前讀寫位置進(jìn)行定位。它只能對可定位(可隨機(jī)訪問)文件操作。管道、套接字和大部分字符設(shè)備文件不支持此類操作;
函數(shù)原型:
[cpp]?view plaincopy函數(shù)傳入值:
fd? 文件描述符
offset?? 相對于基準(zhǔn)點(diǎn)whence 的偏移量。以字節(jié)為單位,正數(shù)表示向前移動(dòng),負(fù)數(shù)表示向后移動(dòng)
whence 當(dāng)前位置的基點(diǎn)
SEEK_SET:文件的起始位置
SEEK_CUR:文件當(dāng)前讀寫位置
SEEK_END:文件的結(jié)束位置
函數(shù)的返回值:
成功:文件當(dāng)前讀寫位置
-1:出錯(cuò)
? ??? 我們可以通過lseek函數(shù)實(shí)現(xiàn)一個(gè)小功能:查看文件的大小,代碼如下:
[cpp]?view plaincopy執(zhí)行結(jié)果如下:
[cpp]?view plaincopy我們可以看到,得到了lseek.c正確大小!
總結(jié)
以上是生活随笔為你收集整理的Linux 系统应用编程——文件I/O的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 串口485接法图_RS485接线的正确原
- 下一篇: 2021五一建模a题完整论文