嵌入式之文件I/O(一)

姓名:鄭煜爍 學號:19029100010 學院:電子工程學院

轉(zhuǎn)自:https://blog.csdn.net/nan_lei/article/details/81460798

【嵌牛導讀】簡單介紹linux系統(tǒng)中的標準I/O

【嵌牛鼻子】標準I/O

【嵌牛提問】標準I/O和文件I/O的區(qū)別

【嵌牛正文】

一谷朝、文件與文件類型

1堕扶、文件定義

? ? 定義:文件(File)是一個具有符號名字的一組相關(guān)聯(lián)元素的有序序列弓熏。文件可以包含的內(nèi)容十分廣泛,操作系統(tǒng)和用戶都可以將具有一定獨立功能的一個程序模塊杯道、一組數(shù)據(jù)或一組文字命名為一個文件。

? ? 文件名:這個數(shù)據(jù)有序序列集合(文件)的名稱揣非。

2叛氨、文件的分類

? ? 文件由許多種,運行的方式也各有不同擂橘。在Windows中晌区,我們是通過文件的后綴名來對文件分類的。例如.txt通贞、.doc朗若、.exe等。而在Linux系統(tǒng)中則不是昌罩,它不以文件后綴來區(qū)分文件的類型哭懈。

在Linux中,我們可以使用ls -l指令來查看文件的類型茎用。在Linux系統(tǒng)中遣总,文件主要有7種類型睬罗。

? ? -? ? 普通文件? ? 指ASCII文本文件、二進制文件以及硬鏈接文件

? ? d? ? 目錄文件? ? 包含若干文件或子目錄

? ? l? ? 符號鏈接? ? 只保留所指向文件的地址而非文件本身

? ? p? ? 管道文件? ? 用于進程間通信

? ? c? ? 字符設(shè)備? ? 原始的I/O設(shè)備文件旭斥,每次操作僅操作1個字符(例如鍵盤)

? ? b? ? 塊設(shè)備? ? ? ? 按塊I/O設(shè)備文件(例如硬盤)

? ? s? ? 套接字? ? ? ? 套接字是方便進程間通信的特殊文件容达,與管道不同的是套接字能通過網(wǎng)絡(luò)連接使不同的計算機的進程進行通信

3、Linux的文件目錄結(jié)構(gòu)

? ? Linux系統(tǒng)中文件采取樹形結(jié)構(gòu)垂券,即一個根目錄(/)花盐,包含下級目錄或文件的信息;子目錄又包含更下級的目錄或文件的信息菇爪。依次類推層層延伸算芯,最終構(gòu)成一棵樹。

Linux系統(tǒng)的每個目錄都有其特定的功能娄帖,這里只簡單介紹一些主要目錄及其功能

目錄? ? ? ? ? ? 功能說明

/etc? ? ? ? ? ? 存放系統(tǒng)配置文件

/bin? ? ? ? ? ? 存放常用指令

/sbin? ? ? ? (root用戶的)存放指令目錄

/home? ? ? ? 用戶主目錄也祠,所有用戶p的文件默認建立在此目錄下(用戶工作目錄)

/boot? ? ? ? ? 包含內(nèi)核啟動文件

/dev? ? ? ? ? ? 存放設(shè)備文件(與底層驅(qū)動交互)

/usr? ? ? ? ? ? 存放應(yīng)用程序

/mnt? ? ? ? ? ? 掛載目錄

/root? ? ? ? ? ? root用戶主目錄

/proc? ? ? ? ? ? process的所寫,存放描述系統(tǒng)進程的詳細信息

/lib? ? ? ? ? ? ? 存放常見庫文件

/lost+found? ? 可以找到一些誤刪除或丟失的文件并恢復它們

二近速、系統(tǒng)調(diào)用與用戶編程接口(API)

? ? 系統(tǒng)調(diào)用(System Call)是由操作系統(tǒng)實現(xiàn)提供的所有系統(tǒng)調(diào)用所構(gòu)成的程序接口的集合诈嘿。是應(yīng)用程序與操作系統(tǒng)間的接口與紐帶。

