Linux文件管理

文件及文件系统的引入 #

信息存储问题及要求

信息存储解决方案

ls 命令及文件类型

ls -l hello.c
   -rw-rw-r--  1 zgs zgs      561 Aug 24 07:31 hello.c

硬链接和软链接文件共享

lrwxrwxrwx 1 zhaigaoshou2018 zhaigaoshou2018 12 Nov  6 05:49 DataFileRLJ -> DataFile.txt
-rw-rw-r--  2 zhaigaoshou2018 zhaigaoshou2018   15 Nov  6 05:47 DataFile.txt
-rw-rw-r--  2 zhaigaoshou2018 zhaigaoshou2018   15 Nov  6 05:47 DataFileYLJ

文件基本操作与文件系统 #

用户与外设间接口

文件系统的系统解读

文件系统层次模型

磁盘、分区和文件系统

Unix/Linux 文件系统体系结构

UNIX 文件系统概述

文件描述符表与文件表

文件物理结构类型 #

文件的逻辑结构和物理结构

文件物理结构——连续文件

文件的结构组成

混合索引文件结构与寻址方式

混合分配方式 (UNIX 系统)

UNIX 文件操作地址转换过程

索引结点管理

UNIX 文件卷组织结构

假设盘块大小为1KB,索引结点占64字节,则讲索引结
点应位于的物理盘块号为:
i*64B/1KB + 2 = [i/16](向下取整) + 2

虚拟文件系统 #

Linux VFS

Linux VFS 实现机制

面向对象的框架

Linux VFS 主要对象类型

目录管理及文件共享与保护 #

目录文件由对应目录下所有文件的目录项组成

文件控制块 = 目录项(文件名 +i 结点编号)+ i-node

特殊目录及路径名

目录管理

文件共享 - 绕弯路法

基于基本文件目录实现文件共享 ext2

文件保护

访问矩阵的简化策略

文件内存映像及系统实现 #

UNIX/Linux 文件卷组织结构 #

UNIX/Linux 文件系统数据结构 #

UNIX 超级块结构 filsys

struct filsys
{
 int s-isize;		 //inode区占用盘块数
 int s-fsize;		 //磁盘块数
 int s-nfree;		 //直接管理的一般存储盘块空闲块数
 int s-free[100];		 //空闲盘块索引表暨空闲盘块号栈
 int s-ninode;		 //直接管理的空闲索引结点inode数
 int s-inode[100];	 //空闲索引结点inode的索引表暨空闲索引结点号栈
 char s-flock;		 //空闲盘块号栈的上锁标志
 char s-ilock;		 //空闲索引结点号栈的上锁标志
 char sfmod; 		//本信息块已被修改标志
 char s-ronly;		 //本文件系统只能读出的标志
 int s-time[2];		 //最近一次更新时间
 int pad[50];
}; 

Linux 文件系统信息查看命令 #

mount

文件系统信息查看命令2-2B——考试着重考计算

8192*256/4096
= 2^13 * 2^8 / 2^12
= 2^9
= 512
盘块组数:
12M/32768
= 12*2^20 / 2^15
= 12*2^5
= 384

Linux 目录项及索引结点结构 #

Linux 进程控制块与文件打开表 #

进程控制块【struct task_struct】

文件打开表【struct files_struct】

文件描述符表【 struct fd_struct】

文件控制块【 struct file】

//zgs/linux-4.8.8/include/linux/sched.h
//进程控制块

struct task_struct {
	volatile long state;
	atomic_t usage;
	unsigned int flags;
	unsigned int ptrace;
……
	struct fs_struct *fs;
	struct files_struct *files;
……
};
//zgs/linux-4.8.8/include/linux/fdtable.h
//每进程文件打开表

struct files_struct {
……
	struct fdtable __rcu *fdt;
	struct fdtable fdtab;
……
	int next_fd;
	unsigned long close_on_exec_init[1];
	unsigned long open_fds_init[1];	
	unsigned long full_fds_bits_init[1];
	struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};
//zgs/linux-4.8.8/include/linux/fdtable.h
//文件描述符表

