(萊昂氏unix原始碼分析導讀-46)許可權、管道
by cszhao1980
1. 檔案與許可權控制
程序u結構中,身份相關的資訊有:
0420: char u_uid; /* effective user id */
0421: char u_gid; /* effective group id */
0422: char u_ruid; /* real user id */
0423: char u_rgid; /* real group id */
如果程序為超級使用者,則u_uid 為0。函式suser()執行檢查,如果為超級使用者則返回1。
而inode結構中,記錄了檔案的所屬關係:
5609: char i_uid;
5610: char i_gid;
如果程序的u_uid等於檔案inode的i_uid,則表示該程序擁有此檔案——超級使用者是例外,
超級使用者擁有任何檔案。函式owner()執行此項檢查,如果擁有此檔案,則返回檔案inode,
否則,返回NULL。
熟悉unix的同學應該都知道,unix檔案的許可權控制是在兩個維度上進行的:
(1) 檔案許可權有三種:Read、write和Exec
(2) 不同使用者所允許的許可權不同,具體來說:
1) 檔案owner(包括超級使用者);
2) 同group;
3) 其他。
檔案的許可權資訊記錄在(indoe的)i_mode變數的低9bit中,每3 bit
(1) 8~6:用於檔案owner;
(2) 5~3:用於同group;
(3) 2~0:用於其他使用者
在這3個 bit之中,最高bit為Read許可權標誌、中bit為write許可權標誌、低bit為Exec許可權標誌。
access()函式用於進行許可權檢查,萊昂有詳細的介紹,在此不再贅述。
2. 管道
管道是一種特殊的檔案,用於unix的程序間通訊。
管道均為“小”檔案,即小於4096個位元組,如下所示:
#define PIPSIZ 4096
sys call pipe()用於生成管道,從程式碼可以看到,管道最大的特點是它擁有兩個file
別用於read和write,正因如此ip->i_count也被初始化為2。該函式需要注意的是其對R0、R1的
設定——如前面所述,falloc()會隱含的設定R0。
首先,看一下管道寫函式writep(fp),其引數為file陣列指標,指向該管道的“寫”file entry:
(1) plock鎖定inode,因此,管道的讀、寫是互斥的,同一時間僅有一種操作可行;
(2) 檢查管道的i_count,如<2證明Read已關閉,則管道的“寫”功能也無意義,故error,併發訊號;
(3) 管道最大為PIPSIZ個位元組,在“寫”時需要注意:
i. ip->i_size1 == PIPSIZ,管道已寫“滿”,故睡眠;
ii. 7844 ~ 7847計算所能寫的byte數,和剩餘位元組數;
(4) 7850 ~ 7853:喚醒因“讀完”而等待的程序。
readp(fp)是管道讀函式,與寫函式的實現互相呼應,需要注意的是:
(1) 其引數為指向該管道的“寫”file entry的指標:
(2) 7772行表示,已經讀“完”了管道的內容——會清空管道;
除了這幾個函式之外,還有一些函式對管道(FPIPE)有特殊的處理,如rdwr、closef等,
由於其實現比較簡單,就請讀者自行檢視吧。
【思考題】:是解決EXEC sys call的時候了,相信您已經儲備了足夠的知識,這個任務就交給您了。