4.2 返回文件的信息的函数
int stat(const char *restrict pathname, struct stat *restrict buf); 文件路径
int fstat(int filedes, struct stat *buf); 文件描述符,如果是符号链接,仍然获取文件信息。
int lstat(const char* restrict pathname, struct stat *restrict buf);如果是符号链接,获取链接本身信息。
4.3 普通文件,可以用红S_ISXXX()来判断。
目录文件,
块特殊文件,提供对设备(如磁盘)带缓冲的访问,每次以固定长度单位进行。
字符特殊文件,对设备不带缓冲的访问,每次访问长度可变。系统中的设备要么是字符,要么是块特殊文件。
FIFO,进程间通信,也叫命名管道。
套接字,进程间网络通信。或宿主机进程间非网络通信。Linux编译需要定义_GNU_SOURCE,使之包括S_ISSOCK宏(具体查看平台的stat.h文件)。
符号链接,指向另一个文件的文件类型。
4.4 与进程关联的ID有6个或更多。
real user ID,real group ID。(我们实际上是谁)登陆口令中的登陆项中的内容。
有效user ID,有效group ID,附加group ID。(用于文件访问权限检查)
保持的设置user ID,保持的设置group ID。(由exec函数保存)
4.5 每个文件有9个访问权限bit,分为三类。
chmod用来修改,u=owner,g=group,o=other。执行权限,read,write,execute。3*3 = 9
#打开任何文件,则对路径包含的所有目录都应有execute权限。
#read权限和O_RDONLY及ORDWR标志有关。
#write权限和O_WRONLY及O_RDWR标志有关。
#open函数指定O_TRUNC,必须有write权限。
#在目录中创建new file,必须对目录有write和execute权限。
#使用6个exec函数执行某个文件,比如有文件execute权限,文件必须是普通文件。
进程每次open,create,delete文件时,内核会测试权限。2个所有者ID是文件的性质,2个有效ID和附加组ID是进程的性质。
1)进程有效ID是0(root),则允许访问。
2)进程有效ID等于文件所有者ID(进程拥有此文件),如果匹配(想读,则对此用户的读位set为1,以此类推),则允许访问。
3)进程有效组ID或附加组ID等于文件组ID,如果匹配(同2),则允许访问。否则。。。
4)对于其他用户,适当的位被设置,则可访问。否则。。。
4.6 新建文件用户ID随创建它的进程。组ID,则可以随进程,也可以随所在的目录。
4.7 函数int access(const char *pathname, int mode);按real user ID和real group ID进行访问权限测试。
4.8 函数mode_t umask(mode_t cmask);为进程设置文件模式创建屏蔽字,并返回之前的值。
S_IRUSER(读), S_IWUSR(写), S_IXUSR(执行)将USR(user)改为--->GRP(group)或---->OTH(other)九种模式。<------9种文件访问权限位------------
设置哪个,哪个被屏蔽。可以按位或(|运算符)组合。
umask(0); 创建文件默认是-rw-rw-rw-
umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);屏蔽组的读写,其他的读写,所以创建文件是-rw-------.
好记的数字屏蔽位的值,用户读写执行 0400,0200,0100.
组读写执行 0040,0020,0010.
其他读写执行 0004,0002,0001.
4.9 改变现有文件访问权限
int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode); 修改前提,超级用户或运行代码的进程的有效用户ID==文件owner的ID(自己改自己被允许改的)
之前的9个加上新的S_ISUID(执行时设置user ID), S_ISGID(执行时设置组ID), S_ISVTX(保存正文<粘住位>)。
S_IRWXU,对用户(所有者)的三种操作的组合值。
S_IRWXG,对组的三种操作的组合值。 添加: stat.st_mode & ~S_IXXXX 移除:stat.st_mode | S_IXXXX
4.10 粘住位,程序第一次执行完,正文部分(机器指令部分)仍在交换区,下次可以快速装入内存区。现在很少使用。
4.11 更改文件的用户ID和组ID。
int chown(const char *pathname, uid_t owner, gid_t group);文件路径。
int fchown(int filedes, uid_t owner, gid_t group);文件描述符。
int lchown(const char *pathname, uid_t owner, gid_t group);修改链接文件的。
传入-1表示不变。注意系统的不同_POSIX_CHOWN-RESTRICTED.
4.12 文件长度由stat.st_size表示,只对普通文件,目录文件和符号链接有意义。
文件:可以为0。
目录:通常是某个数(16或512)的倍数。
符号链接:是文件名(可带路径)中的实际字节数。
如果文件中有空洞,复制后会被0代替填充。
4.13 截取一些数据以缩短文件。
int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);
如果offset小于文件长度,文件被截变短。如果大于文件,效果与系统有关。可能增加文件长度,也可能创建一个空洞。
4.14 关于i节点和指向i节点的目录项之间的区别。
i节点是固定长度的记录项,它包含有关文件的大部分信息。多个目录项可以指向同一个i节点。
每个i节点都有链接计数,链接计数减少至0,才可以删除文件。stat.st_nlink中包含链接数。这种链接称为硬链接。
符号链接symbolic link,这种链接,文件实际内容包含了符号链接指向的文件路径和名字。
不改变文件系统情况下文件改名,文件实际不移动,构造指向现有节点的新目录项,并解除与旧目录项的链接即可。
目录的链接数,至少有2个,命名它的目录项,该目录中的.项,如果有子目录,则子目录中的..项,此时则是3。
4.15 int link(const char* existingpath, const char *newpath);
创建指向现有文件的链接。原子操作。对于目录,只有root才可以。
int unlink(const char *pathname);
删除现有目录项,并将文件链接减1。如果出错,不对文件做任何更改。打开进程=0,链接=0,关闭文件时,文件内容被删除。
unlink这种性质用来确保程序崩溃时创建的临时文件不会留下来。先open或creat文件,然后调用unlink。
如果pathname是符号链接,会删除该链接,不会删除文件。
int remove(const char *pathname);
对于文件,与unlink相同。对于目录,与rmdir相同。
int rename(const char *oldname, const char *newname);
复杂的描述。。。。。查看书籍。
4.16 使用文件操作函数前,注意查看是否该函数会处理符号链接。
4.17 int symlink(const char *actualpath, const char *sympath); 创建指向actualpath的新目录项sympath。actualpath可以不存在。
ssize_t readlink(const char* restrict pathname, char *restrict buf, size_t bufsize);打开链接本身,读取链接中的名字。
4.18 文件有三个时间字段
st_atime, 最后access时间,进行read操作,用ls -u显示。
st_mtime, 最后modify时间,进行write操作,ls默认会显示。
st_ctime, i节点状态最后更改时间,chmod或chown,用ls -c显示。
系统并不保持对一个i节点最后一次访问时间,所以access和stat函数并不修改3个时间中的任意一个。
详细函数调用对时间的影响,查看表4-11。
4.19 int utime(const char *pathname, const struct utimbuf *times); 修改access和modify时间。如果times为NULL,则是当前时间。
4.20 int mkdir(const char *path, mode_t mode);对于目录至少要设置一个执行权限位,以允许访问目录中的文件名。
int rmdir(const char *pathname); 删除一个空目录。链接计数0,无其他进程打开,则释放空间。
有进程打开,则函数返回前删除最后一个链接及.和..项。目录中无法再创建文件。
4.21 读目录
DIR *opendir(const char *pathname);
struct dirent *readdir(DIR *dp);
void rewinddir(DIR *dp);
closedir(DIR *dp);
long telldir(DIR *dp);
void seekdir(DIR *dp, long loc);
4.22 每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点。
int chdir(const char *pathname);当前工作目录是进程的属性,它只影响调用chdir的进程本身。
int fchdir(int filedes);
char *getcwd(char *buf, size_t size); buffer size = path + null.
4.23 st_dev和st_rdev
4.24 看图片