个人知识库 个人知识库
首页
关于
  • C语言
  • CPlusPlus
  • Linux
  • PHP
  • Nginx
  • MySQL
  • Redis
  • Docker
  • Kubernetes
  • SRS
阅读
常用工具
  • 分类
  • 标签
  • 归档
GitHub

Agnes001

坚持是一件很伟大的事业
首页
关于
  • C语言
  • CPlusPlus
  • Linux
  • PHP
  • Nginx
  • MySQL
  • Redis
  • Docker
  • Kubernetes
  • SRS
阅读
常用工具
  • 分类
  • 标签
  • 归档
GitHub
  • C语言

  • CPlusPlus

  • Lua技术栈

  • edoyun

  • 内存管理

  • 数据结构

  • 网络编程

  • Linux

    • Linux基础
    • 系统编程

      • 概述
      • 文件io
      • 文件系统
        • ext2文件系统
          • 文件系统详解
        • 文件操作
          • 获取文件属性
          • 测试指定文件是否存在/拥有某种权限。
          • 修改文件的访问权限
          • 文件屏蔽字
          • 截断文件长度成指定长度
          • 重定向
        • 函数stat、fstat、fstatat和lstat
        • 文件类型
      • 进程控制
      • 进程间通信
      • 信号
      • 线程
    • 基础命令
    • itcast
    • 文件io
    • gdb
    • Ubuntu安装eclipse
    • gcc安装
    • 系统编程
    • linux内核多线程
  • 池化技术

  • 操作系统

  • python

  • 编程技术
  • Linux
Agnes001
2022-05-09

文件系统

# ext2文件系统

  Boot Block | Block Group 0 | Block Group 1 | ... | Block Group n
_____________/                \___________________________________________
Super Block | GDT | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks

文件系统中存储的最小单位是块

  • 启动块(Boot Block) 1KB,由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用该块
  • 超级块(Supper Block) 描述整个分区的文件系统信息,例如块大小、文件系统版本号、上次mount时间等等,超级块在每个块组的开头都有一份拷贝
  • 块组描述符表(GDT, Group Descripter Table) 由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符,包括inode表哪里开始,数据块从哪里开始,空闲的inode和数据块还有多少个等。块组描述符在每个块组的开头也都有一份拷贝
  • 块位图(Block Bitmap) 用来描述整个块组中哪些块已经使用,哪些空闲
  • inode位图 标识一个inode是否空闲可用
  • inode表 文件类型(常规、目录、符号链接等),权限,文件大小,创建、修改、访问时间等信息,每个文件都有一个inode
  • 数据块
    • 常规文件 文件的数据存储在数据块中
    • 目录 该目录下所有文件名和目录名存储在数据块中(注意,文件名保存在它所在的目录的数据块中,其他信息都保存在该文件的inode中)
    • 符号链接 如果目标路径名比较短则直接保存在inode中,否则分配一个数据块保存
    • 设备文件、FIFO和socket等特殊文件 没有数据块,设备文件的主设备号和次设备号保存在inode中

stat/opendir/readdir/closedir

# 文件系统详解

#拷贝文件
dd if=/dev/zero of=fs count=256 bs=4K
#把/dev/zero文件开头的1M字节拷贝成文件名为fs的文件。256次,4K大小

#格式化文件
mke2fs fs
#现在fs的大小仍然是1MB,但不再是全0了,其中已经有了块组和描述信息。

#查看这个分区的信息
dumpe2fs fs

#挂载文件系统
mount -o loop fs /mnt
#-o loop告诉mount这是一个常规文件而不是一个块设备文件,mount会把它的数据块中的数据当作分区格式来解释
#文件系统格式化之后在根目录下自动生成三个子目录:. , ..和lost+found

umount /mnt

#用二进制查看工具查看这个文件系统的所有字节
od -tx1 -Ax fs

# 文件操作

# 获取文件属性

