一、文件同步:
1.在写入数据时内存与磁盘直接也有一个缓冲区,这种机制降低了磁盘的读写次数,提高了读写的效率
2.这种机制带来的后果就是磁盘中的数据与实际写入的数据不匹配,系统提供了三个函数可以让缓冲区中的数据立即写入到磁盘上
void sync(void);
功能:吧缓冲区中的数据立即同步到磁盘上
注意:并不会等待数据全部同步完,而是把缓冲区的数据全部加入到写入队列后,立即返回
int fsync(int fd);
功能:把指定文件的内容从缓冲区同步到磁盘上
注意:会等到全部写入到磁盘后才返回
int fdatasync(int fd);
功能:把指定文件的内容从缓冲区同步到磁盘上,只同步文件的内容不同步属性
注意:会等到全部写入到磁盘后才返回
二、文件属性
int stat(const char *path, struct stat *buf);
功能:根据文件的路径获取文件的属性
buf:存储文件属性的结构体指针,是一个输出型参数
struct stat {
dev_t st_dev; /* 设备ID */
ino_t st_ino; /* inode编号 */
mode_t st_mode; /* 文件的类型和权限*/
nlink_t st_nlink; /* 硬链接数 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
dev_t st_rdev; /* 特殊设备ID*/
off_t st_size; /* 总字节数 */
blksize_t st_blksize; /* IO块字节数 */
blkcnt_t st_blocks; /* 占用512字节的块数 */
time_t st_atime; /* 最后的访问时间 */
time_t st_mtime; /* 最后内容修改时间 */
time_t st_ctime; /* 最后状态修改时间 */
};
在POSIX中,有对于st_mode 有以下宏可以判断文件属于哪个类型:
S_ISREG(m) 判断是否为普通文件
S_ISDIR(m) 判断是否为目录文件
S_ISCHR(m) 判断是否为字符设备文件
S_ISBLK(m) 判断是否为块设备文件
S_ISFIFO(m) 判断是否为管道文件
S_ISLNK(m) 判断是否为软链接文件
S_ISSOCK(m) 判断是否为Socket文件
S_IFMT 0170000 获取文件类型的掩码
S_IFSOCK 0140000 socket文件
S_IFLNK 0120000 软连接文件
S_IFREG 0100000 普通文件
S_IFBLK 0060000 块设备文件
S_IFDIR 0040000 目录文件
S_IFCHR 0020000 字符设备文件
S_IFIFO 0010000 管道文件
S_ISUID 0004000 设置用户ID
S_ISGID 0002000 设置组ID
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 用户权限掩码
S_IRUSR 00400 读
S_IWUSR 00200 写
S_IXUSR 00100 执行
S_IRWXG 00070 组权限掩码
S_IRGRP 00040 读
S_IWGRP 00020 写
S_IXGRP 00010 执行
S_IRWXO 00007 其他用户权限掩码
S_IROTH 00004 读
S_IWOTH 00002 写
S_IXOTH 00001 执行
三、文件权限
int access(const char *pathname, int mode);
功能:测试当前用户对文件有哪些权限
pathname:文件路径
mode:想要测试的权限
F_OK 文件是否存在
R_OK 读权限
W_OK 写权限
X_OK 读写权限
返回值:存在则返回0,不存在返回-1
注意:如果文件不存在,测试RWX权限也会返回-1
int chmod(const char *path, mode_t mode);
功能:根据文件路径修改文件权限
path:文件路径
mode:由三位的八进制数组成的权限码
0644 普通文件
0755 执行文件
int fchmod(int fd, mode_t mode);
功能:根据文件描述符修改文件权限
权限屏蔽码:
如果我们不想让新创建的文件具有某项权限,可以通过设置权限屏蔽码进行过滤
通过命令 umask 查看当前终端的权限屏蔽码
通过命令 umask 0xxx 修改当前终端的权限屏蔽码
注意:权限屏蔽码对于chmod/fchmod函数和命令无效
mode_t umask(mode_t mask);
功能:设置当前进程的权限屏蔽码
mask:想要设置的权限屏蔽码
返回值:返回旧的权限屏蔽码
注意:该函数的设置只对当前进程有效,进程结束就失效了
四、修改文件大小
int truncate(const char *path, off_t length);
功能:根据文件路径修改文件的大小
length:想要修改成的字节数大小
int ftruncate(int fd, off_t length);
功能:根据文件描述符修改文件大小
练习1:实现一个函数,可以删除文件的[n,m)个字节
五、删除和重命名
int remove(const char *pathname);
功能:标准库中的删除文件函数
int unlink(const char*pathname);
功能:删除文件
int rename(const char *oldpath, const char *newpath);
功能:重命名文件
六、链接文件
Linux的文件系统会把分区分成两大部分
inode 信息块:默认128KB,记录了文件的权限、大小、所有者、修改时间等信息,以及对应的block的位置信息
block 块:记录了文件名和真正的数据信息
每个文件必须拥有唯一一个inode以及若干个block,读取文件时需要借助目录的block中记录的文件名找到该文件的inode号,通过inode读取到该文件的block
什么是软硬链接文件?
硬链接:硬链接文件没有字节的inode和block,只是在不同目录下复制了一份源文件的inode信息,可以通过inode访问到源文件的同一份block
软链接:软链接会建立自己的新的inode和block,而软链接文件的block中存储的是源文件的文件名和inode号
区别:
1.如果修改硬链接文件内容,源文件以及其他的硬链接内容也会被修改,软链接不会
2.当删除源文件,只是删除了源文件的inode,硬链接文件不受影响,但是软链接文件无法访问源文件
3.当硬链接数被删除到0时,此时文件才算被真正删除
4.软链接可以链接目录,硬链接不行
5.软链接可以跨文件系统,硬链接不行
int link(const char *oldpath,const char *newpath);
功能:创建硬链接文件
int symlink(const char *oldpath, const char *newpath);
功能:创建软链接文件
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
功能:读取软链接文件数据,而非链接目标文件数据,读取的其实是链接的路径
buf:是一个输出型参数,获取链接路径
bufsiz:获取的字节数
七:目录操作
int mkdir(const char *pathname,mode_t mode);
功能:创建目录
mode:目录的权限,注意必须要有执行权限否则无法进入
int rmdir(const char *pathname);
功能:删除空目录
int chdir(const char *path);
功能:进入某个目录,相当于cd命令
char *getcwd(char *buf, size_t size);
功能:获取当前工作目录,相当于pwd
DIR *opendir(const char *name);
功能:打开目录文件,返回一个目录流
name:选择要打开的目录
struct dirent *readdir(DIR *dirp);
功能:从目录流中读取一条记录
struct dirent {
ino_t d_ino; /* i节点号 */
off_t d_off; /* 下一条条目的偏移量*/
unsigned short d_reclen; /* 当前条目的长度 */
unsigned char d_type; /* 文件类型 */
DT_BLK 块设备文件
DT_CHR 字符设备文件
DT_DIR 目录文件
DT_FIFO 管道文件
DT_LNK 链接文件
DT_REG 普通文件
DT_SOCK Socket文件
DT_UNKNOWN 未知类型
char d_name[256]; /* 文件名 */
};
void seekdir(DIR *dirp, long loc);
功能:设置目录流的位置指针,用于随机读取
void rewinddir(DIR *dirp);
功能:设置目录流指针到开头
long telldir(DIR *dirp);
功能:获取当前目录流位置指针位置
实现 rm -rf 功能(建议备份虚拟机,重点关注 . .. 两个目录的删除)