边看边记录一些这一章的要点
1、本章主要围绕三个函数来进行讲述:stat() fstat() lstat(),他们都是对一些文件进行信息获取,查看这个文件。第一个函数是最普通的函数,第二个函数是针对打开的文件进行信息获取,第三个函数则对synbolic links有特殊的处理。
2、File Types:Unix系统中有很多的文件类型,分类如下:
· Regular file. 这是Unix系统之中最常见的一种文件类型,它用来存储某种格式的数据。不过是text文本还是二进制文本,这对于Unix内核来说都是一样的,它会把相应的操作交给这个文件的处理程序去处理,内核自己不去管这个事情。但是对于二进制可执行文件,他们使用统一的格式,使得内核可以知道从哪里去取这个程序的数据和文本。
· Directory file. 这是一种比较特殊的文件。它里面存储着其他文件的名字,它还存储着一些指针,这些指针指向与这些文件相关信息。任何拥有读权限的人都可以读一个Directory file,但是只有内核才能够直接对这种文件进行写操作。
· Block special file. 这种文件叫做“块”文件,磁盘就是一种这样的文件。这种文件提供buffered I/O access,并且每次访问的大小都是固定的(fixed-size units)。(A type of file providing buffered I/O access in fixed-size units to devices such as disk drives.)
· Character special file. 这种文件也是一种device。它提供unbuffered I/O,,并且访问单元的大小是可以变动的。(A type of file providing unbuffered I/O access in variable-sized units to devices)。 Unix中的所有devices,要么是 block speical files,要么是character special files。
· FIFO. 这种文件用来在进程之间进行通信。又叫做 named pipe.
· Socket. 这也是一种文件,用来在进程之间进行网络通信。这种文件还可以用来在一个host上进行非网络通信。
· Symbolic file. 这是一种指向其他文件的文件。比如/dev/fd中的文件。还有apue.2e中的那些fig3.1等等的文件。
3、在与file 相关的信息中,有st_mode 这个值(可以使用struct stat来表示一个file的相关信息),这个值中有set-user-ID 和 set-group-ID的位,当这个bit 被设定的时候,那么这个文件执行时的process的effective user ID(或者effective group ID)就会变成这个文件的user ID。passwd这个文件就是一个例子,它是一个程序,任何人都可以运行,但是运行的时候这个进程的权限就变成了superuser,可以修改这个用户的password file(/etc/passwd or /etc/shadow)。
这里需要搞清楚,file 和 process 是不同的。一个可执行文件在执行之前是file,当它执行的时候就是process。
每一个file 都有它的:owner(st_uid) 和
group owner(st_gid),
还有它的执行权限(r, w, x; for user, group, other)。
每一个process都有6个IDs和它联系在一起:real user ID real group ID
effective user ID effective group ID supplementary group ID
saved set-user-ID saved set-group-ID
默认情况下,process的effective xxx ID会和real xxx ID一样。不过,当设定了file中的st_mode中的set-xxxx-ID 标记位之后,这个file 执行时的process 的effective xxx ID就变了,变成和file的st_uid或者st_gid一样。
一个process的effective XXX ID和file的st_uid、st_gid的相互作用,导致了不同程序对不同文件访问权限的差异性。
4、st_mode中还有其他bit,表示一个文件的access permission.
5、关于各种文件的read write 以及 execute权限的说明:
· 如果我们想要打开一个文件,那么这个文件名中的所有directories都应该具有execute权限。比如我们想要open一个文件/usr/include/stdio.h,那么我们需要对/、/usr、/usr/include 这几个directories都要有execute权限,然后还有对stdio.h有相应的权限,才可以打开这个文件。
· 对于一个已经存在的文件,它的read权限决定我们是否可以“以读的方式”打开这个文件:the O_RDONLY and O_RDWR flags for the open function
· 对于一个已经存在的文件,它的write权限决定我们是否可以“以写的方式”打开这个文件:the O_WRONLY and O_RDWR flags for the open function
· We must have write permission for a file to specify the O_TRUNC flag in the open function
· 对于一个目录文件,我们具有write 和 execute权限,只有这样我们才能在这个目录中创建一个新的文件。
· 在我看来,创建和删除文件都只是针对目录来说,对于具体的文件则关联不大。如果我们想要删除一个文件,那么我们要有这个目录的write 和 execute权限,对于所要删除的那个文件,则不需要有read 或者 write权限。
· 对于一个regular file,如果我们想要使用exec() 函数执行这个文件,那么我们就要对这个文件具有execute权限。
6、我们使用open或者creat新创建一个文件,那么这个文件的user ID(owner) 和 group ID(group owner) 又分别是什么呢?
· The user ID of a new file is set to the effective user ID of the process
· Group ID 可以是effective group ID, 也可以是这个新创建的文件所在的目录所具有的group ID。一般用后者。
7、一般kernel进行access tests的时候,使用process的effective XXX ID。使用函数access()进行测试的时候,是用real XXX ID进行测试的。
8、file mode creation mask:每一个新创建的文件都有其权限,指定user、group、other用户是否可以对这个文件进行r、w、x操作。这些权限由umask进行设置。在umask中打开的选项,在新创建的文件中就要关闭。有umask()函数可以进行相应的操作。
比如一个文件的权限为-rw-r--r-- ,那么这个umask值就为0022。
9、对于一个文件:-rw-rw-rw- 1 cat cat 0 2011-05-01 09:12 foo
| | |__group owner(st_gid)
| |___owner(st_uid)
|___file access permission bits(- usr group other)
10、使用chmod() 函数改变一个文件的access permission bits的时候,运行这个函数的进程要有superuser的权限,或者它的effective user ID 和这个文件的st_uid一样(即这个进程拥有这个文件),这时候才能进行修改。
fchmod()函数是对一个已近打开的文件修改起permission bits.