Linux環境程式設計入門 四 檔案操作的系統呼叫

2021-07-24 09:03:09 字數 4494 閱讀 8267

tar zxvf chapter4.tar

.gz

在linux系統中,幾乎可以認為一切皆檔案。所以檔案的操作是非常頻繁且至關重要的。在這一章中,我們來介紹一下linux系統下的檔案操作相關的程式設計。

在講解檔案操作之前,我們先簡單的介紹下linux系統上的檔案許可權。

在任意目錄下輸入下列命令:

ls -l
將會有類似如下的輸出:

我們先看第一行:

drwxrwxr-x. 2 test

test 104 nov 3 21:21

example

第一列的第乙個字元 「d」表示該行的檔案(example)是乙個目錄。第一列接下來的 「rwxrwxr-x」可以分為三組:

第一組 「rwx」: 對應檔案(這裡的example目錄)的所有者的許可權,所有者即第三列的 「test」使用者。

第二組 「rwx」:對應檔案的所屬組的許可權,所屬組即第四列的 「test」組。

第三組 「r-x」:其他使用者的許可權。

那麼每組下的rwx是什麼意思呢?

r: 表示對應的使用者/組有寫的許可權

w: 表示對應的使用者/組有讀的許可權

x: 表示對應的使用者/組有執行檔案的許可權

對於通常意義下的檔案,這三個許可權很好理解,那麼對於目錄,又該怎樣理解呢? 其實我們可以簡單的理解為既然linux下幾乎一切皆檔案,那麼目錄也是檔案,目錄的內容就是目錄下的那些檔案,這樣就不難理解目錄的rwx許可權分別對應什麼操作了:

r: 查詢該目錄下的檔案(如 「ls 目錄」)

w: 修改目錄下的目錄結構,如刪除檔案,重新命名檔案,新建檔案等

x: 表示能夠進入該目錄(如 「cd 目錄」)

在c語言的標準i/o庫(stdio)中,也有許多i/o相關的函式,這裡我們不做**,有興趣的讀者可以查閱c語言相關資料。我們在這一章中,主要**linux檔案的底層系統呼叫。(c語言的標準i/o庫已經提供了相當多的功能,但是如果你需要對檔案操作進行精確的控制,則底層系統呼叫會比較合適)。

在講檔案操作的系統呼叫前,我們先來講一下檔案描述符。這是一些整數值,它們對應到具體的檔案。當程式想操作某個檔案的時候,只要向相應的函式裡傳入檔案描述符就可以了。我們舉例說明一下:

每乙個程序一般都會有如下三個已經開啟的檔案描述符:

0:標準輸入

1:標準輸出

2:異常輸出

當乙個程序想向標準輸出(一般為終端或控制台)輸出字元時,便可通過檔案描述符2來進行輸出。讀者可以在下面講解系統呼叫的時候體會檔案描述符的意義。

open系統呼叫

open系統呼叫的原型如下:

#include 

//在遵循posix規範的系統上,下面兩個標頭檔案不是必須的

#include

#include

int open(const

char *path, int oflags);

int open(const

char *path, int oflags, mode_t mode);

我們來逐一分析open函式的引數和返回值(詳細的文件可以在終端輸入 「man 2 open」檢視):

最一目了然的是path,這個就是我們要開啟的檔案的位址 (如 「/home/test/test.txt」),而返回的int型別的值便是我們上面提到的檔案描述符,我們把這個值傳到下面要講到的read和write函式,read和write函式便能知道我們要讀/寫的是哪個檔案了。

在上面我們提到了o_creat方式要和第三個引數mode一起使用,現在我們來講解mode引數。mode引數主要是給檔案設定許可權的,在上面講到檔案許可權的時候我們知道檔案許可權分三個組,每個組下有三種許可權,所以mode引數一共有9個選值:

s_irusr: 所有者的讀許可權

s_iwusr: 所有者的寫許可權

s_ixusr: 所有者的執行許可權

s_irgrp: 所屬組的讀許可權

s_iwgrp: 所屬組的寫許可權

s_ixgrp: 所屬組的執行許可權

s_iroth: 其他使用者的讀許可權

s_iwoth: 其他使用者的寫許可權

s_ixoth: 其他使用者的執行許可權

這9個名字看上去很難記,其實是很有規律的:即 「s_i(r/w/x)」 + 「usr/grp/oth」拼出來的,一共9個,rwx分別就是讀/寫/執行的許可權,而usr/grp/oth分別是所有者(user)/所屬組(group)/其他使用者(other)。

