Linux文件系统
Linux文件系统(一)文件系统概述
一、文件系统的功能规划
文件系统是用来管理磁盘空间,存储文件的一套软件,它需要满足下面几个特点
-
文件系统要有严格的组织形式,使得文件能以块为单位存储
-
文件系统需要索引区,用来查找存储文件的多个块存放在哪个区域
-
如果文件系统的某个文件时热点文件,最近经常被访问,那么文件系统应该有缓存层
-
文家应该用文件节夹的形式组织起来,方便管理和查询
-
Linux内核在内存中应该维护一套数据结构,来维护对应进程打开的文件
二、文件系统相关的命令
对于一块磁盘,首先需要格式化才能存放文件,Linux下常用的文件系统格式为 ext3 和 ext4
可以使用命令 fdisk -l
查看磁盘的分区情况
# fdisk -l
Disk /dev/vda: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000a4c75
Device Boot Start End Blocks Id System
/dev/vda1 * 2048 41943006 20970479+ 83 Linux
Disk /dev/vdc: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
例如上面 vda,大小为 21.5 G,有一个分区 vda1
vdc,大小为 107.4 G,没有被分区
可以使用 mkfs.ext3
和 mkfs.ext4
进行格式化
mkfs.ext4 /dev/vdc
执行完命令后,vdc 会建立一个分区,格式化为 ext4 格式
也可以选择不把一个磁盘格式化为一个分区,而是分为好几个分区,然后分别格式化
首先通过 fdisk
启动一个交互程序
fdisk /dev/vdc
输入 p
可以显示当前的分区信息
输入 n
(new)新建一个分区,它会让你选择创建一个主分区 primary,还是扩展分区 extended。我们一般都会选择 primary
接下来会让你输入分区号,如果原来没有分区,那么应该时从 1 开始的,直接按回车默认也行
接下来,可以一路选择默认值,直到让你输入分区的大小,通过 +sizeM 或者 +sizeK 的方式,默认值是整块磁盘都用上。可以输入 +5620M 来创建一个 5G 的分区。这时候输入 p 就可以看到分区信息,然后再输入 w 将分区信息写入磁盘中
分区结束后,可能会出现 vdc1,vdc2 等多个分区,这时候可以通过 mkfs.ext3 /dev/vdc1
将第一个分区格式化为 ext3 格式。通过 mkfd.ext4 /dev/vdc2
将第二个分区格式化为 ext2 格式
格式化后需要挂载到某个目录下,才能访问
mount /dev/vdc1 / 根目录 / 用户 A 目录 / 目录 1
需要卸载可以通过下面命令
umount / 根目录 / 用户 A 目录 / 目录 1
Linux下一切皆文件。可以使用 ls -l
查看文件的类型
- -:普通文件
- d:文件夹
- c:字符设备文件
- b:块设备文件
- s:socket文件
- l:软链接文件
# ls -l
lrwxrwxrwx 1 root root 61 Dec 14 19:53 instance -> /var/lib/cloud/instances
三、文件系统相关的调用
操作文件可以通过下面的方法
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd = -1;
int ret = 1;
int buffer = 1024;
int num = 0;
if((fd=open("./test", O_RDWR|O_CREAT|O_TRUNC))==-1)
{
printf("Open Error\n");
exit(1);
}
ret = write(fd, &buffer, sizeof(int));
if( ret < 0)
{
printf("write Error\n");
exit(1);
}
printf("write %d byte(s)\n",ret);
lseek(fd, 0L, SEEK_SET);
ret= read(fd, &num, sizeof(int));
if(ret==-1)
{
printf("read Error\n");
exit(1);
}
printf("read %d byte(s),the number is %d\n", ret, num);
close(fd);
return 0;
}
- open:打开一个文件
- write:往文件里写内容
- lseek:移动文件指针
- read:读取文件内容
- close:关闭文件
获取文件信息可以通过下面三个系统调用
int stat(const char *pathname, struct stat *statbuf); //无法处理软链接
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf); //可以返回符号链接的内容
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
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; /* Block size 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:通过文件路径获取文件的 stat 信息,无法查看软链接文件
- fstat:通过文件描述符获取文件信息
- lstat:通过文件路径获取文件信息,当文件为软链接的时候,获取该链接的文件信息
可以通过下面的方法来读取目录下文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
struct stat sb;
DIR *dirp;
struct dirent *direntp;
char filename[128];
if ((dirp = opendir("/root")) == NULL) {
printf("Open Directory Error%s\n");
exit(1);
}
while ((direntp = readdir(dirp)) != NULL){
sprintf(filename, "/root/%s", direntp->d_name);
if (lstat(filename, &sb) == -1)
{
printf("lstat Error%s\n");
exit(1);
}
printf("name : %s, mode : %d, size : %d, user id : %d\n", direntp->d_name, sb.st_mode, sb.st_size, sb.st_uid);
}
closedir(dirp);
return 0
}
- opendir:打开一个目录
- readdir:读取目录下的项
- closedir:关闭一个目录
- dirent:表示目录下一个项
四、总结
- 在文件系统上,需要维护文件严格的格式,需要通过 mkfd.ext4 来讲分区格式化为 ext4 格式
- 每一磁盘保存文件都需要一个索引,来维护对应文件存储在磁盘上的位置
- 文件通过文件夹组织起来,方便管理
- 为了快速读取文件,内核分配了一块空间作为缓存,让一些数据块存储在缓存里面
- 在内核中,要有一套数据结构来表示进程打开的文件
- 在内核态,每个打开的文件都有一个文件描述符,文件相关的操作都需要通过这个文件描述符找到对应的文件