1. 程式人生 > >嵌入式 Linux系統程式設計(一)——檔案IO

嵌入式 Linux系統程式設計(一)——檔案IO

嵌入式 Linux系統程式設計(一)——檔案IO

一、檔案IO概念

        linux檔案IO操作有兩套大類的操作方式:不帶快取的檔案IO操作,帶快取的檔案IO操作。不帶快取的屬於直接呼叫系統呼叫(system call)的方式,高效完成檔案輸入輸出。它以檔案識別符號(整型)作為檔案唯一性的判斷依據。這種操作不是ASCI標準的,與系統有關,移植有一定的問題。而帶快取的是在不帶快取的基礎之上封裝了一層,維護了一個輸入輸出緩衝區,使之能跨OS,成為ASCI標準,稱為標準IO不帶快取的方式頻繁進行使用者態 和核心態的切換,高效但是需要程式設計師自己維護;帶緩衝的方式因為有了緩衝區,不是非常高效,但是易於維護。由此,不帶緩衝區的通常用於檔案裝置的操作,而帶緩衝區的通常用於普通檔案的操作。

    檔案平時儲存在塊儲存裝置中的檔案系統中(靜態檔案),open開啟一個檔案時,linux核心在程序中建立一個開啟檔案的資料結構,記錄開啟的檔案的資訊;核心在記憶體中申請建立一段記憶體,並將靜態檔案的內容從塊儲存裝置讀取到特定地址管理存放(動態檔案)。

    開啟檔案後對這個檔案的讀寫操作都是針對記憶體中的動態檔案,當對動態檔案進行讀寫後,動態檔案和塊儲存裝置中的靜態檔案不同步,close時關閉動態檔案,核心將記憶體中的動態檔案的內容同步到塊儲存裝置的靜態檔案。

二、檔案描述符

    檔案描述符是一個非負整數,用來標識一個程序中開啟或建立的檔案。當開啟一個現有檔案或建立一個新檔案時,核心嚮應用程式程序返回一個檔案描述符。當讀或寫一個檔案時,使用

opencreat返回的檔案描述符標識該檔案,將其作為引數傳遞給readwrite等操作函式檔案描述符的作用域限於當前應用程式的程序,檔案關閉close後,檔案描述符將被釋放。在遵從POSIX的應用程式中,檔案描述符012分別對應STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO,因此一個應用程式程序中檔案描述符總是從3開始的。

三、常用檔案IO函式

1open

            #include <sys/types.h>

       #include <sys/stat.h>

       #include <fcntl.h>

       int open(const char *pathname, int flags);

       int open(const char *pathname, int flags, mode_t mode);

Open函式返回開啟、建立檔案的檔案描述符,如果失敗返回-1

Flags

O_RDONLY   //只讀開啟

O_WRONLY   //只寫開啟

O_RDWR    //讀、寫開啟

O_APPEND   //每次寫時都追加到檔案的尾端

O_CREAT   //若此檔案不存在,則建立它。使用時,需要第三個引數mode

O_EXCL   //如果同時指定了O_CREAT,而檔案已經存在,則會出錯。用此可以測試一個檔案是否存在,如果不存在,則建立此檔案

O_TRUNC  //如果此檔案存在,而且為只寫或讀寫成功開啟,則將其長度截短為0

O_NONBLOCK  //如果pathname指的是一個FIFO、一個塊特殊檔案或一個字元特殊檔案,則此選項為檔案的本次操作和後續的I/O操作設定非阻塞模式。只用於裝置檔案,不能用於普通檔案。

O_SYNC    //使每次write都等到物理I/O操作完成,包括由write操作引起的檔案屬性更新所需的I/O

Mode

使用四個數字指定建立檔案的許可權,與linux的許可權設定相同,如0755

2close

            #include <unistd.h>

       int close(int fd);

關閉檔案描述符fd指向的動態檔案,並存儲檔案和重新整理快取。

3read

 #include <unistd.h>

           ssize_t read(int fd, void *buf, size_t count);

Read成功返回讀取的位元組數,失敗返回-1

4write

         #include <unistd.h>

        ssize_t write(int fd, const void *buf, size_t count);

Write成功返回寫入的位元組數,失敗返回-1

5、lseek

    每一個已開啟的檔案都有一個讀寫位置,當開啟檔案時通常其讀寫位置是指向檔案開頭,若是以附加的方式開啟檔案(O_APPEND),則讀寫位置會指向檔案尾。當read()write()時,讀寫位置會隨之增加,lseek()便是用來控制該檔案的讀寫位置。

#include <sys/types.h>

       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);

Lseek成功,返回當前的位置,即當前位置距離檔案開頭的位元組數,失敗返回-1

Offset:偏移量

Whence:偏移基址

SEEK_SET:將讀寫位置指向檔案頭後再增加offset個位移量

SEEK_CUR以目前的讀寫位置往後增加offset個位移量