//参数1:文件名
//参数2:inode结构体指针 (传出参数)
int stat(const char *path, struct stat *buf); 	//成返回0;失败返回-1 设置errno为恰当值。	
//当命名的文件是一个符号链接,lstat返回该符号链接的有关信息,而不是该符号链接引用的文件的信息
int lstat(const char *path, struct stat *buf);  //成返回0;失败返回-1 设置errno为恰当值。
struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* inode number */
    mode_t    st_mode;        /* protection 文件类型,文件访问权限 */
        // S_ISREG(m)  	is it a regular file?
        // S_ISDIR(m)  	directory?
        // S_ISCHR(m)  	character device?
        // S_ISBLK(m)  	block device?
        // S_ISFIFO(m) 	FIFO (named pipe)?
        // S_ISLNK(m)  	symbolic link?  (Not in POSIX.1-1996.)
        // S_ISSOCK(m) 	socket?  
    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 512B blocks allocated */
    struct timespec st_atim;  /* time of last access */
    struct timespec st_mtim;  /* time of last modification */
    struct timespec st_ctim;  /* time of last status change */
};

穿透符号链接:stat:会;lstat:不会

# 测试指定文件是否存在/拥有某种权限。

//参数2:R_OK、W_OK、X_OK,通常使用access函数来测试某个文件是否存在。F_OK	
int access(const char *pathname,  int mode); //成功/具备该权限:0;失败/不具备 -1 设置errno为相应值。

# 修改文件的访问权限

int chmod(const char *path, mode_t mode);		///成功:0;失败:-1设置errno为相应值
int fchmod(int fd, mode_t mode);

# 文件屏蔽字

int umask(mode_t cmask);
umask -S //打印符号格式

# 截断文件长度成指定长度

int truncate(const char *path, off_t length);	//成功:0;失败:-1设置errno为相应值
int ftruncate(int fd, off_t length);

# 重定向

int dup(int oldfd); //成功:返回一个新文件描述符;失败:-1设置errno为相应值
int dup2(int oldfd, int newfd); 

wc -c file 计算文件中的字符数

# 函数stat、fstat、fstatat和lstat

文件相关的信息结构

//参数1:文件名
//参数2:inode结构体指针 (传出参数)
int stat(const char *path, struct stat *buf); 	//成返回0;失败返回-1 设置errno为恰当值。	
int fstat(int fd, struct stat* buf);
//当命名的文件是一个符号链接,lstat返回该符号链接的有关信息,而不是该符号链接引用的文件的信息
int lstat(const char *path, struct stat *buf);  //成返回0;失败返回-1 设置errno为恰当值。
struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* inode number */
    mode_t    st_mode;        /* protection 文件类型,文件访问权限 */
        // S_ISREG(m)  	is it a regular file?
        // S_ISDIR(m)  	directory?
        // S_ISCHR(m)  	character device?
        // S_ISBLK(m)  	block device?
        // S_ISFIFO(m) 	FIFO (named pipe)?
        // S_ISLNK(m)  	symbolic link?  (Not in POSIX.1-1996.)
        // S_ISSOCK(m) 	socket?  
    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 512B blocks allocated */
    struct timespec st_atim;  /* time of last access */
    struct timespec st_mtim;  /* time of last modification */
    struct timespec st_ctim;  /* time of last status change */
};
// 用上面3种即可,该方法一般不用
int fstatat(int fd, const char* pathname, struct stat* buf, int flag);

穿透符号链接:stat:会;lstat:不会

#include <unistd.h>
#include <sys/stat.h>

int main(int argc, char * argv[])
{
    struct stat sbuf;
    int ret = stat(argv[1], &sbuf);         //穿透符号链接
    if (ret < 0) {
        perror("stat");
        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);

    if (S_ISREG(sbuf.st_mode)) {
        printf("It's a regular file\n");
    } else if (S_ISDIR(sbuf.st_mode)) {
        printf("It's a directory\n");
    } else if (S_ISFIFO(sbuf.st_mode)) {
        printf("It's a fifo\n");
    } else if (S_ISLNK(sbuf.st_mode)) {
        printf("It's a symbolic link\n");
    }
    return 0;
}

# 文件类型

编辑此页
文件io
进程控制

← 文件io 进程控制 →

Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式