struct fdtable {
	unsigned int max_fds;
	struct file __rcu **fd; 
	unsigned long *close_on_exec;
	unsigned long *open_fds;
	unsigned long *full_fds_bits;
	struct rcu_head rcu;
};
//zgs/linux-4.8.8/include/linux/fs.h //文件控制块结构
struct file {
	union {
		struct llist_node	fu_llist;
		struct rcu_head 	fu_rcuhead;
	} f_u;
	struct path		f_path;
	struct inode		*f_inode;
	const struct file_operations	*f_op;
 	spinlock_t		f_lock;
	atomic_long_t		f_count;
	unsigned int 		f_flags;
	fmode_t			f_mode;
	struct mutex		f_pos_lock;
	loff_t			f_pos;
	struct fown_struct	f_owner;
	const struct cred	*f_cred;
	struct file_ra_state	f_ra;
	u64			f_version;
#ifdef CONFIG_SECURITY
	void			*f_security;
#endif
……
	struct address_space	*f_mapping;
} __attribute__((aligned(4)));

Linux 虚拟文件系统实现概要 #

基于 C 的面向对象实现方法

Linux 文件操作相关系统调用 #

文件创建系统调用例程

creatProg.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
 int fd = creat("FileCreated.txt", 0777);
 return 0;
}

//文件FileCreated.txt存取权限:-rwxrwxr-x
// <= 0777 & ~0002

creat 系统调用基本用法

文件实际的存取权限 = (~mask & mode)

进程的真实/有效用户标识符

struct task_struct {
 ……
 const struct cred __rcu *real_cred;
 const struct cred __rcu *cred;
 …… 
 struct nsproxy *nsproxy;
 ……
};
struct cred {
 ......
 kuid_t	uid;
 kgid_t	gid;
 kuid_t	suid;
 kgid_t	sgid;
 kuid_t	euid;
 kgid_t	egid;
 kuid_t	fsuid;
 kgid_t	fsgid;
 ......
 struct user_struct *user;
 struct user_namespace *user_ns;  
 ......
};

umask 命令及使用效果

文件打开/关闭 - 系统调用

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
#include <unistd.h>
int close(int fd);

文件硬链接 - 系统调用

#include <unistd.h>
int link(const char *pathnameS, const char *pathnameD);
#include <unistd.h>
int unlink(int fd);

关于文件读/写的系统调用

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, void *buf, size_t count);

文件读写指针移动 - 系统调用

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

off_t lseek(int fd, off_t offset, int whence);

SEEK_SET  0
SEEK_CUR  1
SEEK_END  2

Linux 管道通信相关系统调用 #

UNIX/Linux 管道通信

系统调用 pipe 及系统命令 mknod

#include <unistd.h>
int pipe(int pipefd[2]);
pipefd[0]用于读管道,pipefd[1]用于写管道
成功返回0,出错返回-1
mknod <管道文件名> p
mknod zgsPipe p

0777文件权限的解释 - 掘金

关于linux下0666和0777权限所代表的意思_权限0777-CSDN博客

//有名管道例程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
int main() 
{
 char zPipeName[10] = "zgs-pipe";
 char zFileName[15] = "DataFile.txt";
 char buf[PIPE_BUF + 1];
 int fdPipe, fdData, zRead, zWrite, zSend = 0;
 if (access(zPipeName, F_OK) == -1)
 {if (mkfifo (zPipeName, S_IFIFO|0666) == -1)
  {
   printf("Failed to create pipe[%s] by mkfifo()!\n", zPipeName);
   exit(0);
 }}
fdPipe = open(zPipeName, O_WRONLY);
 fdData = open(zFileName, O_RDONLY);
 printf("Process[%d] open pipe[%s] in WriteOnly mode\n", getpid(), zPipeName);
 if (fdPipe!=-1 && fdData!=-1)
 {while ((zRead = read(fdData, buf, PIPE_BUF))>0)
  {buf[zRead] = '\0';
   if ((zWrite = write(fdPipe, buf, zRead))==-1)
   {printf("Failed to write pipe[%s]!\n", zPipeName);
    exit(0);
   }
   zSend += zWrite;
  }
  close(fdPipe);   close(fdData);
 }
 printf("Process[%d] finished writting %d bytes.\n", getpid(), zSend);
 return 0;
}

int main() 
{char zPipeName[10] = "zgs-pipe";
 char buf[PIPE_BUF + 1];
 int fdPipe, zRead, zReceive = 0;
 memset(buf, '\0', sizeof(buf));
 fdPipe = open(zPipeName, O_RDONLY);
 printf("Process[%d] open pipe[%s] in ReadOnly mode\n", getpid(), zPipeName);
 printf("The following are contents that Process[%d] have read:\n", getpid());
 if (fdPipe!=-1)
 {
   while ((zRead = read(fdPipe, buf, PIPE_BUF))>0)
  {   buf[zRead] = '\0';    printf("%s", buf);    zReceive += zRead;   }
  close(fdPipe);
 }
 printf("Process[%d] finished reading %d bytes.\n", getpid(), zReceive);
 return 0;
}