APUE第4章 文件和目录笔记

5 篇文章 0 订阅

1.#include<sys/types.h>
#include<sys/stat.h>
int stat(const char *pathname,struct stat *buf);//根据文件名取得文件的信息
int fstat(int fd,struct stat *buf);//根据文件描述符取得文件信息
int lstat(const char *pathname,struct stat *buf);//类似stat,但当文件是一个
链接文件时,取得链接文件的信息,而非链接引用的文件

2.struct stat {
              dev_t     st_dev;     /* ID of device containing file */
              ino_t     st_ino;     /* inode number */
              mode_t    st_mode;    /* protection */
              nlink_t   st_nlink;   /* number of hard links */
              uid_t     st_uid;     /* user ID of owner */
              gid_t     st_gid;     /* group ID of owner */
              dev_t     st_rdev;    /* device ID (if special file) */
              off_t     st_size;    /* total size, in bytes */
              blksize_t st_blksize; /* blocksize for filesystem I/O */
              blkcnt_t  st_blocks;  /* number of blocks allocated */
              time_t    st_atime;   /* time of last access */
              time_t    st_mtime;   /* time of last modification */
              time_t    st_ctime;   /* time of last status change */
          };

3.要进入一个目录必需要有可执行权限。

4.文件类型包括:普通文件(regular file)、目录文件(directory file)、块特殊文件(block special file)(典型用于磁盘)、字符特殊文件(character special file)(用以系统中某些类型的设备)、  FIFO(用于进程间通信)、套接字(socket)(用于网络通信)、符号链接(symbolic link)。文件类型信息保存在stat类型的st_mode字段中

 确定文件类型的宏(sys/stat.h):如S_ISREG(stat.st_mode)
  宏  文件类型
  S_ISREG() 普通文件
  S_ISDIR() 目录文件
  S_ISCHR() 字符特殊文件
  S_ISBLK() 块特殊文件
  S_ISFIFO() 管道或FIFO
  S_ISLNK() 符号链接
  S_ISSOCK() 套接字

S_ISDIR的定义#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR),即文件类型与屏蔽字S_IFMT逻辑与,再与对应的宏对比。

5.有效用户和有效组

一般实际用户和有效用户是相同的,实际组和有效组是相同的。有效用户和组是用来表示对文件或者目录所拥有的权限的。

看下passwd程序,注意用户执行位的s

ls -l /usr/bin/passwd
-rwsr-xr-x 1 root shadow 79336 May  4  2007 /usr/bin/passwd             

再看下passwd文件

ls -l /etc/passwd
-rw-r--r-- 1 root root 6890 Jul  3 09:25 /etc/passwd

修改passwd文件要有root权限才可以,但实际上我们任意用户都可以使用passwd程序修改passwd文件。这是因为我们在执行passwd程序时获得了root的权限,从而

passwd程序可以去修改passwd文件,我们之所以能取得root权限,就是因为passwd程序设置了有效用户位s,拥有可执行权限则为s,没有则为S。用户调用passwd程序修改passwd文件。

6.粘着位

看下tmp目录,注意红色

drwxrwxrwt  23 root root 1560 Aug  7 16:42 tmp

使用root用户在tmp目录内touch一个文件加上777权限

使用普通用户在tmp目录内删除刚才的那个文件,发现删除不了,这就是粘着位的作用。

如果对一个文件或者目录设置了粘住位,则只有对该目录具有写许可权的用户并且满足下列条件之一,才能删除或更名该目录下的文件:

· 拥有此文件。
· 拥有此目录。
· 是 超级用户
这么做就是防止用户删除别人的文件如果有可执行权限则为t,没有则为T。
7.设置有效用户位和粘着位
4为SUID
2为SGID
1为Sticky bit
这3位可以同时设置,如chmod 6777 tmp,这里的6就是4+2
8.设置用户ID位及组ID位都包含在stat的st_mode中,可以用S_ISUID和S_ISGID测试
9.每个文件有9个访问权限位,包含在stat.st_mode中
  st_mode屏蔽 意义
  S_IRUSR  用户-读
  S_IWUSR  用户-写
  S_IXUSR  用户-执行
  S_IRGRP  组-读
  S_IWGRP  组-写
  S_IXGRP  组-执行
  S_IROTH  其他-读
  S_IWOTH  其他-写
  S_IXOTH  其他-执行
