Linux系統程式設計(二)檔案I O

2023-07-24 20:16:56 字數 4982 閱讀 4101

一、系統呼叫概述1、什麼是檔案io 1)本質檔案io 等價於檔案的input output 即檔案的輸入輸出在linux下一切皆檔案,在linux下所有裝置的訪問都可以以檔案的形式進行訪問。2、系統呼叫概念 0)回顧以前操作檔案的函式fopen、fread、fwrite、fclose等等,這些函式也能夠操作檔案,但是這些函式不叫api(系統呼叫) 1)什麼是api?

概念:系統呼叫是linux核心對上層應用提供的訪問系統核心的介面(函式),上層應用訪問系統核心只能通過系統呼叫來實現。這裡說的這個介面就是api。原因:系統核心很核心,也很脆弱,一旦出問題會導致整個程式崩潰。所以通常情況下所有使用者程序不允許訪問核心資料的,但是很多情況下,使用者程序又需要獲得系統服務(比如說操作/控制系統硬體),那為了保證系統核心的安全性,作業系統就提供了唯一訪問系統核心的路徑---即api介面 2)檔案i/o的api和庫函式的區別①庫函式的特點

特點:部分庫函式在進行操作的時候不需要訪問系統核心,比如bzero、strcmp、strcat等等,部分庫函式在進行操作的時候需要進行系統呼叫,比如fopen、fread、fwrite、fclose等等系統呼叫訪問的過程:首先cpu工作有兩種狀態,分別是使用者態和核心態,一般程式工作在使用者態,當程式進行系統呼叫的時候,使用者態相關的棧和記憶體環境首先會進行備份,然後轉入核心態進行系統呼叫,呼叫完畢後再切換回使用者態,切換的過程又需要還原相關環境。這種切換通常需要消耗時間。其次:庫函式訪問檔案的時候,在進行讀寫的時候並不是立即執行的,通常在記憶體中會有乙個緩衝區來存放讀寫的資料,在緩衝區資料滿的時候再將內容寫入到檔案/磁碟。

總結:1.部分庫函式訪問硬體本身是通過系統呼叫實現的2.庫函式操作硬體會有緩衝會有遲滯3.庫函式與底層系統關聯性不大,可移植性強②庫函式和api的區別應用方向:系統呼叫api更偏向於底層硬體開發庫函式因為沒有平台差異,更適合做應用程式開發 3) 檔案描述符一般在使用庫函式操作檔案的時候,使用的是檔案指標來訪問具體某個檔案的。對於系統呼叫函式來說,一般使用的是乙個int型別的數值來表示檔案具體某個檔案的。一般程式執行起來後(每個程序)都有一張檔案描述符的表,標準輸入、標準輸出、標準錯誤輸出裝置檔案被開啟,對應的檔案描述符記錄在表中,後面但凡開啟乙個檔案,其檔案編號就會自動加1.

linux中乙個程序最多只能開啟nropendefault(1024)個檔案,所以一般檔案不使用的時候盡量關閉檔案。注:預設當前系統允許開啟最大檔案數記錄在:/proc/sys/fs/file-max檔案中當前使用者使用的資源限制資訊檢視:ulimit -a修改當前使用者每個程序允許開啟的最大檔案數:ulimit -n 數值。

