linuxC編程之常用文件I/O操作-創(chuàng)新互聯(lián)


今天我們總結(jié)一下,linux中常用文件I/O操作。

目前創(chuàng)新互聯(lián)已為上1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、網(wǎng)站托管、服務(wù)器租用、企業(yè)網(wǎng)站設(shè)計、南部網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

     首先讓我們看一下,什么是文件I/O:


        所謂文件I/O就是:對于I/O就是input/output,輸入/輸出。文件IO的意思就是讀寫文件。

1、linux給我們留的常用文件I/O接口。


    1、open close write read lseek


2、文件操作的一般步驟:

    1、在linux中要操作一個文件,一般是先open打開一個文件,得到文件描述符,然后對文件進行讀寫操作(或其他操作),最后是close關(guān)閉文件即可。

    2、強調(diào)一點:我們對文件進行操作時,一定要先打開文件,打開成功之后才能操作,如果打開失敗,就不用進行后邊的操作了,最后讀寫完成后,一定要關(guān)閉文件,否則會造成文件損壞。


    3、文件平時是存放在塊設(shè)備中的文件系統(tǒng)文件中的,我們把這種文件叫靜態(tài)文件,當我們?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)文件)。


    4、打開文件以后,以后對這個文件的讀寫操作,都是針對內(nèi)存中的這一份動態(tài)文件的,而并不是針對靜態(tài)文件的。當然我們對動態(tài)文件進行讀寫以后,此時內(nèi)存中動態(tài)文件和塊設(shè)備文件中的靜態(tài)文件就不同步了,當我們close關(guān)閉動態(tài)文件時,close內(nèi)部內(nèi)核將內(nèi)存中的動態(tài)文件的內(nèi)容去更新(同步)塊設(shè)備中的靜態(tài)文件。

  5、為什么這么設(shè)計,不直接對塊設(shè)備直接操作。


   塊設(shè)備本身讀寫非常不靈活,是按塊讀寫的,而內(nèi)存是按字節(jié)單位操作的,而且可以隨機操作,很靈活。

3、重要概念:

    文件描述符:

   1、對于內(nèi)核而言,所有打開文件都由文件描述符引用。文件描述符是一個非負整數(shù)。當打開一個現(xiàn)存文件或者創(chuàng)建一個新文件時,內(nèi)核向進程返回一個文件描述符。當讀寫一個文件時,用open和creat返回的文件描述符標識該文件,將其作為參數(shù)傳遞給read和write。

按照慣例,UNIX shell使用文件描述符0與進程的標準輸入相結(jié)合,文件描述符1與標準輸出相結(jié)合,文件描述符2與標準錯誤輸出相結(jié)合。STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO這幾個宏代替了0、1、2這幾個魔數(shù)。

  2、文件描述符,這個數(shù)字在一個進程中表示一個特定含義,當我們open一個文件時,操作系統(tǒng)在內(nèi)存中構(gòu)建了一些數(shù)據(jù)結(jié)構(gòu)來表示這個動態(tài)文件,然后返回給應(yīng)用程序一個數(shù)字作為文件描述符,這個數(shù)字就和我們內(nèi)存中維護的這個動態(tài)文件的這些數(shù)據(jù)結(jié)構(gòu)綁定上了,以后我們應(yīng)用程序如果要操作這個動態(tài)文件,只需要用這個文件描述符區(qū)分。


  3、文件描述符的作用域就是當前進程,出了這個進程文件描述符就沒有意義了。


open函數(shù)打開文件,打開成功返回一個文件描述符,打開失敗,返回-1。

補充:這里我們補充一點,

        1、學習linux過程中注意學會使用man手冊,查詢幫助文檔。

        2、man 1 xx查linux shell命令,man 2 xxx查API, man 3 xxx查庫函數(shù)

4、常用文件I/O操作的使用:


  1、open函數(shù)(打開文件操作)


需要用到的頭文件
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
函數(shù)原型:
       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);
                                           返回值:若成功返回文件描述符,若出錯返回 -1

  對于open函數(shù)而言,僅當創(chuàng)建新文件時才使用第三個參數(shù)。namepath是要打開或創(chuàng)建的文件的名字。oflag參數(shù)可以用來說明函數(shù)的多個選項。用下列一個或者多個常數(shù)進行或運算構(gòu)成oflag參數(shù)(這些參數(shù)定義在<fcntl.h>頭文件中):