对于目录的读权限和可执行权限的意义不相同。读允许我们读目录,获得在该目录中所有文件名的列表。
执行则允许我们进入该目录,同时PATH环境变量如果包含该路径,则shell可以在该目录下找到可执行文件。
对于一个文件的读决定我们能够打开该文件进行读操作。这对应于open函数的O_RDONLY和O_RDWR标志。
对于一个文件的写决定我们能够打开该文件进行写操作。这对应于open函数的O_WRONLY和O_RDWR标志。
在目录内想干嘛要对目录有可执行权限,对文件创建,删除要对目录有写权限。
在open函数中指定为O_TRUNC标志,必须对该文件具有写许可权。
10.进程在打开,创建,删除文件时都会进行
进程访问文件权限测试:
  (1) 若进程的有效用户ID是0,则允许访问。
  (2) 若进程的有效用户ID等于文件的所有者ID,若文件所有者相应的访问权限位被设置,则访问允许,否则拒绝。
  (3) 若进程的有效组ID或进程的附件组ID之一等于文件的组ID,若组相应的访问权限位被设置,则访问允许,否则失败。
  (4) 若其他用户相应的访问权限位被设置,则访问允许,否则拒绝。
11.新文件和目录的所有权:新文件的所有者ID设置为进程的有效用户ID,新文件的组ID二者选一:
 1>进程的有效组ID;2>它所在目录的组ID。
12.access函数:当 用open函数打开一个文件时内核进程的有效用户和有效用户组来测试权限。但有时程序仍想 用实际用户和实际用户组来测试,这就需要使用access函数。
#include <unistd.h>
 int access(const char *pathname, int mode);
 返回值:若成功则返回0,若出错则返回-1
 mode 说明
 R_OK 测试读成功
 W_OK 测试写成功
 X_OK 测试执行权限
 F_OK 测试文件是否存在
13.umask设置掩码
在创建一个文件或者目录时,默认为666权限,生成一个可执行文件时默认为777权限,然后使用掩码去处理, 如果原来的权限位为0,则还为0,为1的话则减去对应的掩码位
umask 27     // 注意这里的27是8进制,二进制即000010111
而666为110110110
 110110110
-000010111
 110100000
即640也就是-rw-r------权限
#include<sys/types.h>
#include<sys/stat.h>
mode_t umask(mode_t mask);//为进程设置文件方式创建屏蔽字,并返回以前的值。这是少数几个没有出错返回的函数中的一个。
其中,参数mask由9个常数S_IRUSER,S_IWUSR等逐位“或”构成的。
14.chmod和fchmod函数:更改指定文件的访问权限。
 #include <sys/stst.h>
 int chmod(const char *pathname, mode_t mode);
 int fchmod(int filedes, mode_t mode);
 返回值:若成功则返回0,若失败则返回-1;
 mode  说明
 S_ISUID  执行时设置用户ID
 S_ISGID  执行时设置组ID
 S_ISVTX  保存正文(黏住位)
 S_IRWXU  用户(所有者)读、写和执行
 S_IRUSR  用户(所有者)读
 S_IWUSR  用户(所有者)写
 S_IXUSR  用户(所有者)执行
 S_IRWXG  组读、写和执行
 S_IRGRP  组读
 S_IWGRP  组写
 S_IXGRP  组执行
 S_IRWXO  其他读、写和执行
 S_IROTH  其他读
 S_IWOTH  其他写
 S_IXOTH  其他执行
样例:
struct stat statbuf;
if(stat("foo",&statbuf)<0)          //先取出原来的状态
err_sys("stat error for foo");
if(chmod("foo",(statbuf.st_mode&~S_IXGRP)|S_ISGID)<0)//再设置
err_sys("chmod error for foo");
注意chmod更新的是文件最近一次被更改的时间,而ls -l列出的是最后修改文件内容的时间。
15.chown、fchown和lchown函数:更改文件的用户ID和组ID
 #include <unistd.h>
 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);
 返回值:成功返回0,出错返回-1;
16.文件截短:
 #include <unistd.h>
 int truncate(const char *pathname, off_t length);
 int truncate(int filedes, off_t length);
 返回值:成功返回0,出错返回-1;
 如果文件以前的长度大于length,则超过length以外的数据就不能再访问了;如果短于length,则效果与系统有关。
