嵌入式 Linux系統程式設計(一)——檔案IO
嵌入式 Linux系統程式設計(一)——檔案IO
一、檔案IO概念
linux檔案IO操作有兩套大類的操作方式:不帶快取的檔案IO操作,帶快取的檔案IO操作。不帶快取的屬於直接呼叫系統呼叫(system call)的方式,高效完成檔案輸入輸出。它以檔案識別符號(整型)作為檔案唯一性的判斷依據。這種操作不是ASCI標準的,與系統有關,移植有一定的問題。而帶快取的是在不帶快取的基礎之上封裝了一層,維護了一個輸入輸出緩衝區,使之能跨OS,成為ASCI標準,稱為標準IO庫。不帶快取的方式頻繁進行使用者態 和核心態的切換,高效但是需要程式設計師自己維護;帶緩衝的方式因為有了緩衝區,不是非常高效,但是易於維護。由此,不帶緩衝區的通常用於檔案裝置的操作,而帶緩衝區的通常用於普通檔案的操作。
檔案平時儲存在塊儲存裝置中的檔案系統中(靜態檔案),open開啟一個檔案時,linux核心在程序中建立一個開啟檔案的資料結構,記錄開啟的檔案的資訊;核心在記憶體中申請建立一段記憶體,並將靜態檔案的內容從塊儲存裝置讀取到特定地址管理存放(動態檔案)。
開啟檔案後對這個檔案的讀寫操作都是針對記憶體中的動態檔案,當對動態檔案進行讀寫後,動態檔案和塊儲存裝置中的靜態檔案不同步,close時關閉動態檔案,核心將記憶體中的動態檔案的內容同步到塊儲存裝置的靜態檔案。
二、檔案描述符
檔案描述符是一個非負整數,用來標識一個程序中開啟或建立的檔案。當開啟一個現有檔案或建立一個新檔案時,核心嚮應用程式程序返回一個檔案描述符。當讀或寫一個檔案時,使用
三、常用檔案IO函式
1、open
#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
2、close
#include <unistd.h>
int close(int fd);
關閉檔案描述符fd指向的動態檔案,並存儲檔案和重新整理快取。
3、read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
Read成功返回讀取的位元組數,失敗返回-1
4、write
#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、 欲將讀寫位置移到檔案開頭時
lseek(int fd,0,SEEK_SET);
返回0
B、欲將讀寫位置移到檔案尾時
lseek(int fd,0,SEEK_END);
返回檔案長度
C、想要取得目前檔案位置時
lseek(int fd,0,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、Dup和dup2讓程序複製檔案描述符
同一個程序中多次開啟同一個檔案,返回的檔案描述符不同,同時對這個檔案進行寫操作時,分別寫入內容,後邊寫入的內容將覆蓋前邊寫入的內容,此時不同的檔案描述符擁有自己的檔案指標。當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庫的區別:檔案IO是linux系統的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,負極接地時導通