SEEK_END將讀寫位置指向檔案尾後再增加offset個位移量

A 欲將讀寫位置移到檔案開頭時

lseekint fd,0,SEEK_SET);

返回0

B欲將讀寫位置移到檔案尾時

lseekint fd0,SEEK_END);

返回檔案長度

C想要取得目前檔案位置時

lseekint fd0,SEEK_CUR);

返回當前檔案指標相對於檔案開頭的偏移量

D、計算檔案長度

int get_file_length(const char *filename)

{

    unsigned int n = 0;

    unsigned int fd = open(filename, O_RDONLY);

    if(fd < 0)

    {   

        fprintf(stderr, "error:%s PID: %d\n", strerror(errno), getpid());

        return -1;

    }   

    n = lseek(fd, 0, SEEK_END);

    close(fd);

    return n;

}

E、建立空洞檔案

int create_null_file(const char *filename, unsigned int len)

{

    unsigned int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);

    if(fd < 0)

    {   

        fprintf(stderr, "error:%s PID: %d", strerror(errno), getpid());

        return -1;

    }   

    lseek(fd, len, SEEK_SET);

    write(fd, "\0",1);

    close(fd);

    return 0;

}

四、錯誤資訊

errno就是error number

如果程式程式碼中包含 #include <errno.h>,函式呼叫失敗的時候,系統會自動用用錯誤程式碼填充errno這個全域性變數,errno全域性變數可以獲得失敗原因。函式呼叫失敗是否會設定errno全域性變數由函式決定,並不是所有函式呼叫失敗都會設定errno變數。

#include <string.h>

char *strerror(int errnum);

fprintf(stderr,"error :%s, PID: %d ",strerror(errno),getpid());

根據errnum錯誤碼返回一個指向描述errnum錯誤碼資訊的字串指標。

 #include <stdio.h>

 void perror(const char *s);

perror ( )用來將上一個函式發生錯誤的原因輸出到標準錯誤(stderr),引數s 所指的字串會先打印出,後面再加上錯誤原因 字串。

五、檔案共享

檔案共享的是三種實現方式:

1、同一個程序中多次開啟同一個檔案

2、不同程序中多次開啟同一個檔案

3、Dupdup2讓程序複製檔案描述符

    同一個程序中多次開啟同一個檔案,返回的檔案描述符不同,同時對這個檔案進行寫操作時,分別寫入內容,後邊寫入的內容將覆蓋前邊寫入的內容,此時不同的檔案描述符擁有自己的檔案指標。當open建立、開啟檔案時採用O_APPEND,則不同的檔案描述符的不同檔案指標會實現同步。O_APPEND是原子操作的。所謂原子操作,就是該操作絕不會在執行完畢前被任何其他任務或事件打斷

檔案描述符的複製

#include <unistd.h>

int dup(int oldfd);//返回新分配的檔案描述符,失敗返回-1

int dup2(int oldfd, int newfd);//newfd為指定的新的檔案描述符,返回新分配的檔案描述符,失敗返回-1

dup函式複製的檔案描述符不同,但檔案指標相同,所以對檔案的操作是原子操作的。

六、檔案IO與標準IO庫的區別

    檔案IO與標準IO庫的區別:檔案IOlinux系統的API,標準IO庫是C語言庫函式,標準IO庫函式由linux API封裝而來,函式內部通過呼叫linux API完成。API在不同的作業系統之間不能通用,C語言庫函式可以在不同作業系統之間移植。檔案IO函式不帶快取,標準IO庫函式帶快取。

本文出自 “生命不息,奮鬥不止” 部落格,轉載請與作者聯絡!

相關推薦

嵌入式 Linux系統程式設計——檔案IO