open函數(shù)flags參數(shù)詳解:

    讀寫權(quán)限:O_RDONLY O_WRONLY O_RDWR

        O_RDONLY 只讀打開

        O_WRONLY 只寫打開

        O_RDWR  可讀可寫打開

    當我們附帶了權(quán)限后,打開的文件就只能按照這種權(quán)限來操作。以上這三個常數(shù)中應(yīng)當只指定一 個。下列常數(shù)是可選擇的:

        O_CREAT 若文件不存在則創(chuàng)建它。使用此選項時,需要同時說明第三個參數(shù)mode,用其說明該新文件的存取許可權(quán)限。

        O_EXCL 如果同時指定了OCREAT,而文件已經(jīng)存在,則出錯。這可測試一個文件是

否存在,如果不存在則創(chuàng)建此文件成為一個原子操作。3 . 11節(jié)將較詳細地說明原子操作。

        O_APPEND 每次寫時都加到文件的尾端。

        O_TRUNC 屬性去打開文件時,如果這個文件中本來是有內(nèi)容的,而且為只讀或只寫成功打開,則將其長度截短為0。


重點:


  一: 打開存在并有內(nèi)容的文件時:O_APPEND、O_TRUNC

    (1)思考一個問題:當我們打開一個已經(jīng)存在并且內(nèi)部有內(nèi)容的文件時會怎么樣?

    可能結(jié)果1:新內(nèi)容會替代原來的內(nèi)容(原來的內(nèi)容就不見了,丟了)

    可能結(jié)果2:新內(nèi)容添加在前面,原來的內(nèi)容繼續(xù)在后面

    可能結(jié)果3:新內(nèi)容附加在后面,原來的內(nèi)容還在前面

    可能結(jié)果4:不讀不寫的時候,原來的文件中的內(nèi)容保持不變

  (2)O_TRUNC屬性去打開文件時,如果這個文件中本來是有內(nèi)容的,則原來的內(nèi)容會被丟棄。這就對應(yīng)上面的結(jié)果1

    (3)O_APPEND屬性去打開文件時,如果這個文件中本來是有內(nèi)容的,則新寫入的內(nèi)容會接續(xù)到原來內(nèi)容的后面,對應(yīng)結(jié)果3

    (4)默認不使用O_APPEND和O_TRUNC屬性時就是結(jié)果4

    (5)如果O_APPEND和O_TRUNC同時出現(xiàn)會會清空文件。

   二:打開不存在的文件時:O_CREAT、O_EXCL

    (1)思考:當我們?nèi)ゴ蜷_一個并不存在的文件時會怎樣?當我們open打開一個文件時如果這個文件名不存在則會打開文件錯誤。

    (2)vi或者windows下的notepad++,都可以直接打開一個尚未存在的文件。

    (3)open的flag O_CREAT就是為了應(yīng)對這種打開一個并不存在的文件的。O_CREAT就表示我們當前打開的文件并不存在,我們是要去創(chuàng)建并且打開它。

    (4)思考:當我們open使用了O_CREAT,但是文件已經(jīng)存在的情況下會怎樣?經(jīng)過實驗驗證發(fā)現(xiàn)結(jié)果是報錯。

    (5)結(jié)論:open中加入O_CREAT后,不管原來這個文件存在與否都能打開成功,如果原來這個文件不存在則創(chuàng)建一個空的新文件,如果原來這個文件存在則會重新創(chuàng)建這個文件,原來的內(nèi)容會被消除掉(有點類似于先刪除原來的文件再創(chuàng)建一個新的)

    (6)這樣可能帶來一個問題?我們本來是想去創(chuàng)建一個新文件的,但是把文件名搞錯了弄成了一個老文件名,結(jié)果老文件就被意外修改了。我們希望的效果是:如果我CREAT要創(chuàng)建的是一個已經(jīng)存在的名字的文件,則給我報錯,不要去創(chuàng)建。

    (7)這個效果就要靠O_EXCL標志和O_CREAT標志來結(jié)合使用。當這連個標志一起的時候,則沒有文件時創(chuàng)建文件,有這個文件時會報錯提醒我們。

    (8)open函數(shù)在使用O_CREAT標志去創(chuàng)建文件時,可以使用第三個參數(shù)mode來指定要創(chuàng)建的文件的權(quán)限。mode使用4個數(shù)字來指定權(quán)限的,其中后面三個很重要,對應(yīng)我們要創(chuàng)建的這個文件的權(quán)限標志。譬如一般創(chuàng)建一個可讀可寫不可執(zhí)行的文件就用0666


        O_NOCTTY 如果pathname指的是終端設(shè)備,則不將此設(shè)備分配作為此進程的控制終端。9.6節(jié)將說明控制終端。

        O_NONBLOCK 如果pathname指的是一個FIFO、一個塊特殊文件或一個字符特殊文件,則此選擇項為此文件的本次打開操作和后續(xù)的I/O操作設(shè)置非阻塞方式。(只用于設(shè)備文件,而不用于普通文件。)

    (1)阻塞與非阻塞。如果一個函數(shù)是阻塞式的,則我們調(diào)用這個函數(shù)時當前進程有可能被卡住(阻塞住,實質(zhì)是這個函數(shù)內(nèi)部要完成的事情條件不具備,當前沒法做,要等待條件成熟),函數(shù)被阻塞住了就不能立刻返回;如果一個函數(shù)是非阻塞式的那么我們調(diào)用這個函數(shù)后一定會立即返回,但是函數(shù)有沒有完成任務(wù)不一定。


    (2)阻塞和非阻塞是兩種不同的設(shè)計思路,并沒有好壞??偟膩碚f,阻塞式的結(jié)果有保障但是時間沒保障;非阻塞式的時間有保障但是結(jié)果沒保障。

    (3)操作系統(tǒng)提供的API和由API封裝而成的庫函數(shù),有很多本身就是被設(shè)計為阻塞式或者非阻塞式的,所以我們應(yīng)用程度調(diào)用這些函數(shù)的時候心里得非常清楚。

    (4)我們打開一個文件默認就是阻塞式的,如果你希望以非阻塞的方式打開文件,則flag中要加O_NONBLOCK標志。

  O_SYNC 使每次write都等到物理I/O操作完成

    (1)write阻塞等待底層完成寫入才返回到應(yīng)用層。

    (2)無O_SYNC時write只是將內(nèi)容寫入底層緩沖區(qū)即可返回,然后底層(操作系統(tǒng)中負責實現(xiàn)open、write這些操作的那些代碼,也包含OS中讀寫硬盤等底層硬件的代碼)在合適的時候會將buf中的內(nèi)容一次性的同步到硬盤中。這種設(shè)計是為了提升硬件操作的性能和銷量,提升硬件壽命;但是有時候我們希望硬件不好等待,直接將我們的內(nèi)容寫入硬盤中,這時候就可以用O_SYNC標志。


  2、creat函數(shù)(也可用creat函數(shù)創(chuàng)建一個新文件)