操作系統(tǒng)的主要功能是為管理硬件資源和為應(yīng)用程序開發(fā)人員提供良好的環(huán)境來使應(yīng)用程序具有良好的兼容性削葱。為了達到這個目的奖亚,內(nèi)核提供一系列具備預(yù)定功能的函數(shù),通過系統(tǒng)調(diào)用的接口呈現(xiàn)給用戶析砸。當用戶訪問系統(tǒng)調(diào)用昔字,系統(tǒng)調(diào)用把應(yīng)用程序的請求傳遞給內(nèi)核,調(diào)用相應(yīng)的內(nèi)核函數(shù)完成所需處理首繁,將處理結(jié)果返回給應(yīng)用程序作郭。

? ? 應(yīng)用程序編程接口(API,Application Programming Interface)是一些預(yù)定義的函數(shù)弦疮,目的是提供應(yīng)用程序與開發(fā)人員基于軟件/硬件得以訪問一組例程的能力夹攒,而又無需訪問源碼或理解內(nèi)部工作原理機制。

在實際開發(fā)應(yīng)用程序的過程中胁塞,我們并不直接使用系統(tǒng)調(diào)用接口咏尝,而是使用用戶編程接口(API)。為什么呢啸罢?

? ? ? ? 1.系統(tǒng)調(diào)用功能非常簡單编检,有時無法滿足程序的需求。

? ? ? ? 2.不同操作系統(tǒng)的系統(tǒng)調(diào)用接口不兼容扰才,若使用系統(tǒng)調(diào)用接口則程序移植工作量非常大允懂。

? ? 用戶編程接口使用各種庫(在C語言中最主要的是C庫)中的函數(shù)。為了提高編程效率衩匣,C庫中實現(xiàn)了很多函數(shù)累驮。這些函數(shù)實現(xiàn)了許多常用功能供程序開發(fā)者調(diào)用酣倾。這樣一來,程序開發(fā)者無需自己編寫這些代碼谤专,直接可以調(diào)用函數(shù)就能實現(xiàn)功能,提高了編碼效率和代碼復用率午绳。

? ? 使用用戶編程接口還有一個好處:一定程度上解決了程序的可移植性(雖然C語言的可移植性仍沒有Java好)置侍。幾乎所有的操作系統(tǒng)上都實現(xiàn)了C庫,因此使用C語言編寫的程序只需在不同的系統(tǒng)下重新編譯即可運行拦焚。

? ? 通常情況下蜡坊,用戶編程接口API在實現(xiàn)時需要依賴系統(tǒng)調(diào)用接口。例如創(chuàng)建進程API函數(shù)fork()需要調(diào)用內(nèi)核空間的sys_fork()系統(tǒng)調(diào)用赎败。但是還有一些API無需調(diào)用任何系統(tǒng)調(diào)用秕衙。

來源 CSDN

在Linux中用戶編程接口遵循在Unix系統(tǒng)中最流行的應(yīng)用編程編程標準POSIX標準。

/***************POSIX簡介*************************/

? ? POSIX表示可移植操作系統(tǒng)接口(Portable Operating System Interface 僵刮,縮寫為 POSIX )据忘,POSIX標準定義了操作系統(tǒng)應(yīng)該為應(yīng)用程序提供的接口標準,是IEEE為要在各種UNIX操作系統(tǒng)上運行的軟件而定義的一系列API標準的總稱搞糕,其正式稱呼為IEEE 1003勇吊,而國際標準名稱為ISO/IEC 9945。

? ? POSIX標準意在期望獲得源代碼級別的軟件可移植性窍仰。換句話說汉规,為一個POSIX兼容的操作系統(tǒng)編寫的程序,應(yīng)該可以在任何其它的POSIX操作系統(tǒng)(即使是來自另一個廠商)上編譯執(zhí)行驹吮。

/***************POSIX簡介end**********************/

標準I/O與文件I/O的區(qū)別:

? ? 1.文件I/O又稱為低級磁盤I/O针史,遵循POSIX標準。任何兼容POSIX標準的操作系統(tǒng)都支持文件I/O碟狞。標準I/O又稱為高級磁盤I/O啄枕,遵循ANSI C相關(guān)標準。只要開發(fā)環(huán)境有標準C庫篷就,標準I/O就可以使用射亏。

在Linux系統(tǒng)中使用GLIBC標準,它是標準C庫的超集竭业,既支持ANSI C中定義的函數(shù)又支持POSIX中定義的函數(shù)智润。因此Linux下既可以使用標準I/O,也可以使用文件I/O未辆。

