1.mmap
mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要read/write函数。
-
addr:如果addr参数为NULL,内核自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可得到。
-
len:需要映射的那一部分文件的长度。off参数是从文件的什么位置开始映射,必须是页大小的整数倍。
-
filedes:该文件的描述符。
-
prot:有4种取值:①PROT_EXEC:映射的这一段可执行,如映射共享库 ②PROT_READ:映射的这一段可读 ③PROT_WRITE:映射的这一段可写 ④PROT_NONE:映射的这一段不可访问。
-
flag:①MAP_SHARED:多个进程对同文件映射共享, ②MAP_PRIVATE:多个进程对同文件映射不共享
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
int main(void) {
int fd = open("test.txt", O_RDWR);
if (fd < 0) {
perror("open file");
exit(1);
}
int *p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);
((int *)((char *)p) + 1)[0] = 0x30313233;
munmap(p, 6);
return 0;
}
2.虚拟文件系统VFS
【1】ext2文件系统
文件系统中存储的最小单位是块Block,一个块究竟多大是格式化时确定的,
如:mke2fs的-b选项可以设定块大小是1024,2048或4096字节。
-
启动块Boot Block:大小就是1KB,由PC标准确定,用来存储磁盘分区信息和启动信息,任何文件系统d都不能使用该块。
-
超级块Super Block:描述整个分区的文件系统信息,如:块大小,文件系统版本号,上次mount的时间等。超级块在每个块组的开头都有一份拷贝 。
-
块组描述符表GDT(Group Descriptor Table):由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符存储一个块组的描述信息,包括inode表从哪里开始,数据块从哪里开始,空闲的inode和数据块还有多少个。块组描述符表在每一个块组的开头都有一份拷贝,这些信息很重要,因此都有多份拷贝。
-
块位图Block Bitmap:是用来描述整个块组中哪些块已用,那些块空闲,本身占一个块,其中的每个bit代表本块中一个块,这个bit为1表示该块已用,这个bit为0表示该块空闲可用。
-
inode位图inode bitmap:和块位图类似,本身占一个块,其中每一个bit表示一个inode是否空闲可用。
-
inode表inode table:文件类型(常规,目录,符号链接),权限,文件大小,创建/修改/访问时间等信息存在inode中,每个文件都有一个inode。
-
数据块Data Block:
①常规文件:文件的数据存在数据块。
②目录:该目录下的所有文件名和目录存在数据块。(文件名保存在所在目录的数据块中,其他信息都保存在该文件的inode中)。
③符号链接:如果目标路径名较短则直接保存在inode中以便更快查找,否则分配一个数据块来保存。
④设备文件、FIFO,socket等特殊文件:没有数据块,设备文件的主设备和次设备号保存在inode。
【2】stat(2)
读取文件的inode,然后把inode中的各种文件属性填入一个struct stat结构体传出给调用者。
stat(1)命令是基于stat函数实现的。
stat需要根据传入的文件路径找到inode。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct stat st;
if (argc < 2) {
printf("usage:cmd + filename,dirname\n");
exit(1);
}
lstat(argv[1], &st);
switch (st.st_mode & S_IFMT)
{
case S_IFREG:
printf("Is regular file\n");
break;
case S_IFDIR:
printf("Is directory\n");
break;
case S_IFCHR:
printf("Is charactor device\n");
break;
default:
printf("Is other file type\n");
break;
}
return 0;
}
lstat: other file type