需要用到的頭文件
#include<sys/types.h>
#include<sys/stat.h>
#include<fcutl.h>
 函數(shù)原型:
 int creat(const char *pathname, mode_t mode);
                                         返回:若成功為只寫打開的文件描述符,若出錯為-1

  此函數(shù)等效于 open(pathname,O_WRONLY|O_CRAT|O_TRUNC,mode);



    3、read 函數(shù)(用read函數(shù)從打開的文件中讀取數(shù)據(jù))

需要的頭文件:
#include<unistd.h>
函數(shù)原型:
ssize_t read(int filedes,void *buffer,size_t nbytes);
返回值:讀取到字節(jié)數(shù),若已到文件尾0,則返回-1如果read成功,則返回讀取到字節(jié)數(shù)。如已到文件結(jié)尾返回0;

有多種情況可使實際讀到的字節(jié)數(shù)少于要求讀字節(jié)數(shù):

1、讀取普通文件時,在讀到要求字節(jié)數(shù)之前已經(jīng)到達了文件結(jié)尾。例如,若在到達文件尾端之前還有30個字節(jié),而要求讀100個字節(jié),則read返回30,下一次調(diào)用read時,它將返回0(文件尾端)。

2、當從終端設(shè)備讀時,通常一次最多讀一行

3、當從網(wǎng)絡(luò)讀時,網(wǎng)絡(luò)中緩存機構(gòu)可能造成返回值小于所要求讀的字節(jié)數(shù)。

