我們花了這麼長的時間,規劃了會議室管理系統,這樣多個項目執行的時候,隔離性能夠獲得保證。node
可是,會議室裏面被回收,會議室裏面的資料就丟失了。有一些資料咱們但願項目結束也能繼續保存,緩存
這就須要一個和項目運行生命週期無關的地方,能夠永久保存,而且空間也要比會議室大的多。bash
一、如何避免必定程度上的命名衝突問題數據結構
每一個文件都有一個名字、這樣咱們訪問一個文件,但願經過它的名字就能夠找到ide
文件名就是一個普通的文本、固然文件名會常常衝突、不一樣用戶取想用的名字的狀況仍是會常常出現的函數
如圖所示,不一樣的用戶的文件放在不一樣的目錄下,雖然不少文件都叫「文件 1」,只要在不一樣的目錄下,就不會有問題ui
也即將一塊盤使用命令組織成必定格式的文件系統的過程。我們買個硬盤或者 U盤,常常說要先格式化,才能放文件,說的就是這個。spa
# 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
mkfs.ext4 /dev/vdc fdisk /dev/vdc
mount /dev/vdc1 / 根目錄 / 用戶 A 目錄 / 目錄 1
格式化後的硬盤,須要掛在到某個目錄下面,才能做爲普通的文件系統進行訪問。操作系統
umount / 根目錄 / 用戶 A 目錄 / 目錄 1
看完了命令行,咱們來看一下,如何使用系統調用在操做文件?咱們先來看一個完整的例子。命令行
#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 打開一個文件時,操做系統會建立一些數據結構來表示這個被打開的文件下一節,咱們就會看到這些。爲了可以找到這些數據結構,在進程中,
咱們會爲這個打開的文件分配一個文件描述符 fd(File Descriptor)。文件描述符,就是用來區分一個進程打開的多個文件的,它的做用域就是當前進程,出了當前進程這個文件描述符就沒有意義了
opne返回的fd必須記錄好,咱們隊這個文件的全部操做都要靠這個fd,包括最後關閉文件
對於命令行來說,經過 ls 能夠獲得文件的屬性,使用代碼怎麼辦呢?
咱們下面三個函數,能夠返回與打開的文件描述符相關的文件狀態信息,這個信息將會寫到類型爲struct stat 的 buf 結構中。
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 */ };
接下來咱們來看,如何使用系統調用列出一個文件夾下面的文件以及文件的屬性
#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 }
到這裏,你應該既會使用系統調用操做文件,也會使用系統調用操做目錄了。下一節,咱們開始來看內核如何實現的。
這一節,咱們對文件系統的主要功能有了一個整體的印象,咱們經過下面這張圖梳理一下
一、在文件系統上,須要維護文件的嚴格的格式,要經過mkfs.ext4 命令來格式化爲嚴格的格式。
二、每個硬盤上保存的文件都要有一個索引,來維護這個文件珊國的數據塊都保存在哪裏
三、文件經過文件夾組織起來,能夠方便用戶使用
四、爲了可以更快讀取文件,內存裏會分配一塊空間最爲緩存,讓一些數據塊放在緩存裏面
五、在內核中,要有一整臺的數據結構來表示打開的文件
六、在用戶態,每一個打開的文件都是一個文件描述符,能夠經過各類文件相關的系統調用,操做這個文件描述符