close系統呼叫

#include 

int close(int fildes);

close系統呼叫很簡單,顧名思義,它會關閉檔案描述符fildes。如果呼叫成功則返回0,否則返回-1.

接下來我們來看乙個例子來展示open和close兩個系統呼叫,原始碼如下:

#include 

#include

#include

//o_wronly, o_creat在下面這個標頭檔案中定義

#include

int main()

這個程式就是在當前目錄下建立了乙個名為 「test.txt」的檔案,並讓所有者/所屬組/其他使用者都對該檔案具有讀寫執行的權力。用該原始碼生成可執行檔案並執行它,然後用 「ls -l」命令檢視 「test.txt」檔案,可能會和我們預想的不一致,在筆者的電腦上,結果如下:

我們注意到,在筆者的電腦上,test.txt檔案的許可權是rwxrwxr-x,為什麼其他使用者沒有寫許可權呢?這是因為筆者的linux的umask值是002(可以通過直接在終端輸入umask檢視umask值),它遮蔽了其他使用者的寫許可權。

原因是這樣的:我們的程式在建立這個檔案的時候試圖賦予的許可權是」rwxrwxrwx」,即所有使用者的讀寫執行許可權都賦予了,我們用1表示有許可權,0表示沒有許可權,則我們試圖給test.txt賦予的許可權是 「111 111 111」,而umask是002,第一位的0對應所有者,第二位的0對應所屬組,第三位的2對應其他使用者,所以umask的值是 「000 000 010」,把這個值按位取反,得到 「111 111 101」,這個值再與我們試圖賦予test.txt的許可權 「111 111 111」做按位與運算,得到 的」111 111 101」就是test.txt的最終許可權。

我們也可以簡單的理解, umask值 」 000 000 010」中哪一位是1,那麼檔案許可權中的哪一位就被遮蔽掉了。

讀者可以自行將umask的值改為其他的,再執行上面的程式,比較一下新生成的test.txt的許可權便能更好地理解umask了。

read系統呼叫

#include 

size_t read(int fildes, void *buf, size_t nbytes);

我們來逐一講解該函式的引數及返回值:

fildes: 要讀的檔案的檔案描述符

buf: 讀進來資料會放進buf

nbytes: 從fildes對應的檔案中要讀取的位元組數

返回值為size_t型別,代表實際讀入的位元組數。

write系統呼叫

#include 

size_t write(int fildes, const

void *buf, size_t nbytes);

下面是對write系統呼叫的引數及返回值的說明:

fildes: 要寫的檔案的檔案描述符

buf: 要寫的內容存在這裡,可以看作是資料緩衝區

nbytes: 要寫的位元組數,即把buf中的前nbytes個位元組寫到fildes對應的檔案中。

返回值是size_t型別,代表實際寫入的位元組數。

例子

在這個例子中,我們從標準輸入中讀入資料,並將其輸出到當前目錄下的data檔案中,如果data檔案不存在,則建立它。

原始碼如下:

#include 

#include

#include

#include

int main()

close(fildes);

return count;

}

用這段原始碼生成可執行檔案並執行,效果如下圖(圖中cat命令用於將檔案內容輸出到終端,可以方便的檢視檔案內容):

Linux入門(三)檔案許可權

linux系統中的每個檔案和目錄都有訪問許可許可權,用它來確定使用者對檔案和目錄進行訪問和操作的許可權。檔案或目錄的訪問許可權分為唯讀r,只寫w和可執行x三種。有三種不同型別的使用者可對檔案或目錄進行訪問 檔案所有者,同組使用者 其他使用者。所有者一般是檔案的建立者。用ls l命令顯示檔案或目錄的周...

Python 快速入門筆記(10) 檔案及目錄操作

python 中讀寫檔案可使用 io 模組 自動匯入 中的函式 open write read close 等 示例 f open test.txt w 以 寫 模式開啟,如果不存在則新建,如果已經存在會清空 f.write hello world 寫入文字 f.close 關閉檔案控制代碼 f o...

Linux入門篇(二) 檔案

這一系列的linux入門都是本人在 鳥哥的linux私房菜 的基礎上總結的基本內容,主要是記錄下自己的學習過程,也方便大家簡要的了解 linux distribution是ubuntu而不是書本上推薦的centos,建議裝雙系統,不要使用虛擬機器。在github上 linuxpractice 其他內...