4、某些面向記錄的設(shè)備,例如磁帶,一次最多返回一個記錄。



    4、write函數(shù)(用write函數(shù)向打開的文件寫數(shù)據(jù))

需要用到的頭文件
#include<unistd.h>
函數(shù)原型:
ssize_t write(int filedes,const void buffer,size_t nbytes);
                                            返回值:若成功返回已寫字節(jié)數(shù),若出錯返回-1
其返回值通常與參數(shù)nbyte的值不同,否則表示出錯。write出錯的一個常見原因是:磁盤已寫滿,或者超過了對一個給定進程的文件長度限制。

寫入用write系統(tǒng)調(diào)用,write的原型和理解方法和read相似


    5、close函數(shù)(可以用close函數(shù)關(guān)閉一個打開是文件)

需要用到的頭文件:
#include<unistd.h>
函數(shù)原型:
int close(int filedes);
                                                        返回值:成功返回0,若出錯返回-1

當一個進程終止時,它所有的打開的文件都是由內(nèi)核自動關(guān)閉。


    6、lseek函數(shù)


每個打開文件都有一個與其相關(guān)聯(lián)的“當前文件位移量”。它是一個非負整數(shù),用以度量從文件開始處計算的字節(jié)數(shù)。

需要用到的頭文件
#include<sys/types.h>
#include<unistd.h>
函數(shù)原型:
off_t lseek(int filedes,off_t offset,int whence);
                                            返回值:若成功為新的文件的位移,若出錯位-1

    對參數(shù)offset 的解釋與參數(shù)whence的值有關(guān)。

    若whence是SEEK_SET,則將該文件的位移量設(shè)置為距文件開始處offset 個字節(jié)。

    若whence是SEEK_CUR,則將該文件的位移量設(shè)置為其當前值加offset, offset可為正或負。

    若whence是SEEK_END,則將該文件的位移量設(shè)置為文件長度加offset, offset可為正或負。*******************************************************************************************

重要概念:

    (1)文件指針:當我們要對一個文件進行讀寫時,一定需要先打開這個文件,所以我們讀寫的所有文件都是動態(tài)文件。動態(tài)文件在內(nèi)存中的形態(tài)就是文件流的形式。

    (2)文件流很長,里面有很多個字節(jié)。那我們當前正在操作的是哪個位置?GUI模式下的軟件用光標來標識這個當前正在操作的位置,這是給人看的。

    (3)在動態(tài)文件中,我們會通過文件指針來表征這個正在操作的位置。所謂文件指針,就是我們文件管理表這個結(jié)構(gòu)體里面的一個指針。所以文件指針其實是vnode中的一個元素。這個指針表示當前我們正在操作文件流的哪個位置。這個指針不能被直接訪問,linux系統(tǒng)用lseek函數(shù)來訪問這個文件指針。

    (4)當我們打開一個空文件時,默認情況下文件指針指向文件流的開始。所以這時候去write時寫入就是從文件開頭開始的。write和read函數(shù)本身自帶移動文件指針的功能,所以當我write了n個字節(jié)后,文件指針會自動向后移動n位。如果需要人為的隨意更改文件指針,那就只能通過lseek函數(shù)了

    (5)read和write函數(shù)都是從當前文件指針處開始操作的,所以當我們用lseek顯式的將文件指針移動后,那么再去read/write時就是從移動過后的位置開始的。

    (6)回顧前面一節(jié)中我們從空文件,先write寫了12字節(jié),然后read時是空的(但是此時我們打開文件后發(fā)現(xiàn)12字節(jié)確實寫進來了)。

lseek函數(shù)幾個用途:

    1、用lseek計算文件長度

(1)linux中并沒有一個函數(shù)可以直接返回一個文件的長度。但是我們做項目時經(jīng)常會需要知道一個文件的長度,怎么辦?自己利用lseek來寫一個函數(shù)得到文件長度即可。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
typedef int file_t;

#define MAXLENG 1024

int main(int argc,char *argv[])
{
	file_t fd = -1;
	ssize_t ret = -1;
	if(2 != argc)
	{
		fprintf(stdout,"usage: %s filename \n",argv[0]);
		_exit(-1);
	}	

	char buffer[MAXLENG] = {0};

	fd = open(argv[1],O_RDONLY);
	
	//文件打開成功,文件指針指向文件開頭
	if(-1 == fd)
 	{
		perror("open file error:");
		_exit(-1);
	}
	else
	{
		fprintf(stdout,"文件打開成功\n");
		ret = lseek(fd,0,SEEK_END);

	}
	
	
	
	fprintf(stdout,"文件長度是: %d\n",ret);

	return 0;
}

     2、用lseek構(gòu)建空洞文件