? ? 2.通過文件I/O讀寫文件時窟绷,每次操作都會執(zhí)行相關(guān)系統(tǒng)調(diào)用。這樣的好處是直接讀寫實際文件咐柜,壞處是頻繁的系統(tǒng)調(diào)用會增加系統(tǒng)開銷兼蜈。標準I/O在文件I/O的基礎(chǔ)上封裝了緩沖機制攘残,每次先操作緩沖區(qū),必要時再訪問文件为狸,從而減少了系統(tǒng)調(diào)用的次數(shù)歼郭。

? ? 3.文件I/O使用文件描述符打開操作一個文件,可以訪問不同類型的文件(例如普通文件辐棒、設(shè)備文件和管道文件等)病曾。而標準I/O使用FILE指針來表示一個打開的文件,通常只能訪問普通文件漾根。

三泰涂、Linux標準I/O

1、標準I/O定義

? ? 標準I/O指的是ANSI C中定義的用于I/O操作的一系列函數(shù)辐怕。只要操作系統(tǒng)安裝了C庫逼蒙,就可以調(diào)用標準I/O。換句話說寄疏,若程序使用標準I/O函數(shù)是牢,那么源代碼無需進行任何修改就可以在其他操作系統(tǒng)上編譯,具有更好的可移植性赁还。

? ? 除此之外妖泄,由于標準I/O封裝了緩沖區(qū),使得在讀寫文件的時候減少了系統(tǒng)調(diào)用的次數(shù)艘策,提高了效率蹈胡。在執(zhí)行系統(tǒng)調(diào)用的時候,Linux必須從用戶態(tài)切換到內(nèi)核態(tài)朋蔫,在內(nèi)核中處理相應(yīng)的請求罚渐,然后再返回用戶態(tài)。如果頻繁地執(zhí)行系統(tǒng)調(diào)用則會增加這種開銷驯妄。標準I/O為了減少這種開銷荷并,采取緩沖機制,為用戶空間創(chuàng)建緩沖區(qū)青扔,讀寫時優(yōu)先操作緩沖區(qū)源织,在必須訪問文件時(例如緩沖區(qū)滿、強制刷新微猖、文件讀寫結(jié)束等情況)再通過系統(tǒng)調(diào)用將緩沖區(qū)的數(shù)據(jù)讀寫實際文件中谈息,從而避免了系統(tǒng)調(diào)用的次數(shù)。

2凛剥、流的定義

? ? 標準I/O的核心對象是流侠仇。當用標準I/O打開一個文件時,就會創(chuàng)建一個FILE結(jié)構(gòu)體描述該文件。我們把這個FILE結(jié)構(gòu)體稱為“流”逻炊。標準I/O函數(shù)都是基于流進行各種操作的互亮。

/**********************流的分類***********************/

流的分類分為文本流和二進制流兩種:

? ? 文本流:文本流是由字符文件組成的序列,每一行包含0個或多個字符并以'\n'結(jié)尾余素。在流處理過程中所有數(shù)據(jù)以字符形式出現(xiàn)豹休,'\n'被當做回車符CR和換行符LF兩個字符處理,即'\n'ASCII碼存儲形式是0x0D和0x0A溺森。當輸出時慕爬,0x0D和0x0A轉(zhuǎn)換成'\n'

? ? 二進制流:二進制流是未經(jīng)處理的字節(jié)組成的序列,在流處理過程中把數(shù)據(jù)當做二進制序列屏积,若流中有字符則把字符當做ASCII碼的二進制數(shù)表示。'\n'不進行變換磅甩。

例如:2016在文本流中和二進制流中的數(shù)據(jù)類型不同:

文本流:2016---->'2''0''1''6'---->50 48 49 54

二進制流:2016-->數(shù)字2016--->0000011111010001

在Linux/Unix系統(tǒng)中炊林,文本流與二進制流沒有差異,但是在Windows中稍有差異卷要,所以標準C庫定義了兩種流渣聚。

/**********************流的分類end********************/

在使用標準I/O操作文件的時候,每個被程序使用的文件都會在內(nèi)存中開辟一塊區(qū)域僧叉,用來存放與文件相關(guān)的屬性信息奕枝,這些信息存放在一個FILE類型的結(jié)構(gòu)體中,F(xiàn)ILE類型的結(jié)構(gòu)體是由系統(tǒng)定義的一個結(jié)構(gòu)體:

typedef struct

