文件存储
一个文件主要有两部分组成:dentry(目录项)和inode
inode本事是结构体,存储文件的属性信息,如权限、类型、大小、时间、用户、盘块位置......也叫做文件属性管理结构。大多书的inode都存储在磁盘上,少量常用、近期使用的inode会被缓存到内存中。
所谓的删除文件,就是删除inode,但是数据其实还是在硬盘上,当没有inode指向这个盘块以后,这个盘块之后会覆盖掉。
dentry本质也是一个结构体,里面有两个重要的成员是文件名、inode。而文件内容保存在磁盘盘块中。
stat/lstst函数
获取文件属性(从inode结构体中获取)
stat/lstat 函数:
int stat(const char *path, struct stat *buf);
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
参数:
path: 文件路径
buf:(传出参数) 存放文件属性。
返回值:
成功: 0
失败: -1 errno
获取文件大小: buf.st_size
获取文件类型: buf.st_mode
获取文件权限: buf.st_mode
符号穿透:stat会。lstat不会。
stat会拿到符号链接(软链接、硬链接)指向那个文件或目录的属性。不想被穿透的话就用lstat
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
struct stat buf;
int ret = stat("temp.txt", &buf);
if(ret == -1){
perror("stat error");
exit(1);
}
printf("st_ino = %ld\n", buf.st_ino);
printf("st_size = %ld\n", buf.st_size);
printf("st_nlink = %d\n", buf.st_nlink);
printf("st_uid = %d\n", buf.st_uid);
printf("st_gid = %d\n", buf.st_gid);
printf("st_mode = %x\n", buf.st_mode);
return 0;
}
truncate函数
截断文件长度成指定长度。常用来拓展文件大小,代替lseek。
int truncate(const char *path, off_t length); 成功 0 ;失败 1 设置 errno 为相应值
int ftruncate(int fd, off_t length);
link/unlink函数
硬链接数就是dentry数目
link就是用来创建硬链接数的
link可以用来实现mv命令
函数原型:
int link(const char *oldpath, const char *newpath)
#include <fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
用这个来实现mv,用oldpath来创建newpath,完事儿删除oldpath就行。
删除一个链接:
int unlink(const char *pathname)
unlink是删除一个文件的目录项dentry,使硬链接数-1
unlink函数的特征:清除文件时,如果文件的硬链接数到0了,没有dentry对应,但该文件仍不会马上被释放,要等到所有打开文件的进程关闭该文件,系统才会挑时间将该文件释放掉。
隐式回收
当进程结束运行时,所有进程打开的文件会被关闭,申请的内存空间会被释放。系统的这一特性称之为隐式回收系统资源。
要是没有在程序中关闭文件描述符,没有隐式回收的话,这个文件描述符会保留,多次出现这种情况会导致系统文件描述符耗尽。所以隐式回收会在程序结束时收回它打开的文件使用的文件描述符。
dup/dup2函数
用来做重定向,本质是复制文件描述符:
int dup(int oldfd); 文件描述符复制。
oldfd: 已有文件描述符
返回:新文件描述符。
int dup2(int oldfd, int newfd); 文件描述符复制。重定向。 new->old #include <unistd.h>
fcntl 函数实现 dup:
int fcntl(int fd, int cmd, ....)
cmd: F_DUPFD
当 fcntl 的第二个参数为 F _DUPFD 时, 它的作用是根据一个已有的文件描述符,复制
生成一个新的文件描述符。此时, fcntl 相当于 dup 和 dup 2 函数。
参3: 被占用的,返回最小可用的文件描述符。
未被占用的, 返回=该值的文件描述符。
目录操作函数
getcwd函数:获取当前进程工作目录(库函数)
char *getcwd(char *buf, size_t 成功: buf 中保存当前进程工作目录位置。失败返回 NULL 。
chdir函数: 改变当前进程的工作目录
int chdir(const char *path); 成功 0 ;失败 1 设置 errno 为相应值
opendir函数: 根据传入的目录名打开一个目录(库函数)
DIR *opendir(const char * name); 成功返回指向该目录结构体指针,失败返回 NULL
closedir函数: 关闭打开的目录
int closedir(DIR *dirp); 成功 0 ;失败 1 设置 errno 为相应值
readdir函数: 读取目录(库函数)
struct dirent *readdir(DIR *dirp); 成功返回 目录项 结构体指针;失败返回 NULL 设置 errno
为相应值
struct dirent {
i no_t d_ino; //inode 编号
off_t d_off;
unsigned short d_reclen; //文件名有效长度
unsi gned char d_type; //类型 (vim 打开看到的类似@*/ 等)
char d_name[256]; //文件名
}
其成员变量重点记忆两个 d_ino 、 d_name 。 实际应用中只使用到 d_name 。