(1)空洞文件就是這個文件中有一段是空的。

(2)普通文件中間是不能有空的,因為我們write時文件指針是依次從前到后去移動的,不可能繞過前面直接到后面。

(3)我們打開一個文件后,用lseek往后跳過一段,再write寫入一段,就會構(gòu)成一個空洞文件。

(4)空洞文件方法對多線程共同操作文件是及其有用的。有時候我們創(chuàng)建一個很大的文件,如果從頭開始依次構(gòu)建時間很長。有一種思路就是將文件分為多段,然后多線程來操作每個線程負責其中一段的寫入。



補充:


  1、exit、_exit、_Exit退出進程

        (1)當我們程序在前面步驟操作失敗導(dǎo)致后面的操作都沒有可能進行下去時,應(yīng)該在前面的錯誤監(jiān)測中結(jié)束整個程序,不應(yīng)該繼續(xù)讓程序運行下去了。

        (2)我們?nèi)绾瓮顺龀绦颍?/p>

        第一種;在main用return,一般原則是程序正常終止return 0,如果程序異常終止則return -1。

        第一種:正式終止進程(程序)應(yīng)該使用exit或者_exit或者_Exit之一。

 2、文件讀寫的一些細節(jié)

  <1> 、errno和perror

(1)errno就是error number,意思就是錯誤號碼。linux系統(tǒng)中對各種常見錯誤做了個編號,當函數(shù)執(zhí)行錯誤時,函數(shù)會返回一個特定的errno編號來告訴我們這個函數(shù)到底哪里錯了。

(2)errno是由OS來維護的一個全局變量,任何OS內(nèi)部函數(shù)都可以通過設(shè)置errno來告訴上層調(diào)用者究竟剛才發(fā)生了一個什么錯誤。

(3)errno本身實質(zhì)是一個int類型的數(shù)字,每個數(shù)字編號對應(yīng)一種錯誤。當我們只看errno時只能得到一個錯誤編號數(shù)字(譬如-37),不適應(yīng)于人看。

(4)linux系統(tǒng)提供了一個函數(shù)perror(意思print error),perror函數(shù)內(nèi)部會讀取errno并且將這個不好認的數(shù)字直接給轉(zhuǎn)成對應(yīng)的錯誤信息字符串,然后print打印出來。

    <2>、read和write的count

(1)count和返回值的關(guān)系。count參數(shù)表示我們想要寫或者讀的字節(jié)數(shù),返回值表示實際完成的要寫或者讀的字節(jié)數(shù)。實現(xiàn)的有可能等于想要讀寫的,也有可能小于(說明沒完成任務(wù))

(2)count再和阻塞非阻塞結(jié)合起來,就會更加復(fù)雜。如果一個函數(shù)是阻塞式的,則我們要讀取30個,結(jié)果暫時只有20個時就會被阻塞住,等待剩余的10個可以讀。

(3)有時候我們寫正式程序時,我們要讀取或者寫入的是一個很龐大的文件(譬如文件有2MB),我們不可能把count設(shè)置為2*1024*1024,而應(yīng)該去把count設(shè)置為一個合適的數(shù)字(譬如2048、4096),然后通過多次讀取來實現(xiàn)全部讀完。

    <3>、文件IO效率和標準IO

(1)文件IO就指的是我們當前在講的open、close、write、read等API函數(shù)構(gòu)成的一套用來讀寫文件的體系,這套體系可以很好的完成文件讀寫,但是效率并不是最高的。

