(莱昂氏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组,分为三组:
(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的时候了,相信您已经储备了足够的知识,这个任务就交给您了。
博客地址:http://blog.csdn.net/cszhao1980
博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html