二、檔案io相關函式1.檔案io的系統呼叫函式 1) open函式原型:int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);函式功能:開啟檔案,如果檔案不存在則可以選擇建立函式引數:pathname:檔案的路徑及檔名flags:開啟檔案的行為標誌,必選項 o_rdonly, o_wronly, o_rdwrmode:這個引數,只有在檔案不存在時有效,指新建檔案時指定檔案的許可權函式返回值:成功:成功返回開啟的檔案描述符失敗:-1 補充說明1:flags 詳細說明必選項:取值 含義o_rdonly 以唯讀的方式開啟o_wronly 以只寫的方式開啟o_rdwr 以可讀、可寫的方式開啟可選項,和必選項按位或起來取值 含義o_creat 檔案不存在則建立檔案,使用此選項時需使用 mode 說明檔案的許可權o_excl 如果同時指定了 o_creat,且檔案已經存在,則出錯 o_trunc 如果檔案存在,則清空檔案內容 o_append 寫檔案時,資料新增到檔案末尾 o_nonblock 對於裝置檔案, 以 o_nonblock 方式開啟可以做非阻塞 i/o補充說明2: 1)檔案最終許可權:mode &~umask (mode為八進位制數) 0666 --檔案 0777 --資料夾 0002 2)umask是指檔案掩碼,可以通過umask命令檢視 3)umask -s 可以檢視各組使用者的預設操作許可權 4)umask mode 可以臨時設定掩碼值,mode為八進位制數(想要永久的修改umask值的話,可以將命令新增到啟動檔案) 2) read函式原型:ssize_t read(int fd, void *buf, size_t count); 函式功能:把指定數目的資料讀到記憶體(緩衝區) 函式引數:fd : 檔案描述符buf : 記憶體首位址count : 想要讀取的位元組個數 函式返回值:成功:實際讀取到的位元組個數失敗:-1 3)write函式原型:ssize_t write(int fd, const void *buf, size_t count); 函式功能:把指定數目的資料寫到檔案(fd) 函式引數:fd : 檔案描述符buf : 資料首位址count : 寫入資料的長度(位元組) 函式返回值:成功:實際寫入資料的位元組個數失敗: -1 4)close函式原型:int close(int fd); 函式功能:關閉已開啟的檔案 函式引數:fd : 檔案描述符,open()的返回值 函式返回值:成功: 失敗: -1, 並設定 errno 5)fcntl 函式原型:int fcntl(int fd, int cmd, .arg */函式功能:改變已開啟的檔案性質,fcntl針對檔案描述符提供控制(針對已經開啟的檔案描述符) 函式引數: fd:操作的檔案描述符cmd:操作方式arg:針對 cmd 的值,fcntl 能夠接受第三個引數 int arg 函式返回值:成功:返回某個其他值失敗:-1fcntl 函式有 5 種功能:1) 複製乙個現有的描述符(cmd=f_dupfd)2) 獲得/設定檔案描述符標記(cmd=f_getfd 或 f_setfd)3) 獲得/設定檔案狀態標記(cmd=f_getfl 或 f_setfl)4) 獲得/設定非同步 i/o 所有權(cmd=fgetown 或 fsetown)5) 獲得/設定記錄鎖(cmd=fgetlk, fsetlk 或 f_setlkw)案例給標準輸入設定非阻塞:#include #include #include int main(int argc,char * ar**)獲取檔案屬性系統預設為我們開啟了三個檔案 //stdin 0 stdout 1 stderro 2 //獲取檔案的狀態值 int status = fcntl(0,f_getfl); 設定檔案的狀態值 status |=o_nonblock; status = fcntl(0,f_setfl,status); 測試設定結果 printf("準備讀取");int ret = read(0,buf,sizeof(buf));printf("讀取到的內容:%s",buf); 關閉檔案 close(0); return 0;} 6)statint stat(const char *path, struct stat *buf);int lstat(const char *pathname, struct stat *buf); 函式功能:獲取檔案狀態資訊stat 和 lstat 的區別:當檔案是乙個符號鏈結時,lstat 返回的是該符號鏈結本身的資訊;而 stat 返回的是該鏈結指向的檔案的資訊 函式引數:path:檔名buf:儲存檔案資訊的結構體 函式返回值:成功: 失敗: -1 stat結構體說明:struct stat #include #include #include #include int main(int argc,char * ar**)獲取乙個未開啟的檔案的檔案狀態資訊 struct stat state; int ret=stat(ar**[1],&state); if(ret < 0) mode_t m = state.st_mode &s_ifmt; if(m ==s_ifsock) else if(m ==s_ifreg) else if(m ==s_ifdir) return 0;} 7)opendir函式原型:dir *opendir(const char *name); 函式功能:開啟資料夾 函式引數:資料夾路徑名 函式返回值:成功返回資料夾指標值,失敗返回-1#include #include #include int main(int argc,char * ar**)開啟乙個資料夾 dir * dir = null; dir = opendir(ar**[1]);if(dir ==null) 顯示資料夾內的內容 struct dirent * opened_dir = null; while(1) if(opened_dir->d_type ==dt_blk) else if(opened_dir->d_type ==dt_reg) else if(opened_dir->d_type ==dt_dir) else printf("%s",opened_dir->d_name); 關閉資料夾 closedir(dir); return 0;}8)readdir函式原型:struct dirent *readdir(dir *dirp);函式功能:讀取開啟了的檔案資訊函式引數: dir:開啟了的目錄指標函式返回值:成功返回下乙個檔案資訊的結構體指標,失敗返回nullstruct dirent ;9)rewindir 函式原型:void rewinddir(dir *dirp);函式功能:將dir指標恢復到開始的位置函式引數:dir --opendir開啟的資料夾指標函式返回值:無 10)closedir 函式原型:int closedir(dir *dirp); 函式功能:關閉開啟著的目錄 函式引數:開啟後的資料夾指標 函式返回值:成功返回0,失敗返回-14.補充內容1)linux檔案許可權

2)檔案的許可權一般來說:建立資料夾的預設建立許可權是0777 (0代表的uid和gid)777代表的是檔案許可權建立檔案的預設建立許可權是0666檔案掩碼:但是linux為了不同使用者或不同屬主有不同的操作許可權,設計了檔案許可權掩碼(umask)檔案最終的許可權:檔案預設建立許可權 & 檔案許可權掩碼)使用者指定的許可權 & 檔案許可權掩碼)注:umask查到的0002其中第乙個0表示的是特殊許可權相關(暫時不管)3)補充函式游標移動:lseek讀取資料夾函式:readdir

linux關機命令詳解

在linux中,有多個命令可以用於關機系統。下面是一些常用的關機命令及其用法 1.shutdown 該命令提供了對系統進行關機的靈活控制。使用該命令時,可以指定關機的時間和原因。以下是乙個示例 shutdown h 20 00 sorry,we need to shut down for maint...

linux檢視埠占用的方法

在linux中,有幾種方式可以檢視埠占用情況。下面是常用的幾種方法及其用法 1.netstat命令 netstat命令用於顯示與網路相關的資訊,包括正在使用的埠。要檢視所有埠的占用情況,可以使用以下命令 netstat tuln 其中,t選項表示顯示tcp連線,u選項表示顯示udp連線,l選項表示僅...

linux刪除資料夾命令

在linux中,有幾種方法可以刪除資料夾。下面是常用的幾種方法及其用法 1.rm命令 rm remove 命令用於刪除檔案和目錄。要刪除乙個空目錄,可以使用以下命令 rm r 目錄路徑 其中,r選項表示遞迴刪除該目錄以及其所有子目錄和檔案。例如,要刪除名為 myfolder 的空目錄,可以執行以下命...