(2)應(yīng)用層C語言庫函數(shù)提供了一些用來做文件讀寫的函數(shù)列表,叫標準IO。標準IO由一系列的C庫函數(shù)構(gòu)成(fopen、fclose、fwrite、fread),這些標準IO函數(shù)其實是由文件IO封裝而來的(fopen內(nèi)部其實調(diào)用的還是open,fwrite內(nèi)部還是通過write來完成文件寫入的)。標準IO加了封裝之后主要是為了在應(yīng)用層添加一個緩沖機制,這樣我們通過fwrite寫入的內(nèi)容不是直接進入內(nèi)核中的buf,而是先進入應(yīng)用層標準IO庫自己維護的buf中,然后標準IO庫自己根據(jù)操作系統(tǒng)單次write的最佳count來選擇好的時機來完成write到內(nèi)核中的buf(內(nèi)核中的buf再根據(jù)硬盤的特性來選擇好的實際去最終寫入硬盤中)。

  3、linux系統(tǒng)如何管理文件

       <1>、硬盤中的靜態(tài)文件和inode(i節(jié)點)

        (1)文件平時都在存放在硬盤中的,硬盤中存儲的文件以一種固定的形式存放的,我們叫靜 態(tài)文件。

    (2)一塊硬盤中可以分為兩大區(qū)域:一個是硬盤內(nèi)容管理表項,另一個是真正存儲內(nèi)容的區(qū)域。操作系統(tǒng)訪問硬盤時是先去讀取硬盤內(nèi)容管理表,從中找到我們要訪問的那個文件的扇區(qū)級別的信息,然后再用這個信息去查詢真正存儲內(nèi)容的區(qū)域,最后得到我們要的文件。

    (3)操作系統(tǒng)最初拿到的信息是文件名,最終得到的是文件內(nèi)容。第一步就是去查詢硬盤內(nèi)容管理表,這個管理表中以文件為單位記錄了各個文件的各種信息,每一個文件有一個信息列表(我們叫inode,i節(jié)點,其實質(zhì)是一個結(jié)構(gòu)體,這個結(jié)構(gòu)體有很多元素,每個元素記錄了這個文件的一些信息,其中就包括文件名、文件在硬盤上對應(yīng)的扇區(qū)號、塊號那些東西·····)

強調(diào):硬盤管理的時候是以文件為單位的,每個文件一個inode,每個inode有一個數(shù)字編號,對應(yīng)一個結(jié)構(gòu)體,結(jié)構(gòu)體中記錄了各種信息。

    (4)聯(lián)系平時實踐,大家格式化硬盤(U盤)時發(fā)現(xiàn)有:快速格式化和底層格式化??焖俑袷交浅?欤袷交粋€32GB的U盤只要1秒鐘,普通格式化格式化速度慢。這兩個的差異?其實快速格式化就是只刪除了U盤中的硬盤內(nèi)容管理表(其實就是inode),真正存儲的內(nèi)容沒有動。這種格式化的內(nèi)容是有可能被找回的。

   <2>、內(nèi)存中被打開的文件和vnode(v節(jié)點)

        (1)一個程序的運行就是一個進程,我們在程序中打開的文件就屬于某個進程。每個進程都有一個數(shù)據(jù)結(jié)構(gòu)用來記錄這個進程的所有信息(叫進程信息表),表中有一個指針會指向一個文件管理表,文件管理表中記錄了當前進程打開的所有文件及其相關(guān)信息。文件管理表中用來索引各個打開的文件的index就是文件描述符fd,我們最終找到的就是一個已經(jīng)被打開的文件的管理結(jié)構(gòu)體vnode

        (2)一個vnode中就記錄了一個被打開的文件的各種信息,而且我們只要知道這個文件的fd,就可以很容易的找到這個文件的vnode進而對這個文件進行各種操作。

   <3>、文件與流的概念

        (1)流(stream)對應(yīng)自然界的水流。文件操作中,文件類似是一個大包裹,里面裝了一堆字符,但是文件被讀出/寫入時都只能一個字符一個字符的進行,而不能一股腦兒的讀寫,那么一個文件中N多的個字符被挨個一次讀出/寫入時,這些字符就構(gòu)成了一個字符流。

        (2)流這個概念是動態(tài)的,不是靜態(tài)的。

        (3)編程中提到流這個概念,一般都是IO相關(guān)的。所以經(jīng)常叫IO流。文件操作時就構(gòu)成了一個IO流。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

網(wǎng)頁題目:linuxC編程之常用文件I/O操作-創(chuàng)新互聯(lián)
本文URL:http://muchs.cn/article26/ddddjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、電子商務(wù)、ChatGPT、關(guān)鍵詞優(yōu)化、品牌網(wǎng)站建設(shè)、全網(wǎng)營銷推廣

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)