本文是笔者拜读《UNIX环境高级编程》第4章(文件和目录)的学习笔记。本文的主要内容包括chdir、设备特殊文件、第4章的小结和习题。文中不仅包含书中的知识点,也包括笔者的理解。
目录
函数chdir、fchdir和getcwd
每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点。进程调用chdir
和fchdir
更改当前工作目录。
在这两个函数中,分别用pathname
或打开文件描述符指定新的当前工作目录。该函数只影响调用chdir
的进程本身的当前工作目录,不影响其他进程。因此,shell
的当前工作目录不会随着程序(shell
的子进程)调用chdir
而改变。cd
命令是建在shell
中的。
chdir
跟随符号链接。
函数getcwd
提供了当前工作目录的完整绝对路径名。它从当前工作目录开始,先找到上一级目录,再读其目录项,找到目录项的i
节点编号与当前工作目录的相同,这样就找到了文件名。逐层上移,直到遇到根目录。
getcwd
有两个参数,一个是缓冲区地址buf
,一个是缓冲区长度size
(以字节为单位)。该缓冲区必须有足够的长度容纳路径名(包括'\0'
),否则返回出错(NULL
)。
设备特殊文件
st_dev
和st_rdev
。
每个文件系统所在的存储设备都由其主、次设备号表示。设备号所用的数据类型是dev_t
。主设备号标识设备驱动程序,次设备号标识特定的子设备。在同一磁盘驱动器上的各文件系统通常具有相同的主设备号,但次设备号不同。
通常使用两个宏:major
和minor
来访问主、次设备号。
系统中与每个文件名关联的st_dev
值是文件系统的设备号。文件系统包含了文件名以及与其对应的i
节点。
只有字符特殊文件和块特殊文件才有st_rdev
值。此值包含实际设备的设备号。
磁盘设备是块特殊文件,终端设备是字符特殊文件。
小结
本章围绕stat
函数,详细介绍了stat
结构中的成员。讨论了文件和目录在文件系统中是如何设计的以及如何使用文件系统命名空间。
习题
4.1
**题目:**用stat
函数替换程序中的lstat
函数,如若命令行参数之一是符号链接,会发生什么变化。
答:stat
跟随符号链接,如果该程序使用stat
获取文件信息,那文件/dev/cdrom
的类型就不是符号链接,而是该文件所引用的文件的类型。
4.2
**题目:**如果文件模式创建屏蔽字是777
,结果会怎么样?用shell
的umask
命令验证该结果:
答: 第一个7
表示对文件的所有者权限是可读、可写、可执行;第二个7
表示对文件的所有者所在的组的其他用户而言,权限是可读、可写、可执行;第一个7
表示对其他用户的权限是可读、可写、可执行。如果屏蔽了所有的这些权限,那任何用户对新创建的文件没有任何权限。
将umask设置为0777
,并新建一个文本文件:
新建文件的访问权限:
4.3
题目: 关闭一个你拥有文件的用户读权限,将导致拒绝你访问自己的文件,对此进行验证。
答:
创建一个能正常访问的文本文件:
更改访问权限,关闭用户读权限:
无法访问该文件:
4.4
题目: 创建文件foo
和bar
后,运行图中的程序,会发生什么?
答: 因为文件foo
和bar
已存在,所以create
函数错误返回。原文件不受任何影响,shell
的文件模式创建屏蔽字也不会因为其子进程调用了umask
函数而改变,
4.5
题目: 一个普通文件的大小可以为0
,而st_size
字段是为目录或符号链接定义的,那么目录和符号链接的长度能否为0
?
答: 不能。目录文件的长度不可能为0
,一个目录至少包含当前目录和上一级目录两个目录项。符号链接文件的长度是其所引用文件名的字符串大小,所以也不可能为0
。
4.6
题目: 编写一个类似cp
的程序,它复制包含空洞的文件,但不能将字节0
输出到文件中去。
答: 每次从源文件读一大段数据放到缓冲区里,然后从头到尾分析缓冲区,将非'\0'
的数据依次写入目标文件。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define N 1024
int TryWrite(int fd, char *buf, int len) {
int wNum = write(fd, buf, len);
if (wNum != len) {
perror("write error");
return -1;
}
return