17.文件系统上的i结点包含了所有与文件有关的信息:文件类型,文件存取许可权位,文件长度和指向该文件所占用的数据块的指针,结点被引用数等等。
而目录项则包含了文件或者目录的名字,引用的结点号。一个目录项就代表了一个文件或者目录。
在不改变文件系统的情况下为一个文件更名时,该文件的实际内容并未移动,只需构造一个指向现存i节点的新目录项,并删除老的目录项。mv命令就
是这样的。
因为目录项中的i节点编号数指向同一个文件系统中的i节点,所以不能使一个目录项指向另一个文件系统的i节点。这就是为什么ln命令不能跨越文件系统。
一个空目录的连接数为2,一个是命名本身,一个是目录内的"."号。
18.创建连接的ln命令如果作用于目录,则链接文件类似目录,如果作用于文件,则链接文件类似于文件。
创建软链接不会增加节点引用数,硬链接才会,普通用户创建硬链接只能作用于文件。只有超级用户才能创建到目录的硬链接。删除文件时,首先检查文件被使用的进程数,其他才是文件的引用数,都为0才真正的删除。
link:创建一个新目录项;unlink:删除一个现有的目录项; remove:删除文件同unlink,删除目录同rmdir;
 #include <unistd.h>
 int link(const char *existingpath, const char *newpath);// 创建的是硬链接,不是软链接
 int unlink(const char *pathname );//删除文件时,如果文件正在被当前进程打开时,当进程结束时,内核会进行删除操作,即文件引用数减1,如果为0则删除。
 #include <stdio.h>
 int remove(const char *pathname);
 int rename(const char *oldname, const char *newname);
unlink函数是不跟随符号链接的
symlink:创建符号链接;readlin:读符号链接(而不是符号链接指向的文件)
 #include <unistd.h>
 int symlink(const char *actualpath, const char *sympath);//创建符号链接时,并不要求实际路径存在。
因为open函数是跟随符号链接的,所以读取符号链接本身时用readlink
 ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t bufsize);//读取符号链接本身的内容,在buf中读取的内容不包含null字符终止。
 返回值:成功返回读到的字节数,出错返回-1;
19.文件的时间
 字段  说明    例子  ls选项
 st_atime 文件数据的最后访问时间  read  -u
 st_mtime 文件数据的最后修改时间  write  默认
 st_ctime i节点状态的最后更改时间  chmod、chown -c
注意系统并不保存存取文件状态的时间,及stat,access函数并不更改上述时间的任意一个。
 
utime函数:更改一个文件的访问和最后修改时间,不能修改状态的最后更新时间,这是由系统自己设置的
 #include <utime.h>
 int utime(const char *pathname, const struct utimbuf *times)
 struct utimbuf{
  time_t actime;
  time_t modtime;
 }
 
20. mdidr和rmdir函数
 #include <sys/stat.h>
 int mkdir(const char *pathname, mode_t mode):创建一个空目录,权限参照文件的创建。
 int rmdir(const char *pathname):删除一个空目录(空目录只包含.和..这两项的目录)
21. 读目录
 #include <dirent.h>
 DIR *opendir(const char *pathname)
 struct dirent *readdir(DIR *dp)
 返回值:成功返回指针,失败返回NULL
 void rewinddir(DIR *dp)//应该循环调用此函数读取目录内容
样例:
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<dirent.h>
#include<stdio.h>
#ifndef NULL
#define NULL 0
#endif
#ifndef ERROR
#define ERROR 0
#define OK 1
#endif
typedef int Status;
Status ls(char *);
int main(int argc,char **argv)
{
	if(argc==1) 
	ls(".");
	//else
	while(--argc)
	{
		printf("%s\n",*++argv);
		ls(*argv);
	}
	return 0;
}
Status ls(char *dirname)
{
	DIR *p_dir;//目录项指针
	struct dirent *p_dirent;//
	if((p_dir=opendir(dirname))==NULL)//首先打开目录
	{
		fprintf(stderr,"---->can\'t open %s\n",dirname);
		return ERROR;
	}
	while((p_dirent=readdir(p_dir)))//循环读取目录
	{
		printf("%s\n",p_dirent->d_name);
	}
	closedir(p_dir);
	return OK;
}


 
 int closedir(DIR *dp)
 long telldir(DIR *dp)
 void seekdir(DIR *dp, long loc)
 struct dirent{
  ino_t d_ino;   /*i-node number*/
  char d_name[NAME_MAX+1]; /*null-terminated filename*/
 }
22.chdir、fchdir:改变进程的当前工作目录;getcwd:获得进程的当前工作目录的绝对路径。
 #include <unistd.h>
 int chdir(const char *pathname);
 int fchdir(int filedes);
 char *getcwd(char *buf, size_t size);
23.延迟写
io写文件操作是把内容写到缓冲区中,缓冲区满了后,则被排到输出队列,最后才写入文件。
void sync()函数只是把修改过的块的缓存排到输出队列中,就立即返回了。它并不等实际IO操作结束
int fsync(int field)函数则等待io操作结束。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值