{

? ? short level;? ? ? ? ? ? ? ? //緩沖區(qū)滿/空的狀態(tài)

? ? unsigned flags;? ? ? ? ? ? //文件狀態(tài)標志

? ? char fd;? ? ? ? ? ? ? ? ? ? //文件描述符

? ? unsigned char hold;? ? ? ? //如緩沖區(qū)無內(nèi)容則不讀取字符

? ? short bsize;? ? ? ? ? ? ? ? //緩沖區(qū)的大小

? ? unsigned char *buffer;? ? ? //數(shù)據(jù)緩沖區(qū)的位置

? ? unsigned char *curp;? ? ? ? //指針當前的指向

? ? unsigned istemp;? ? ? ? ? ? //臨時文件指示器

? ? short token;? ? ? ? ? ? ? ? //用于有效性檢查

}FILE;

在標準I/O中瓶堕,常用FILE類型的結(jié)構(gòu)體指針FILE*來操作文件隘道。

/***************對“流”與“文件”的關(guān)系的討論************/

? ? 在初學C語言文件I/O相關(guān)知識點時,經(jīng)常會陷入“什么是流郎笆?”“什么是文件谭梗?”“流和文件有什么關(guān)系(區(qū)別)?”等問題宛蚓。在這里對“流”與“文件”進行簡單的討論激捏,基礎(chǔ)好的同學可跳過該部分。

《C Primer Plus》上說凄吏,C程序處理一個流而不是直接處理文件远舅。但是后面的解釋十分抽象:『流(stream)是一個理想化的數(shù)據(jù)流,實際輸入或輸出映射到這個數(shù)據(jù)流』痕钢。

? ? 本質(zhì)上來說图柏,文件本身就是數(shù)據(jù)的有序序列,因此我們操作文件時是按順序依次操作該文件的數(shù)據(jù)盖喷。我們可以想象一個傳送帶爆办,傳送帶上的產(chǎn)品就是待操作數(shù)據(jù)。當我們對文件內(nèi)的數(shù)據(jù)進行操作時课梳,已操作的數(shù)據(jù)從當前位置離開距辆,待操作的數(shù)據(jù)不斷流向當前位置余佃,這樣文件內(nèi)的數(shù)據(jù)就產(chǎn)生了流動的感覺,這個“傳送帶”就是C語言內(nèi)“流”的原型跨算。

? ? 我們打開一個流爆土,就意味著將該流與該文件進行了連接(即讓文件內(nèi)的“產(chǎn)品”放上“傳送帶”),關(guān)閉流將斷開流與該文件的連接诸蚕。此時我們對流進行操作就是對文件進行操作步势。通常在不產(chǎn)生歧義的情況下,“文件”與“流”可以不予區(qū)分背犯。

? ? 在程序開始執(zhí)行的時候坏瘩,操作系統(tǒng)會默認開啟stdin、stdout漠魏、stderr三個文件倔矾,這三個文件作為輸入、輸出柱锹、輸出錯誤的流哪自,這樣我們使用諸如scanf()、printf()等就無需手動加載流禁熏,方便使用壤巷。

當我們使用fopen()打開一個文件的時候,該文件會返回一個FILE*類型的指針瞧毙,例如:

FILE *fp = fopen("hello.txt","w")

此時文件hello.txt與流指針fp就關(guān)聯(lián)了起來胧华,對fp的操作就相當于對文件hello.txt進行操作。

/***************對“流”與“文件”的關(guān)系的討論end*********/

在標準I/O中預(yù)定義了三塊緩沖區(qū):stdin升筏、stdout撑柔、stderr,分別代表標準輸入流您访、標準輸出流铅忿、標準輸出錯誤流。見下:

流的名稱? ? ? ? 程序中使用

標準輸入? ? ? ? ? stdin? ?

標準輸出? ? ? ? ? stdout? ?

標準錯誤輸出? ? stderr? ?

標準I/O中的流的緩沖類型有三種:

1.全緩沖:這種情況下灵汪,當緩沖區(qū)被填滿后才進行實際的I/O操作檀训。對于存放在磁盤上的普通文件用標準I/O打開時默認是全緩沖的。當緩沖區(qū)滿或者執(zhí)行刷新緩沖區(qū)(fflush)操作才會進行磁盤操作享言。

2.行緩沖:這種情況下峻凫,當在輸入/輸出中遇到換行符時執(zhí)行I/O操作。-->標準輸入/輸出流(stdin/stdout)就是使用行緩沖览露。

