嵌入式學(xué)習(xí)和發(fā)展(六):Linux_Api文件屬性

姓名:姜思維? ? ? ? ?學(xué)號:19020100333? ? ? ? 學(xué)院:電子工程學(xué)院

轉(zhuǎn)自:https://blog.csdn.net/weixin_41213648/article/details/88049688?spm=1001.2014.3001.5501

【嵌牛導(dǎo)讀】Linux_Api文件屬性

【嵌牛鼻子】Linux_Api? ? ? 文件屬性

【嵌牛提問】什么是Linux_Api的文件屬性?

【嵌牛正文】

1、引言

上一章通過學(xué)習(xí)文件io,知道了如何打開文件、對文件進行讀寫數(shù)據(jù)等的操作,那么我們這一章將換一個角度,專門圍繞文件屬性進行相關(guān)的討論。


2、文件類型

之前說過,在Linux下一切皆是文件。應(yīng)用層看待底層機制時,一切皆以文件的眼光看待,但是底層的機制之間的畢竟是有所不同,根據(jù)這些不同,文件也被分為如下幾種。

2.1、普通文件(regular file:符號-),其又分為如下兩種

a)、文本文件(ascci二進制文件)

b)、二進制文件(純二進制文件)

對linux內(nèi)核而言,這兩種文件并無區(qū)別,具體如何解釋均有應(yīng)用程序說了算。

2.2、目錄文件(director file:符號d):一種特殊的文件,用以包含其它文件的文件名字和指向這些

文件對應(yīng)i節(jié)點的節(jié)點編號,目錄允許讀,那么用戶就可以讀目錄文件,但是只有內(nèi)核可以寫目錄? ? 文件。

2.3、字符特殊文件(character special file:符號c):對應(yīng)字符設(shè)備。

2.4、塊特殊文件(block special file:符號b):對應(yīng)塊設(shè)備(如磁盤等)。

2.5、FIFO(符號p):有名管道文件,用于進程間通信,是一種純軟機制。

2.6、套接口(socket:符號s):用于實現(xiàn)跨機進程間的網(wǎng)絡(luò)通信,當(dāng)然也可用于實現(xiàn)本地(本機)

? ? 進程間的通信。

2.7、符號連接(symbolic link:符號l):用以指向另外一個文件,類似于windos界面下的快捷圖標(biāo)。

所有的這些文件中,普通文件數(shù)量最多,最常見,其次是目錄文件。


3、獲取文件屬性的函數(shù),stat、fstat、lstat

3.1、函數(shù)原型

#include <sys/types.h>

? ? #include <sys/stat.h>

? ? #include <unistd.h>

int stat(const char *path, struct stat *buf);

int fstat(int fd, struct stat *buf);

int lstat(const char *path, struct stat *buf);

3.2、函數(shù)功能

獲取文件的屬性信息,文件的屬性信息存在了磁盤上該文件對應(yīng)的inode(i結(jié)點)結(jié)點中,但

是open打開文件時又會從磁盤i節(jié)點中復(fù)制一份到內(nèi)存v節(jié)點中i節(jié)點結(jié)構(gòu)中,這三個函數(shù)還

是有一些區(qū)別的。

a)、stat:利用文件路徑名從磁盤上的i節(jié)點中讀取文件屬性到buf結(jié)構(gòu)體中。

b)、fstat:前提是文件已經(jīng)打開,利用文件描述符直接從v結(jié)點中的i結(jié)點結(jié)構(gòu)中讀出文件的屬

性,該函數(shù)直接從內(nèi)存中讀,但是stat直接從磁盤讀取。

c)、lstat:如果操作的文件是符號連接文件時,直接讀取的是符號連接文件的屬性信息,而stat

和fstat讀的是符號連接文件指向文件的屬性。所以我們說stat和fstat是一個符號跟隨的函? ? 數(shù),而lstat不是。有關(guān)符號跟隨的問題后面將再次講解。

