姓名:姜思維? ? ? ? ?學(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ò)通信崔挖,當然也可用于實現(xiàn)本地(本機)
? ? 進程間的通信贸街。
2.7、符號連接(symbolic link:符號l):用以指向另外一個文件狸相,類似于windos界面下的快捷圖標薛匪。
所有的這些文件中,普通文件數(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操作時,塊的大惺迦馈(一般是512或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ù)
事先在當前路徑下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)须误、當普通用戶登陸成功后,會自動進入家目錄下的主目錄下(/home/xxxx)仇轻,? ? 主目錄路徑記
錄在了/etc/passwd中的用戶信息中京痢。以我的普通用戶linux為例,ls /home/ 看下篷店,結(jié)果如下:
linux? share? smb
家目錄/home/存放的是主目錄祭椰,每個主目錄就是每個注冊過的用戶的合法操作目錄,該普通用戶在自己的主目錄下?lián)碛袑λ形募僮鞯臋?quán)利疲陕。當前普通用戶是無法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 程序運行時醇疼,當前用戶是linux的話硕并,進程的實際ID就是linux,ID是我們登錄時從/etc/passwd中讀出的秧荆。即便是我們現(xiàn)在將當前用戶切換到了超級用戶或其它的普通用戶倔毙,但是之前運行進程的實際用戶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酿雪,當它去改寫/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荞驴,但是有的時候當可執(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
當我們在普通用戶執(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