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 其他內...