3.4、參數(shù)說明

a)、const char *path:文件路徑名。

b)、int fd:文件描述符。

c)、struct stat *buf:存放讀出的文件屬性信息。

3.4.1、struct stat *buf結(jié)構(gòu)體說明

struct stat {

? ? dev_t? ? st_dev;? ? ? /* 塊設(shè)備號 */

? ? ino_t? ? st_ino;? ? ? ? /* inode結(jié)點號 */

? ? mode_t? ? st_mode;? ? /* 文件類型和文件權(quán)限*/

? ? nlink_t? st_nlink;? ? ? /* 鏈接數(shù) */

? ? uid_t? ? st_uid;? ? ? ? /* 文件所屬用戶ID*/

? ? gid_t? ? st_gid;? ? ? ? /* 文件所屬組ID */

? ? dev_t? ? st_rdev;? ? ? /* 字符設(shè)備ID */

? ? off_t? ? st_size;? ? ? ? /* 文件大小 */

blksize_t st_blksize;? ? /* 系統(tǒng)每次按塊Io操作時,塊的大?。ㄒ话闶?12或1024) */

blkcnt_t? st_blocks;? /* 塊的索引號 */

? ? time_t? ? st_atime;? /* 最后一次訪問時間,如read*/

time_t? ? st_mtime;? /* 最后一次修改時間 */

time_t? ? st_ctime;? /* 最后一次狀態(tài)修改的時間,如權(quán)限,所有者的修改 */

};

以上這些結(jié)構(gòu)體成員專門用來存放文件的相關(guān)屬性,囊括了我們講的7種文件,但是每種類型的文件都不會全用上這些成員項。比如說塊設(shè)備文件用了塊設(shè)備ID st_dev后,就不會使用字符設(shè)備ID st_rdev,又如文件的大小只有普通文件和目錄才有,其它文件是沒有的。

3.4.2、st_uid、st_gid

st_uid:文件所屬用戶ID

st_gid:文件所屬組ID

3.4.3、st_mode

st_mode其實是unsigned short(被typedef為了mode_t)的類型,包含了文件類型、設(shè)置位和文件權(quán)限。

3.4.4、ls -al看到的文件權(quán)限

7種文件決大部分屬性是相同的,但是每種不同的文件都有自己獨特的屬性,這些屬性都是stat函數(shù)從磁盤中讀到了struct stat結(jié)構(gòu)體中,ls -al的目的就是把struct stat結(jié)構(gòu)體描述共有屬性顯示出來,我們下面以普通文件為例進行說明。

我們執(zhí)行l(wèi)s -al main

3.5、返回值

調(diào)用成功,返回0,失敗返回-1,errno被設(shè)置。

3.6、測試用例

3.6.1、stat和lstat函數(shù)

事先在當(dāng)前路徑下touch一個file的普通文件,然后調(diào)用stat函數(shù)獲取文件屬性。


4、超級用戶(root用戶)和普通用戶

a)、root用戶對 / 下所有的文件有讀寫權(quán)限,而我們登陸的linux系統(tǒng)軟件的內(nèi)核代碼和一些重

要文件也放在了root下,所以我們并不主張用root權(quán)限操作,這可能會修改或刪除某些重要文

件導(dǎo)致系統(tǒng)崩潰。

b)、當(dāng)普通用戶登陸成功后,會自動進入家目錄下的主目錄下(/home/xxxx),? ? 主目錄路徑記

錄在了/etc/passwd中的用戶信息中。以我的普通用戶linux為例,ls /home/ 看下,結(jié)果如下:

linux? share? smb

家目錄/home/存放的是主目錄,每個主目錄就是每個注冊過的用戶的合法操作目錄,該普通用戶在自己的主目錄下?lián)碛袑λ形募僮鞯臋?quán)利。當(dāng)前普通用戶是無法cd進入其它普通用戶的主目錄,目的是防止你修改或刪除其它普通用戶私有的文件(添加組ID除外)。