3.無緩沖:不使用緩沖區(qū)進行I/O操作荧琼,即對流的讀寫操作會立即操作實際文件。標準出錯流(stderr)是不帶緩沖的,這就使得當發(fā)生錯誤時命锄,錯誤信息能第一時間顯示在終端上堰乔,而不管錯誤信息是否包含換行符。

示例1.1:stdout使用行緩沖形式

效果:不會立即打印內(nèi)容脐恩,而是等待'\n'或者緩沖區(qū)滿才輸出镐侯。

#include<stdio.h>

int main()

{

? ? while(1)

? ? {

? ? ? ? printf("Hello World");

? ? ? ? sleep(1);//延時1秒

? ? }

? ? return 0;

}


來源 CSDN

當緩沖區(qū)滿的時候才輸出到屏幕

示例1.2:stdout使用行緩沖形式

效果:當添加了'\n'之后,會正確地輸出

#include<stdio.h>

int main()

{

? ? while(1)

? ? {

? ? ? ? printf("Hello World\n");

? ? ? ? sleep(1);//延時1秒

? ? }

? ? return 0;

}


來源 CSDN

每1S輸出一次

示例1.3:stderr使用無緩沖形式

效果:stderr使用無緩沖驶冒,即使不使用'\n'仍能立即輸出

#include<stdio.h>

int main()

{

? ? while(1)

? ? {

? ? ? ? perror("Hello World");? //無緩沖

? ? ? ? sleep(1);//延時1秒

? ? }

? ? return 0;

}


來源 CSDN

perror會自動打印系統(tǒng)的提示信息 (:Success)

示例2:編寫程序?qū)崿F(xiàn)以下功能:

? ? ⒈向標準輸出流輸出HelloWorld

? ? ⒉向標準錯誤流輸出HelloWorld

? ? ⒊控制輸出重定向苟翻,使程序僅能輸出標準輸出流的字符

? ? ⒋控制輸出重定向,使程序僅能輸出標準錯誤流的字符

#include<stdio.h>

int main()

{

? ? fprintf(stdout,"%s","This is stdout:HelloWorld!\n");

? ? fprintf(stderr,"%s","This is stderr:HelloWorld!\n");

? ? //fprintf的作用是向某個流(文件)中按格式輸出指定內(nèi)容

? ? return 0;

}


來源 CSDN

實現(xiàn)第三步的功能:在執(zhí)行時:./a.out 2> /dev/null


來源 CSDN

僅能顯示標準輸出的內(nèi)容

實現(xiàn)第四步的功能:在執(zhí)行時:./a.out 1> /dev/null


來源 CSDN

僅能顯示標準出錯的內(nèi)容

————————————————

版權(quán)聲明:本文為CSDN博主「nan_lei」的原創(chuàng)文章骗污,遵循CC 4.0 BY-SA版權(quán)協(xié)議崇猫,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/nan_lei/article/details/81460798

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末需忿,一起剝皮案震驚了整個濱河市邓尤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贴谎,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件季稳,死亡現(xiàn)場離奇詭異擅这,居然都是意外死亡,警方通過查閱死者的電腦和手機景鼠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門仲翎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人铛漓,你說我怎么就攤上這事溯香。” “怎么了浓恶?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵玫坛,是天一觀的道長。 經(jīng)常有香客問我包晰,道長湿镀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任伐憾,我火速辦了婚禮勉痴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘树肃。我一直安慰自己蒸矛,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雏掠,像睡著了一般斩祭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磁玉,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天停忿,我揣著相機與錄音,去河邊找鬼蚊伞。 笑死席赂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的时迫。 我是一名探鬼主播颅停,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼掠拳!你這毒婦竟也來了癞揉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤溺欧,失蹤者是張志新(化名)和其女友劉穎喊熟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姐刁,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡芥牌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了聂使。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壁拉。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖柏靶,靈堂內(nèi)的尸體忽然破棺而出弃理,到底是詐尸還是另有隱情,我是刑警寧澤屎蜓,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布痘昌,位于F島的核電站,受9級特大地震影響梆靖,放射性物質(zhì)發(fā)生泄漏控汉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一返吻、第九天 我趴在偏房一處隱蔽的房頂上張望姑子。 院中可真熱鬧,春花似錦测僵、人聲如沸街佑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沐旨。三九已至森逮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間磁携,已是汗流浹背褒侧。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谊迄,地道東北人闷供。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像统诺,于是被迫代替她去往敵國和親歪脏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容