嵌入式 Linux系統程式設計(一)——檔案IO一、檔案IO概念        linux檔案IO操作有兩套大類的操作方式:不帶快取的檔案IO操作,帶快取的檔案IO操作。不帶快取的屬於直接呼叫系統呼叫(

linux系統程式設計--時間與錯誤處理

#inlcude<error.h> errno perror(); //列印錯誤 strerror //列印錯誤 #inlcude<time.h> //使用CLOCKS_PER_SEC //常量可以得到秒數 clock_t \\ typedef

linux系統程式設計--檔案操作

1.0    檔案描述符         每個程序啟動後會自動開啟三個檔案描述符 0、1、2             分別對應於巨集 STDIN_FIL

Linux系統程式設計4——檔案IO之ioctl函式

ioctl是裝置驅動程式中對裝置的I/O通道進行管理的函式。所謂對I/O通道進行管理,就是對裝置的一些特性進行控制,例如串列埠的傳輸波特率、馬達的轉速等等。它的引數個數如下:int ioctl(int fd, int cmd, …);其中fd就是使用者程式開啟裝置時使用ope

嵌入式Linux學習筆記檔案程式設計

一、系統呼叫-建立 int creat(const char *filename,mode_t mode) filename:要建立的檔名(包含路徑,預設為當前路徑) mode:建立模式 常見建立模式: S_IRUSR 可讀

Linux系統管理

linux redhat 服務器 系統管理 點擊下載:Linux系統管理(一)本文出自 “飛奔的魚兒” 博客,請務必保留此出處http://feiyuer.blog.51cto.com/6967044/1931977Linux系統管理(一)

Linux系統管理Linux系統安裝與修復

linux系統安裝與修復一. Linux多種安裝方式與應用軟件安裝1. Linux的硬盤安裝方式(1) 復制Linux的ISO文件到硬盤某個分區(2) 用Linux安裝啟動盤啟動/DOS啟動盤啟動計算機註: DOS啟動盤中必須要存放加載Linux系統的工具及Linux內核和initrd映像文件,主要文件包括:

Linux系統管理Linux設備和內核管理

linux設備和內核管理一. 設備管理概述1.Linux設備的分類字符設備(c):以字符為單位,傳輸速率較低,無需緩沖區。塊設備(b):以數據塊為單位組織和傳輸數據,需要建立緩沖區網絡設備(s):一種通過SOCKET接口進行主機通信的設備2.設備文件(1)功能用於用戶訪問設備進行輸入和輸出操作(2)常見的設

Linux系統介紹

第一部分:     1:linux基礎簡介         1:作業系統(Operating System)          &nb

Linux基礎之檔案的建立

在GUI的桌面環境中,建立檔案是很簡單的,例如Windows平臺中,大多數情況下只需要點選右鍵,就可以新建文字文件等各類檔案。在終端中建立檔案,大體有這麼三種方式,使用touch命令進行建立,使用文字編輯器進行建立,使用重定向符號進行建立,接下來就演示如何使用

Linux網路程式設計:一個簡單的socket程式

伺服器: /* *tcp_server.c */ #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include

linux CAN程式設計

轉載自:https://blog.csdn.net/lizhu_csdn/article/details/51490958 Linux 系統中CAN 介面配置 在 Linux 系統中, CAN 匯流排介面裝置作為網路裝置被系統進行統一管理。在控制檯下, CAN 匯流排的配置和乙太網的配置使用

Linux網路程式設計基礎

 一、資料儲存順序:大端和小端         大端模式: 地址的增長順序與值的增長順序相反         小段模式: 地址的增長順序與值的增長順序相同         為什麼會有大小端模式之分呢?這是因為在計算機系統中,我們是以位元組為單位的,每個地址單元都對應著

linux C程式設計gcc的用法

C/C++的編譯環境:make工具,編譯器gcc,偵錯程式gdb,C/C++標準庫。常用庫資訊列表build-essential包含gcc,g++,make,libc6-dev等寫程式時基本會用到的工具,因此只安裝build-essential,gcc,make等工具也會自動安裝。不清楚的話全部都a

Linux網路程式設計 基礎API介紹

一、socket 地址API 在介紹地址API前先弄清什麼是大端位元組序、小端位元組序,主機位元組序、網路位元組序。 大端位元組序:指一個整數的高位位元組儲存在記憶體的低地址處,低位位元組儲存在記憶體的高地址處。 小端位元組序:指整數的高位位元組儲存在記憶體的高

linux學習筆記--檔案和目錄管理

檔案系統架構 Linux檔案系統具有層級性 檔案或者目錄起始於根目錄“/”成為樹狀結構 最頂層由/開始 檔案和目錄名區分大小寫 路徑通過“/”分隔開 “..”表示上層目錄 “.”表示當前目錄 隱藏

Linux系統程式設計24——訊號的生命週期

訊號生命週期為從訊號傳送到訊號處理函式的執行完畢。對於一個完整的訊號生命週期(從訊號傳送到相應的處理函式執行完畢)來說,可以分為三個重要的階段,這三個階段由四個重要事件來刻畫:訊號誕生;訊號在程序中註冊完畢;訊號在程序中的登出完畢;訊號處理函式執行完畢。相鄰兩個事件的時間間隔

嵌入式Linux驅動開發一個簡單的Linux核心模組框架

#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> static

Linux Shell 程式設計

從程式設計師的角度來看, Shell本身是一種用C語言編寫的程式,從使用者的角度來看,Shell是使用者與Linux作業系統溝通的橋樑。使用者既可以輸入命令執行,又可以利用 Shell指令碼程式設計,完成更加複雜的操作。在Linux GUI日益完善的今天,在系統管理等領域

嵌入式Linux裸機開發——點亮Led

嵌入式Linux裸機開發(一)——點亮Led開發板:友善之臂smart210一、電路圖查閱1、底板電路圖查閱開發板底板電路圖,查閱LED相關部分LED電路工作原理:LED的正極接3.3V,負極接地時導通