普通用戶對/下的文件只有讀權(quán)限,而沒有寫權(quán)限,目的是為了防止普通用戶修改或刪除超級用戶的/目錄下的文件。

在linux用戶下試圖進入share用戶的主目錄share是無法成功的,這就防止了linux這個普通用戶修改或刪除普通用戶,同樣cd smb也是不行的。但是允許普通用戶cd /,只是對于普通用戶來說只能讀/下的文件,但是無法修改和刪除/目錄下文件。


5、進程與用戶ID

5.1、與一個進程相關(guān)的用戶ID

不管是執(zhí)行vi、ls、pwd等命令,還是./a.out執(zhí)行自己的可執(zhí)行文件,目的都是為了運行程序,那么與一個進程相關(guān)的用戶ID都有哪些呢?

1)、實際ID

?實際用戶ID

?實際組ID? ?

2)、有效ID

?有效用戶ID

?有效組ID? ?

3)、保存ID

?保存有效用戶ID

?保存有效組ID

5.2、三種類型ID的區(qū)別

5.2.1、實際ID? ?

一般情況下,如果未設(shè)置添加組ID的話,用戶自己跟自己一組,自己親自擔(dān)任組長,用戶ID就是自己的組ID。

vi 程序運行時,當(dāng)前用戶是linux的話,進程的實際ID就是linux,ID是我們登錄時從/etc/passwd中讀出的。即便是我們現(xiàn)在將當(dāng)前用戶切換到了超級用戶或其它的普通用戶,但是之前運行進程的實際用戶ID是不會發(fā)生改變的。

實際ID就是看,我們運行該程序的用戶的實際用戶ID和實際組ID,這個ID取自口令文件/etc/passwd。

5.2.2、有效ID? ?

1)、正常情況

有效組ID由exec函數(shù)(保存),正常在沒有對可執(zhí)行文件設(shè)置用戶ID和設(shè)置組ID的情況下,exec保存的有效ID等于實際ID。

2)、特殊情況(設(shè)置了用戶ID和設(shè)置組ID)

初始時exec函數(shù)保存有效ID等于實際ID

?如果對可執(zhí)行文件設(shè)置了用戶ID的話,exec函數(shù)保存的有效用戶ID就被修改為可執(zhí)行

文件的所屬用戶ID。

?如果對可執(zhí)行文件設(shè)置了組ID的話,exec函數(shù)中保存的有效組ID被修改為可執(zhí)行文件? ? 的所屬組ID。

?如果兩個設(shè)置位都被設(shè)置了的話,exec函數(shù)保存的有效用戶ID和有效組ID都會被修改。

3)、有效ID專門用于文件的權(quán)限檢查。

5.2.3、保存ID

運行程序時,將exec函數(shù)中保存的有效ID保存一個副本。

5.2.4、設(shè)置ID? ?

設(shè)置文件的用戶ID和設(shè)置文件的組ID,這在前面已經(jīng)提到過,目的就是想讓進程的實際ID和有效ID發(fā)生分離,因為正常情況下,有效ID就是實際ID的復(fù)制,但是設(shè)置了用戶ID和組ID后,exec函數(shù)保存的有效用戶ID和有效組ID就會被修改為文件的所屬用戶ID和所屬組ID。

密碼是用戶信息的一部分,它存在了口令文件中,但是用戶信息的重要性導(dǎo)致它是不可以被隨意更改的,所以它是一個屬于超級用戶的文件,所以在一般情況下,普通用戶是沒有辦法對其進行修改的,ls -al /etc/passwd,結(jié)果如下:

-rw-r--r--. 1 root root 2244 Jan 12? 2012 /etc/passwd

看出這個文件的所屬用戶和所屬組都是root,除root外的其它用戶對該文件只能讀,每個普通用戶都有修改自己用戶密碼的權(quán)利,我們常在普通用戶下用passwd這個命令進行修改,修改密碼就涉及/etc/passwd文件的修改,這就需要用到設(shè)置位。

