UNIX 環(huán)境高級編程|文件和目錄
GitHub: https://github.com/storagezhang
Emai: debugzhang@163.com
本文為《UNIX 環(huán)境高級編程》第 4 章學習筆記
本章內容圍繞 stat 函數,詳細介紹了 stat 結構中的每一個成員。這使我們對 UNIX 文件和目錄的各個屬性都有所了解。
我們討論了文件和目錄在文件系統(tǒng)中是如何設計的以及如何使用文件系統(tǒng)命令空間。對文件和目錄的所有屬性以及對文件和目錄進行操作的所有函數的全面了解,對于 UNIX 編程是非常重要的。
4.2 函數 stat、fstat、fstatat 和 lstat
#include
功能:
stat:
返回與 pathname 有關的信息結構。
fstat:
獲得已在描述符 fd 上打開的文件的有關信息。
lstat:
lstat 函數類似于 stat,但是當命名的文件是一個符號鏈接時,lstat 返回該符號鏈接的有關信息,而不是由該符號鏈接引用的文件的信息。
fstatat:
為一個相對于當前打開目錄(由 fd 參數指向)的路徑名返回文件統(tǒng)計信息。
flag 參數控制著是否跟隨著一個符號鏈接:
當 AT_SYMLINK_NOFOLLOW 標志被設置時,fstatat 不會跟隨符號鏈接,而是返回符號鏈接本身的信息。
否則,在默認情況下,返回的是符號鏈接所指向的實際文件的信息。
如果 fd 參數的值是 AT_FDCWD,并且 pathname 參數是一個相對路徑名,fstatat 會計算相對于當前目錄的 pathname 參數。如果 pathname 是一個絕對路徑,fd 參數就會被忽略。
根據 flag 的取值,fstatat 的作用就跟 stat 或 lstat 一樣。
參數:
fd:打開的文件描述符
對于 fstat,該文件就是待查看信息的文件
對于 fstatat,該文件是并不是待查看信息的文件,待查看信息的文件是以該 fd 對于的目錄相對路徑定位的。
pathname:文件或目錄的名字
buf:存放信息結構的緩沖區(qū),函數用來填充由 buf 指向的結構
struct stat { mode_t st_mode; /* file type & mode (permissions) */ ino_t st_ino; /* i-node number (serial number) */ dev_t st_dev; /* device number (file system) */ dev_t st_redv; /* device number for special files */ nlink_t st_nlink; /* number of links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ off_t st_size; /* size in bytes, for regular files */ struct timespec st_atime; /* time of last access */ struct timespec st_mtime; /* time of last modification */ struct timespec st_ctime; /* time of last file status change */ blksize_t st_blksize; /* best I/O block size */ blkcnt_t st_blocks; /* number of disk blocks allocated */
flag
控制著 fstatat 函數是否跟隨著返回一個符號鏈接。
返回值:
若成功,返回 0。
若出錯,返回 -1。
4.3 文件類型
UNIX 系統(tǒng)的文件類型:
普通文件(regular file)
這是最常用的文件類型,這種文件包含了某種形式的數據。至于這種數據是文本還是二進制數據,對于 UNIX 內核而言并無區(qū)別。對普通文件內容的解釋由處理該文件的應用程序進行。
例外是二進制可執(zhí)行文件。為了執(zhí)行程序,內核必須理解其格式。所有二進制可執(zhí)行文件都遵循一種標準化的格式,這種格式使內核能夠確定程序文本和數據的加載位置。
目錄文件(directory file)
這種文件包含了其他文件的名字以及指向與這些文件有關信息的指針。對一個目錄文件具有讀權限的任一進程都可以讀該目錄的內容,但只有內核可以直接寫目錄文件。進程必須使用相應的函數才能更改目錄。
塊特殊文件(block special file)
這種類型的文件提供對設備(如磁盤)帶緩沖的訪問,每次訪問以固定長度為單位進行。
字符特殊文件(character special file)
這種類型的文件提供對設備不帶緩沖的訪問,每次訪問長度可變。系統(tǒng)中的所有設備要么是字符特殊文件,要么是塊特殊文件。
FIFO
這種類型的文件用于進程間通信,有事也稱為命名管道(named pipe)。
套接字(socket)
這種類型的文件用于進程間的網絡通信。套接字也可用于在一臺宿主機上進程之間的非網絡通信。
符號鏈接(symbolic link)
這種類型的文件指向另一個文件。
文件類型信息包含在 stat 結構的 st_mode 成員中。可以用下表中的宏(
POSIX.1 允許實現將進程間同學(IPC)對象(如消息隊列和信號量等)說明為文件。下表中的宏(
4.4 設置用戶 ID 和設置組 ID
與一個進程相關聯(lián)的 ID 有 6 個或更多:
實際用戶 ID 和實際組 ID 標識我們究竟是誰。
這兩個字段在登錄時取自口令文件中的登錄項。
通常,在一個登錄回話期間這些值并不改變,但是超級用戶進程有方法改變它們。
有效用戶 ID、有效組 ID 以及附屬組 ID 決定了我們的文件訪問權限。
保存的設置用戶 ID 和保存的設置組 ID 在執(zhí)行一個程序時包含了有效用戶 ID 和有效用戶組 ID 的副本。
通常,有效用戶 ID 等于實際用戶 ID,有效組 ID 等于實際組 ID。
每個文件有一個所有者和組所有者,所有者由 stat 結構中的 st_uid 指定,組所有者則由 st_gid 指定。
4.5 文件訪問權限
st_mode 值也包含了對文件的訪問權限位。當提及文件時,指的是前面所提到的任何類型的文件。
所有文件類型(目錄、字符特別文件等)都有訪問權限。
每個文件有 9 個訪問權限位(
我們用名字打開任一類型的文件時,對該名字中包含的每一個目錄,包括它可能隱含的當前工作目錄都應具有執(zhí)行權限。這就是為什么對于目錄,其執(zhí)行權限位常被稱為搜索位的原因。
對于一個文件的讀權限決定了我們是否能夠打開現有文件進行讀操作。
這與 open 函數的 O_RDONLY 和 O_RDWR 標志相關。
對于一個文件的寫權限決定了我們是否能夠打開現有文件進行寫操作。
這與 open 函數的 O_WRONLY 和 O_RDWR 標志相關。
為了在 open 函數中對一個文件指定 O_TRUNC 標志,必須對該文件具有寫權限。
為了在一個目錄中創(chuàng)建一個新文件,必須對該目錄具有寫權限和執(zhí)行權限。
為了刪除一個現有文件,必須對包含該文件的目錄具有寫權限和執(zhí)行權限。對該文件本身則不需要有讀、寫權限。
如果用 7 個 exec 函數中的任何一個執(zhí)行某個文件,都必須對該文件具有執(zhí)行權限。該文件還必須是一個普通文件。
進程每次打開、創(chuàng)建或刪除一個文件時,內核就進行文件訪問權限測試,而這種測試可能涉及文件的所有者(st_uid 和 st_gid)、進程的有效 ID(有效用戶 ID 和有效組 ID)以及進程的附屬組 ID(若支持的話)。兩個所有者 ID 是文件的性質,而兩個有效 ID 和附屬組 ID 則是進程的性質。
內核進行的測試具體如下:
若進程的有效用戶 ID 是 0(超級用戶),則允許訪問。這給予了超級用戶對整個文件系統(tǒng)進行處理的最充分的自由。
若進程的有效用戶 ID 等于文件的所有者 ID(也就是進程擁有此文件),那么如果所有者適當的訪問權限位被設置,則允許訪問;否則拒絕訪問。
適當的訪問權限位指的是:
若進程為讀而打開該文件,則用戶讀位應為 1;
若進程為寫而打開該文件,則用戶寫位應為 1;
若進程將執(zhí)行該文件,則用戶執(zhí)行位應為 1。
若進程的有效組 ID 或進程的附屬組 ID 之一等于文件的組 ID,那么如果組適當的訪問權限位被設置,則允許訪問;否則拒絕訪問。
若其他用戶適當的訪問權限位被設置,則允許訪問;否則拒絕訪問。
按順序執(zhí)行這 4 步:
如果進程擁有此文件(第 2 步),則按用戶訪問權限批準或拒絕該進程對文件的訪問,不查看組訪問權限。
如果進程不擁有該文件,但進程屬于某個適當的組,則按組訪問權限批準或拒絕該進程對文件的訪問,不查看其他用戶的訪問權限。
4.6 新文件和目錄的所有權
新文件的用戶 ID 設置為進程的有效用戶 ID。關于組 ID,POSIX.1 允許實現選擇下列之一作為新文件的組 ID:
新文件的組 ID 可以是進程的有效組 ID。
新文件的組 ID 可以是它所在目錄的組 ID。
4.7 函數 access 和 faccessat
當用 open 函數打開一個文件時,內核以進程的有效用戶 ID 和有效組 ID 為基礎執(zhí)行其訪問權限測試。
access 和 facessat 函數是按實際用戶 ID 和實際組 ID 進行訪問權限測試的。
#include
參數:
mode:指定要測試的模式
如果要測試文件是否已存在,則 mode 設為 F_OK。
否則,mode 設置為下列常量的按位或:
R_OK:測試讀權限
W_OK:測試寫權限
X_OK:測試執(zhí)行權限
fd:打開目錄文件的描述符,或者 AT_FDCWD
faccess 函數與 access 函數在下面兩種情況下是相同的:
pathname 參數為絕對路徑
fd 參數取值為 AT_FDCWD 而 pathname 參數為相對路徑
否則,faccessat 計算相對于打開目錄(由 fd 參數指向)的 pathname。
flag:用于改變 faccessat 的行為:
如果 flag 設置為 AT_EACCESS,訪問檢查用的是調用進程的有效用戶 ID 和有效用戶組 ID。
返回值:
若成功,返回 0;
若出錯,返回 -1。
4.8 函數 umask
umask 函數為進程設置文件模式創(chuàng)建屏蔽字,并返回之前的值(沒有出錯返回):
#include
參數:
cmask 是由 st_mode 屏蔽中的 9 個常量中的若干個按位“或”構成的。
返回值:
舊的文件模式創(chuàng)建屏蔽字
在文件模式創(chuàng)建屏蔽字中為 1 的位,在文件 mode 中的相應位一定被關閉。
更改進程的文件模式創(chuàng)建屏蔽字并不影響其父進程(常常是 shell)的屏蔽字。
Single UNIX Specification 要求 shell 應該支持符號形式的 umask 命令。與八進制格式不太,符號格式指定許可的權限而非拒絕的權限。
4.9 函數 chmod、fchmod 和 fchmodat
chmod、fchmod 和 fchmodat 這 3 個函數使我們可以更改現有文件的訪問權限:
#include
為了改變一個文件的權限位,進程的有效用戶 ID 必須等于文件的所有者 ID,或者該進程必須具有超級用戶權限。
區(qū)別:
chmod 函數在指定的文件上進行操作
fchmod 函數對已打開的文件進行操作
fchmodat 函數與 chmod 函數在下面兩種情況下是相同的:
pathname 參數為絕對路徑。
fd 參數取值為 AT_FDCWD 而 pathname 參數為相對路徑。
否則,fchmodat 計算相對于打開目錄(由 fd 參數指向)的 pathname。
參數:
mode:文件修改后的權限(取自
flag:用于改變 fchmodat 的行為
當設置了 AT_SYMLINK_NOFOLLOW 標志時,fchmodat 并不會跟隨符號鏈接。
返回值:
若成功,返回 0。
若出錯,返回 -1。
4.10 粘著位
粘著位(sticky bit)是指,如果一個可執(zhí)行程序文件的這一位被設置了,那么當該程序第一次被執(zhí)行,在其終止時,程序正文部分的一個副本仍被保存在交換區(qū)(程序的正文部分是機器指令)。這使得下次執(zhí)行該程序時能較快地將其裝載入內存。
現在較新的 UNIX 系統(tǒng)大多數都配置了虛擬存儲系統(tǒng)以及快速文件系統(tǒng),所有不再需要使用這種技術。
現今的系統(tǒng)擴展了粘著位的使用范圍,Single UNIX Specification 允許針對目錄設置粘著位。如果對一個目錄設置了粘著位,只有對該目錄具有寫權限并且滿足下列條件之一的用戶,才能刪除或重命名該目錄下的文件:
擁有此文件
擁有此目錄
是超級用戶
目錄 /tmp 和 /var/tmp 是設置粘著位的典型候選擇。
4.11 函數 chown、fchown、fchownat 和 lchown
下列函數可用于更改文件的用戶 ID 和組 ID。如果兩個參數 owner 或 group 中的任意一個是 -1,則對應的 ID 不變。
#include
區(qū)別:
在所引用的文件是符號鏈接時,lchown 和 fchownat(設置了 AT_SYMLINK_NOFOLLOW 標志)更改符號鏈接本身的所有者,而不是該符號鏈接所指向的文件的所有者。
fchown 函數改變 fd 參數指向的打開文件的所有者,既然它在一個已打開的文件上操作,就不能用于改變符號鏈接的所有者。
返回值:
若成功,返回 0。
若出錯,返回 -1。
4.12 文件長度
stat 結構成員 st_size 表示以字節(jié)為單位的文件的長度,此字段只對普通文件、目錄文件和符號鏈接有意義。
對于普通文件,其文件長度可以是 0,在開始讀這種文件時,將得到文件結束指示。
對于目錄,文件長度通常是一個數(如 16 或 512)的整數倍。
對于符號鏈接,文件長度是文件名中的實際字節(jié)數。
文件中的空洞
空洞是由所設置的偏移量超過文件尾端,并寫入了某些數據后造成的。
對于沒有寫過的字節(jié)位置,read 函數讀到的字節(jié)是 0。
如果使用實用程序(如 cat)復制文件,那么所有這些空洞都會被填滿,其中所有實際數據字節(jié)皆填寫為 0。
4.13 文件截斷
有時我們需要在文件尾端處截去一些數據以縮短文件。將一個文件的長度截斷為 0 是一個特例,在打開文件時使用 O_TRUNC 標志可以做到這一點。
為了截斷文件可以調用函數 truncate 和 furuncate:
#include
參數:
length:將一個現有文件長度截斷為 length。
如果該文件以前的長度大于 length,則超過 length 以外的數據就不再能訪問。
如果以前的長度小于 length,文家長度將增加,在以前的文件尾端和新的文件尾端之間的數據將讀作 0(也就是可能在文件中創(chuàng)建了一個空洞)。
返回值:
若成功,返回 0。
若出錯,返回 -1。
4.14 文件系統(tǒng)
我們可以把一個磁盤分成一個或多個分區(qū)。每個分區(qū)可以包含一個文件系統(tǒng)。
i 節(jié)點是固定長度的記錄項,它包含有關文件的大部分信息。
上圖中:
在圖中有兩個目錄項指向同一個 i 節(jié)點。每個 i 節(jié)點中都有一個鏈接計數,其值是指向該 i 節(jié)點的目錄項數。只有當鏈接計數減少至 0 時,才可刪除該文件(也就是可以釋放該文件占用的數據塊)。在 stat 結構中,鏈接技術包含在 st_nlink 成員中,其基本系統(tǒng)數據類型是 nlink_t,這種鏈接類型稱為硬鏈接。
另外一種鏈接類型稱為符號鏈接。符號鏈接文件的實際內容(在數據塊中)包含了該符號鏈接所指向的文件的名字。該 i 節(jié)點中的文件類型是 S_IFLNK,于是系統(tǒng)知道這是一個符號鏈接。
i 節(jié)點包含了文件有關的所有信息:文件類型、文件訪問權限位、文件長度和指向文件數據塊的指針等。stat 結構中的大多數信息都取自 i 節(jié)點。只有兩項重要數據存放在目錄項中:文件名和 i 節(jié)點編號。i 節(jié)點變化的數據類型是 ino_t。
因為目錄項中的 i 節(jié)點編號指向同一文件系統(tǒng)中的相應 i 節(jié)點,一個目錄項不能指向另一個文件系統(tǒng)的 i 節(jié)點。
當在不更換文件系統(tǒng)的情況下為一個文件重命名時,該文件的實際內容并未移動,只需構造一個指向現有 i 節(jié)點的新目錄項,并刪除老的目錄項,鏈接技術不會改變。
4.15 函數 link、linkat、unlink、unlinkat 和 remove
任何一個文件可以有多個目錄項指向其 i 節(jié)點。創(chuàng)建一個指向現有文件的鏈接的方法是使用 link 函數或 linkat 函數。
#include
參數:
existingpath:現有文件(新創(chuàng)建的鏈接指向它)
newpath:新創(chuàng)建的目錄項,引用現有文件 existingpath
如果 newpath 已經存在,則返回出錯。
值創(chuàng)建 newpath 中的最后一個分量,路徑中的其他部分應當已經存在。
現有文件通過 efd 和 existingpath 參數指定:
若 existingpath 是絕對路徑,則忽略 efd。
若 existingpath 是相對路徑,則
若 efd = AT_FDCWD,那么相應的路徑名就通過相對于當前目錄進行計算。
若 efd 是一個打開的目錄文件的文件描述符,則 existingpath 是相對于 efd 的目錄文件。
新的路徑名通過 nfd 和 newpath 參數指定:
若 newpath 是絕對路徑,則忽略 nfd。
若 newpath 是相對路徑,則
若 nfd = AT_FDCWD,那么相應的路徑名就通過相對于當前目錄進行計算。
若 nfd 是一個打開的目錄文件的文件描述符,則 newpath 是相對于 nfd 的目錄文件。
flag:控制 linkat 函數是創(chuàng)建指向現有符號鏈接的鏈接還是創(chuàng)建指向現有符號鏈接所指向的文件的鏈接。
如果 flag = AT_SYMLINK_FOLLOW,就創(chuàng)建指向符號鏈接目標的鏈接。
如果這個標志被清除了,就創(chuàng)建指向符號鏈接本身的鏈接。
返回值:
若成功,返回 0。
若出錯,返回 -1。
創(chuàng)建新目錄項和增加鏈接計數應當是一個原子操作。
為了刪除一個現有的目錄項,可以調用 unlink 函數。
#include
參數:
flag:使調用進程可以改變 unlinkat 函數的默認行為。
當 AT_REMOVEDIR 標志被設置時,unlinkat 函數可以類似于 rmdir 一樣刪除目錄。
如果這個標志被清除,unlinkat 與 unlink 執(zhí)行同樣的操作。
pathname:如果 pathname 是符號鏈接,那么 unlink 刪除該符號鏈接,而不是刪除由該鏈接所引用的文件。給出符號鏈接名的情況下,沒有一個函數能刪除由該鏈接所引用的文件。
返回值:
若成功,返回 0。
若出錯,返回 -1。
這兩個函數刪除目錄項,并將 pathname 所引用文件的鏈接計數減 1.如果對該文件還有其他鏈接,則仍可通過其他鏈接訪問該文件的數據。如果出錯,則不對該文件做任何修改。
關閉一個文件時,內核首先檢查打開該文件的進程個數;如果這個計數達到 0,內核再去檢查其鏈接計數;如果計數也是 0,那么就刪除該文件的內容。
也可以用 remove 函數解出對一個文件或目錄的鏈接:
對于文件,remove 的功能與 unlink 相同。
對于目錄,remove 的功能與 rmdir 相同。
#include
4.16 函數 rename 和 renameat
文件或目錄可以用 rename 函數或者 renameat 函數進行重命名。
#include
參數:
如果 oldname 指的是一個文件,那么為該文件或符號鏈接重命名。
如果 newname 已存在:
如果它引用一個目錄,報錯。
如果它不是一個目錄,則先將該目錄項刪除然后再完成重命名。
對包含 oldname 的目錄以及包含 newname 的目錄,調用進程必須具有寫權限,因為將更改這兩個目錄。
如果 oldname 指的是一個目錄,那么為該目錄重命名。
如果 newname 已存在,則它必須引用一個目錄,而且改名了應當是空目錄(空目錄指的是該目錄中只有 . 和 … 項),先將 newname 刪除,然后完成重命名。
newname 不能包含 oldname 作為其路徑前綴。
如果 oldname 或 newname 引用符號鏈接,則處理的是符號鏈接本身,而不是它所引用的文件。
不能對 . 和 … 重命名。
如果 oldname 和 newname 引用同樣文件,則函數不做任何更改而成功返回。
返回值:
若成功,返回 0。
若出錯,返回 -1。
4.17 符號鏈接
符號鏈接是對一個文件的間接指針。
硬鏈接直接指向文件的 i 節(jié)點。
引入符號鏈接的原因是為了避開硬鏈接的一些限制:
硬鏈接通常要求鏈接和文件位于同一文件系統(tǒng)中。
只有超級用戶才能創(chuàng)建指向目錄的硬鏈接(在底層文件系統(tǒng)支持的情況下)。
對符號鏈接以及它指向何種對象并無任何文件系統(tǒng)限制,任何用戶都可以創(chuàng)建指向目錄的符號鏈接。符號鏈接一般用于將一個文件或整個目錄結構移到系統(tǒng)中另一個位置。
4.18 創(chuàng)建和讀取符號鏈接
可以用 symlink 或 symlinkat 函數創(chuàng)建一個符號鏈接。
#include
返回值:
若成功,返回 0。
若出錯,返回 -1。
在創(chuàng)建符號鏈接 sympath 時,并不要求 actualpath 已經存在,并且,sympath 和 actualpath 并不需要位于同一文件系統(tǒng)中。
因為 open 函數跟隨符號鏈接,所有需要有一種方法打開該鏈接本身,并讀該鏈接中的名字。readlink 和 readlinkat 函數提供了這種功能。
#include
返回值:
若成功,返回讀取的字節(jié)數。
若出錯,返回 -1。
兩個函數組合了 open、read 和 close 的所有操作。如果函數執(zhí)行,則返回讀入 buf 的字節(jié)數。在 buf 中返回的符號鏈接的內容不以 null 字節(jié)終止。
4.19 文件的時間
對每個文件維護 3 個時間字段,它們的意義如下:
4.20 函數 futimens、utimensat 和 utimes
一個文件的訪問和修改時間可以用以下幾個函數更改。futimens 和 utimensat 函數可以指定納秒級精度的時間戳,用到的數據結構是與 stat 函數族相同的 timespec 結構。
#include
參數:
times:
數組的第一個元素包含訪問時間,第二個元素包含修改時間。
這兩個時間值是日歷時間,不足秒的部分用納秒表示。
執(zhí)行這些函數所要求的優(yōu)先權取決于 times 參數的值。
時間戳可以按下列 4 種方式之一進行指定:
如果 times 參數是一個空指針,則訪問時間和修改時間兩者都設置為當前時間。
如果 times 參數是指向兩個 timespec 結構的數組:
任一數組元素的 tv_nsec 字段的值為 UTIME_NOW,相應的時間戳就設置為當前時間,忽略相應的 tv_sec 字段。進程的有效用戶 ID 必須等于該文件的所有者 ID;進程對該文件必須具有寫權限,或者進程是一個超級用戶進程。
任一數組元素的 tv_nsec 字段的值為 UTIME_OMIT,相應的時間戳保持不變,忽略相應的 tv_sec 字段。如果兩個 tv_nsec 字段的值都為 UTIME_OMIT,就不執(zhí)行任何的權限檢查。
任一數組元素的 tv_nsec 字段的值為既不是 UTIME_NOW 也不是 UTIME_OMIT,相應的時間戳設置為相應的 tv_sec 和 tv_nsec 字段的值。進程的有效用戶 ID 必須等于該文件的所有者 ID,或者進程必須是一個超級用戶進程。對文件只具有寫權限是不夠的。
flag:進一步修改默認行為
如果設置了 AT_SYMLINK_NOFOLLOW 標志,則符號鏈接本身的時間就會被修改(如果路徑名指向符號鏈接)。
默認的行為是跟隨符號鏈接,并把文件的時間改成符號鏈接的時間。
返回值:
若成功,返回 0。
若出錯,返回 -1。
futimens 函數需要打開文件來更改它的時間,utimensat 函數提供了一種使用文件名更改文件時間的方法。
futimens 和 utimensat 函數都包含在 POSIX.1 中。
utimes 包含在 Single UNIX Specification 的 XSI 擴展選項中:
#include
4.21 函數 mkdir、mkdirat 和 rmdir
用 mkdir 和 mkdirat 函數創(chuàng)建目錄,用 rmdir 函數刪除目錄:
#include
返回值:
若成功,返回 0。
若出錯,返回 -1。
用 rmdir 函數可以刪除一個空目錄,空目錄是只包含 . 和 … 這兩項的目錄:
#include
返回值:
若成功,返回 0。
若出錯,返回 -1。
如果調用此函數使目錄的鏈接計數成為 0,并且也沒有其他進程打開此目錄,則釋放由此目錄占用的空間。
如果在鏈接計數達到 0 時,有一個或多個進程打開此目錄,則在此函數返回前刪除最后一個鏈接及 . 和 … 項。另外,在此目錄中不能再創(chuàng)建新文件。但是在最后一個進程關閉它之前并不釋放此目錄。
4.22 讀目錄
對某個目錄具有訪問權限的任一用戶都可以讀該目錄,但是,為了防止文件系統(tǒng)產生混亂,只有內核才能寫目錄。一個目錄的寫權限位和執(zhí)行權限位決定了在該目錄中能否創(chuàng)建新文件以及刪除文件,它們并不代表能否寫目錄本身。
#include
4.23 函數 chdir、fchidr 和 getcwd
進程調用 chdir 或 fchdir 函數可以更改當前工作目錄:
#include
返回值:
若成功,返回 0。
若出錯,返回 -1。
在這兩個函數中,分別用 pathname 或打開文件描述符來指定新的當前工作目錄。
進程調用 getcwd 獲取當前工作目錄的絕對路徑名:
#include
參數:
buf:緩沖區(qū)地址
size:緩沖區(qū)長度(以字節(jié)為單位)
容納絕對路徑名再加上一個終止 null 字節(jié),否則返回出錯。
返回值:
若成功,返回 buf。
若出錯,返回 NULL。
4.24 設備特殊文件
st_dev 存的是文件本身存儲設備的主、次設備號,也就是硬盤的主、次設備號。
st_rdev 存的是針對驅動的字符設備和塊設備文件的主、次設備號。
每個文件系統(tǒng)所在的存儲設備都由其主、次設備號表示。
設備號所用的數據類型是基本系統(tǒng)數據類型 dev_t。
主設備號標識設備驅動程序,有時編碼為與其通信的外設板。
次設備號標識特定的子設備。
通常可以使用兩個宏:major 和 minor 來訪問主、次設備號,大多數實現都定義這兩個宏,這就意味著我們無需關心這兩個數是如何存放在 dev_t 對象中的。
系統(tǒng)中與每個文件名關聯(lián)的 st_dev 值是文件系統(tǒng)的設備號,該文件系統(tǒng)包含了這一文件名以及與其對應的 i 節(jié)點。
只有字符特殊文件和塊特殊文件才有 st_rdev 值,此值包含實際設備的設備號。
4.25 文件訪問權限位小結
Linux Unix
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現本站中有涉嫌抄襲或描述失實的內容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。