passwd這個命令是一個可執(zhí)行文件,我們執(zhí)行這個命令就是為了運行這個程序。實際上shell腳本的作用就是為了邏輯控制shell命令的執(zhí)行,而每個shell命令其實就是一個可執(zhí)行文件,每個命令運行起來就是一個程序。

執(zhí)行命令ls /usr/bin/passwd? -al

-rwsr-xr-x. 1 root root 25980 Feb 22? 2012 /usr/bin/passwd

這個命令(可執(zhí)行文件),對于其它普通用戶來說只能執(zhí)行而不能讀寫,但是被做了用戶設(shè)置位的設(shè)置,所以執(zhí)行這個程序后,進程的有效用戶ID被設(shè)置為了root,當(dāng)它去改寫/etc/passwd文件時,這個文件的所屬用戶ID等于進程的有效用戶ID,passwd命令能修改/etc/passwd文件。


6、文件權(quán)限的檢查

前面多多少少已經(jīng)講到了文件權(quán)限的檢查,本小節(jié)將集中討論文件權(quán)限的檢查。

文件權(quán)限的檢查實際上分為兩部分:

?文件所屬用戶ID和所屬組ID檢查

?文件讀寫執(zhí)行權(quán)限檢查


7、新創(chuàng)建的的文件和目錄的所有權(quán)

7.1、對于新創(chuàng)建的文件和目錄所有權(quán)遵循如下規(guī)則

1)、新創(chuàng)建的文件(包括目錄在內(nèi))所屬用戶ID設(shè)置為進程的有效用戶ID,

2)、新文件的有效組ID按如下規(guī)則:

a)、如果該新文件所在目錄的所屬組ID未做設(shè)置,新文件的所屬組ID為進程的有效組ID

b)、如果該新文件所在目錄的所屬組ID做了設(shè)置,新文件的所屬組ID為該文件所在目錄的所屬組ID

7.2、舉例

1)、例1

正常情況下vi或touch file,mkidr kk,試想file和kk的所屬用戶ID和所屬組ID是多少呢?

2)、例2

a)、我們自己寫一個程序,調(diào)用open函數(shù)創(chuàng)建一個新文件file,然后我們對生成a.out所屬? ? 用戶改為root,并且做所屬用戶的設(shè)置位,新文件file的所屬用戶ID是什么

b)、將a.out所在目錄的所屬組ID修改為root,并作組設(shè)置位,那么這時新創(chuàng)建的文件file? ? 的所屬組ID又什么呢?

8、access函數(shù)

open函數(shù)打開已存在文件時會進行文件權(quán)限檢查,用的是進程的有效用戶ID和有效組ID,但是有的時候當(dāng)可執(zhí)行文件被做了設(shè)置為以后,往往進程的實際ID和有效ID不再相同,那么我們可能就像驗證下實際ID對于文件是否具有相應(yīng)的存取權(quán)限呢,access函數(shù)就能夠滿足這樣的功能。


8.1函數(shù)原型和所需頭文件

#include <unistd.h>

int access(const char *pathname, int mode);

8.2、函數(shù)功能:按照實際ID對文件進行相應(yīng)的存取權(quán)限測試

8.3、函數(shù)參數(shù)

?const char *pathname:文件路徑名

?int mode:文件擦開放式說明,mode與如下選擇

F_OK:測試文件是否存在

R_OK:測試文件是否允許讀

W_OK:測試文件是否允許寫

X_OK:測試文件是否允許執(zhí)行

以上多個選項可用|組合。

8.4、函數(shù)返回值:成功返回0,失敗返回-1,errno被設(shè)置

8.5、測試用例

1)、切換到root用戶,然后touch file,ls file -al

-rw-r--r--. 1 root root 0 Apr 30 14:46 file

2)、回到普通用戶,編譯下面的程序,得到可執(zhí)行文件a.out


9、umask函數(shù)

9.1函數(shù)原型和所需頭文件

#include <sys/types.h>

#include <sys/stat.h>

mode_t umask(mode_t mask);

9.2、函數(shù)功能:修改文件權(quán)限掩碼

9.3、函數(shù)參數(shù)

?mode_t mask:新的文件權(quán)限掩碼

9.4、函數(shù)返回值:此函數(shù)調(diào)用永遠都會成功返回,返回的是修改前的文件權(quán)限掩碼


10、chmod、fchmod函數(shù)

10.1函數(shù)原型和所需頭文件

#include <sys/stat.h>

int chmod(const char *path, mode_t mode);

int fchmod(int fd, mode_t mode);

10.2、函數(shù)功能:修改文件權(quán)限,一個是用文件路徑操作,一個是用文件描述符操作

10.3、函數(shù)參數(shù)

?const char *path:文件路徑

?int fd:文件描述符

10.4、函數(shù)返回值:調(diào)用成功返回0,失敗返回-1,errno被設(shè)置

10.5、測試用例:略

10.6、注意

1)、我們常見的chmod命令就是這兩函數(shù)的一個調(diào)用界面

2)、chmod命令、chmod函數(shù)和fchmod函數(shù)想要被合法執(zhí)行需滿足下面的條件

a)、超級用戶,無條件執(zhí)行

b)、如果在普通用戶下,進程的有效用戶ID等于文件所屬用戶ID

比如file文件,它的權(quán)限如下

-rw-rw-r--.? 1 root? linux? ? 0 Apr 30 21:33 file

當(dāng)我們在普通用戶執(zhí)行chmod函數(shù)或chmod命令時,因為進程的有效用戶ID是普通用戶,而不是root,所以在在普通用戶相面執(zhí)行chmod命令或函數(shù)失敗,報如下錯誤:

[? ? linux@bogon xiangtan_1404]$ chmod 777 file

報錯chmod: changing permissions of `file': Operation not permitted,權(quán)限受限

3)、只有超級用戶有權(quán)限調(diào)用chmod命令或函數(shù)設(shè)置或修改粘住位


11、粘住位

在早期的unix系統(tǒng)中,如果一個可執(zhí)行文件的粘住位S_ISVTX做了設(shè)置(粘住位st_mode中,前面有提到),那么這個程序第一次執(zhí)行結(jié)束后,這個程序的.text會被保存在交換區(qū),目的是為了下一次執(zhí)行改程序時,得到快速執(zhí)行,但是實際上現(xiàn)代unix已經(jīng)不再需要粘住位這個技術(shù)了,我們這里就不再講解。

12、chown,fchown,lchown函數(shù)

12.1函數(shù)原型和所需頭文件

#include <unistd.h>

int chown(const char *path, uid_t owner, gid_t group);

int fchown(int fd, uid_t owner, gid_t group);

int lchown(const char *path, uid_t owner, gid_t group);


12.2、函數(shù)功能:修改文件的所屬用戶ID或所屬組ID。

12.3、函數(shù)參數(shù)

?const char *path:文件路徑

?int fd:文件描述符

?uid_t owner:指定所屬用戶ID

?gid_t group指定所屬組ID

12.4、函數(shù)返回值:調(diào)用成功返回0,失敗返回-1,errno被設(shè)置。

12.5、測試用例:略

12.6、注意

1)、我們的chown命令是這兩個函數(shù)的調(diào)用界面。

2)、chown用文件路徑操作,fchown功能和chown一樣,但是它使用文件描述符操作。lchown也利用文件路徑操作,不過它可以操作符號連接文件,chown和fchown卻不能。

3)、只有超級用戶才能執(zhí)行chown命令或函數(shù)


————————————————

版權(quán)聲明:本文為CSDN博主「JiandaoStudio」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/weixin_41213648/article/details/88049688

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容