日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux Storage入门学习

發(fā)布時(shí)間:2023/12/20 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux Storage入门学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

本文大量代碼基于linux 0.11,因?yàn)樵缙趌inux的版本更加適合初學(xué)者入門。雖然代碼比較早,但是不妨礙我們學(xué)習(xí)Linux Storage的精髓。

一、hello world

1.1 Demo

#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h>int main(int argc, char *argv[]) {printf("pid = %d\n", getpid());int fd1,fd2;char s[] = "hello world\n";//打開文件,拿到fdfd1 = open("/tmp/1.txt", O_RDWR | O_CREAT);printf("fd1 = %d\n", fd1);//寫入write(fd1, s, sizeof(s));close(fd1);fd2 = open("/tmp/2.txt", O_RDWR | O_CREAT);printf("fd2 = %d\n", fd2);//打開文件,拿到fdfd1 = open("/tmp/1.txt", O_RDWR);printf("fd1 = %d\n", fd1);char buffer[80];//讀取read(fd1, buffer, sizeof(buffer));//關(guān)閉fdprintf("%s", buffer);getchar();//暫停程序close(fd1);close(fd2);return 0; }

運(yùn)行結(jié)果

pid = 14378 fd1 = 3 fd2 = 3 fd1 = 4 hello world


1.1 fd只是一個(gè)數(shù)字,代表數(shù)字和文件之前的一個(gè)映射關(guān)系

查看/proc/14378/fd,可以看到映射關(guān)系

dr-x------ 2 wangbinhong tctnb 0 3月 14 16:27 . dr-xr-xr-x 9 wangbinhong tctnb 0 3月 14 16:26 .. lrwx------ 1 wangbinhong tctnb 64 3月 14 16:27 0 -> /dev/pts/19 //stdin lrwx------ 1 wangbinhong tctnb 64 3月 14 16:27 1 -> /dev/pts/19 //stdout lrwx------ 1 wangbinhong tctnb 64 3月 14 16:27 2 -> /dev/pts/19 //stderr lrwx------ 1 wangbinhong tctnb 64 3月 14 16:27 3 -> /tmp/2.txt lrwx------ 1 wangbinhong tctnb 64 3月 14 16:27 4 -> /tmp/1.txt

程序中的4是數(shù)字,/proc/14378/fd/4是一個(gè)文件,鏈接到/tmp/1.txt,/proc/14378/fd/4只存在內(nèi)存中,不存在硬盤中,程序中的數(shù)字4不是指向/proc/14378/fd/4文件

二、數(shù)字fd代表什么

2.1 task_struct

每一個(gè)進(jìn)程在內(nèi)核中的有一個(gè)task_struct的結(jié)構(gòu)體,結(jié)構(gòu)體中有一個(gè)file指針數(shù)組filp,fd代表filp這個(gè)數(shù)組的下標(biāo),fd = 4 就代表filp[4]指向的file結(jié)構(gòu)體

struct task_struct {...struct file * filp[NR_OPEN];... }

2.2 file

struct file {unsigned short f_mode;//文件的類型和屬性u(píng)nsigned short f_flags;//文件打開的標(biāo)志unsigned short f_count;//關(guān)聯(lián)的fd的個(gè)數(shù)struct m_inode * f_inode;//file的真實(shí)實(shí)現(xiàn)off_t f_pos;//文件當(dāng)前的讀寫指針,讀到哪里了。 }

2.3 file_table

內(nèi)核中還有一個(gè)全局的file_table,是file數(shù)組,保存所有file結(jié)構(gòu)體。

struct file file_table[NR_FILE];//系統(tǒng)級(jí)的一個(gè)file table

2.4 關(guān)聯(lián)關(guān)系

兩個(gè)細(xì)節(jié)
dup:同進(jìn)程兩個(gè)fd指向同一個(gè)file
fork:兩個(gè)進(jìn)程的兩個(gè)fd指向同一個(gè)file


下面是新的Kernel關(guān)系圖


2.5 Binder傳輸fd

Binder傳輸fd,兩個(gè)進(jìn)程的不同fd指向了同一個(gè)file,享有相同的file offset和file status flag.

三、以pipe為例:一切皆文件

早期的錯(cuò)誤想法

硬件驅(qū)動(dòng)通過設(shè)備文件和用戶空間的應(yīng)用程序通信,是通過將驅(qū)動(dòng)的信息寫進(jìn)設(shè)備文件,然后應(yīng)用程序讀取設(shè)備文件的內(nèi)容。

3.1 pipe初始化


3.1.1 sys_pipe

系統(tǒng)調(diào)用pipe的實(shí)現(xiàn),會(huì)返回兩個(gè)fd給用戶空間

int sys_pipe(unsigned long * fildes)//系統(tǒng)調(diào)用生成一對(duì)pipe {struct m_inode * inode;struct file * f[2];int fd[2];int i,j;j=0;for(i=0;j<2 && i<NR_FILE;i++)if (!file_table[i].f_count)//找到空閑的file(f[j++]=i+file_table)->f_count++;//將空閑的file的f_count+1,并保存這兩個(gè)file結(jié)構(gòu)體if (j==1)//只找到一個(gè)f[0]->f_count=0;//將第一file重置,清空if (j<2)return -1;//沒找到一隊(duì),反正就是失敗j=0;for(i=0;j<2 && i<NR_OPEN;i++)//將兩個(gè)file的指針分別保存到current->filp[i]的空閑處if (!current->filp[i]) {current->filp[ fd[j]=i ] = f[j];j++;}if (j==1)current->filp[fd[0]]=NULL;if (j<2) {f[0]->f_count=f[1]->f_count=0;return -1;}//和上面邏輯類似if (!(inode=get_pipe_inode())) {//詳見3.1.2 獲得一個(gè)pipe inodecurrent->filp[fd[0]] =current->filp[fd[1]] = NULL;f[0]->f_count = f[1]->f_count = 0;return -1;}f[0]->f_inode = f[1]->f_inode = inode;//讓兩個(gè)file結(jié)構(gòu)體的f_inode指向pipe inodef[0]->f_pos = f[1]->f_pos = 0;//重置讀寫指針f[0]->f_mode = 1; /* read */f[1]->f_mode = 2; /* write */put_fs_long(fd[0],0+fildes);//將fd0數(shù)值返回給用戶空間put_fs_long(fd[1],1+fildes);//將fd1數(shù)值返回給用戶空間return 0; }
3.1.2 get_pipe_inode

創(chuàng)建一個(gè)m_inode結(jié)構(gòu)體
將m_inode的i_size指向一塊4096B的緩沖區(qū)
設(shè)置m_inode的i_pipe為1,標(biāo)識(shí)這個(gè)m_inode為pipe inode

struct m_inode * get_pipe_inode(void)//返回一個(gè)空的pipe inode用于pipe {struct m_inode * inode;if (!(inode = get_empty_inode()))return NULL;if (!(inode->i_size=get_free_page())) {//申請(qǐng)一個(gè)物理頁4096B作為環(huán)形管道緩沖區(qū),緩沖區(qū)指針保存到i_size。inode->i_count = 0;return NULL;}inode->i_count = 2; /* sum of readers/writers */PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;inode->i_pipe = 1;//表示為pipe的m_inodereturn inode; }
3.1.3 get_free_page

申請(qǐng)一個(gè)物理頁,并返回內(nèi)核空間的地址

unsigned long get_free_page(void) { register unsigned long __res asm("ax");__asm__("std ; repne ; scasb\n\t""jne 1f\n\t""movb $1,1(%%edi)\n\t""sall $12,%%ecx\n\t""addl %2,%%ecx\n\t""movl %%ecx,%%edx\n\t""movl $1024,%%ecx\n\t""leal 4092(%%edx),%%edi\n\t""rep ; stosl\n\t""movl %%edx,%%eax\n""1:":"=a" (__res):"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),"D" (mem_map+PAGING_PAGES-1):"di","cx","dx"); return __res; }

3.2 讀pipe

3.2.1 sys_read

根據(jù)inode->i_pip,將sys_read變成read_pipe。

int sys_read(unsigned int fd,char * buf,int count)//文件讀的系統(tǒng)調(diào)用,fd->file->inode->數(shù)據(jù)塊 {struct file * file;struct m_inode * inode;if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))return -EINVAL;if (!count)return 0;verify_area(buf,count);inode = file->f_inode;if (inode->i_pipe)//pipereturn (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;//3.2.2if (S_ISCHR(inode->i_mode))//字符設(shè)備return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);if (S_ISBLK(inode->i_mode))//塊設(shè)備return block_read(inode->i_zone[0],&file->f_pos,buf,count);if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {//常規(guī)文件或目錄if (count+file->f_pos > inode->i_size)count = inode->i_size - file->f_pos;if (count<=0)return 0;return file_read(inode,file,buf,count);}printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);return -EINVAL; }
3.2.2 read_pipe

將緩沖區(qū)的數(shù)據(jù)讀到用戶空間char,讀count字節(jié)

int read_pipe(struct m_inode * inode, char * buf, int count)//讀取pipe {int chars, size, read = 0;while (count>0) {while (!(size=PIPE_SIZE(*inode))) {//如果發(fā)現(xiàn)沒有內(nèi)容wake_up(&inode->i_wait);//喚醒寫端if (inode->i_count != 2) /* are there any writers? *///沒有寫端return read;sleep_on(&inode->i_wait);//沒有內(nèi)容就睡眠}chars = PAGE_SIZE-PIPE_TAIL(*inode);//判斷尾部的數(shù)據(jù)if (chars > count)chars = count;if (chars > size)chars = size;count -= chars;read += chars;size = PIPE_TAIL(*inode);//頭部開始讀的指針PIPE_TAIL(*inode) += chars;PIPE_TAIL(*inode) &= (PAGE_SIZE-1);while (chars-->0)put_fs_byte(((char *)inode->i_size)[size++],buf++);}wake_up(&inode->i_wait);return read; }

3.3 寫pipe

3.3.1 sys_write

根據(jù)inode->i_pip,將sys_write變成write_pipe。

int sys_write(unsigned int fd,char * buf,int count)//文件寫的系統(tǒng)調(diào)用,fd->file->inode->數(shù)據(jù)塊 {struct file * file;struct m_inode * inode;if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))return -EINVAL;if (!count)return 0;inode=file->f_inode;if (inode->i_pipe)return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;//3.3.2if (S_ISCHR(inode->i_mode))return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);if (S_ISBLK(inode->i_mode))return block_write(inode->i_zone[0],&file->f_pos,buf,count);if (S_ISREG(inode->i_mode))return file_write(inode,file,buf,count);printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);return -EINVAL; }
3.3.2 write_pipe

將用戶空間char對(duì)應(yīng)的數(shù)據(jù)寫到緩沖區(qū),寫入count字節(jié)

int write_pipe(struct m_inode * inode, char * buf, int count)//寫pipe的實(shí)現(xiàn) {int chars, size, written = 0;while (count>0) {while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {//如果寫滿了,size為0wake_up(&inode->i_wait);//喚醒讀端if (inode->i_count != 2) { /* no readers *///沒有讀者直接返回current->signal |= (1<<(SIGPIPE-1));return written?written:-1;}sleep_on(&inode->i_wait);//寫端休眠}chars = PAGE_SIZE-PIPE_HEAD(*inode);//計(jì)算管道頭部到緩沖區(qū)末端的空閑字節(jié)數(shù) 4098if (chars > count)chars = count;if (chars > size)chars = size;count -= chars;written += chars;size = PIPE_HEAD(*inode);//當(dāng)前的頭指正PIPE_HEAD(*inode) += chars;PIPE_HEAD(*inode) &= (PAGE_SIZE-1);while (chars-->0)((char *)inode->i_size)[size++]=get_fs_byte(buf++);//一個(gè)寫字符到管道}wake_up(&inode->i_wait);//寫完喚醒讀端return written; }

3.4 pipe讀寫指針

其實(shí)pipe的讀寫指針并沒有保存在file結(jié)構(gòu)體,而是保存在m_inode。
如果緩沖區(qū)滿了,讀端一會(huì)不讀,會(huì)導(dǎo)致寫端的進(jìn)程sleep。
整個(gè)讀寫的過程,并沒有通過鎖來控制,而是通過ringbuffer來實(shí)現(xiàn),有興趣的可以自己研究。

struct m_inode { ...unsigned long i_size;//被作為指針指向申請(qǐng)的緩沖區(qū),一個(gè)緩沖區(qū)4096Bunsigned short i_zone[9];//用i_zone[0]代表寫的游標(biāo),用i_zone[1]代表寫的游標(biāo) ... }


3.5 思考一個(gè)問題

父進(jìn)程創(chuàng)建一對(duì)pipe的fd1 fd2
子進(jìn)程通過fork復(fù)制父進(jìn)程的pipe fd1 fd2
父進(jìn)程關(guān)閉讀的fd1
子進(jìn)程關(guān)閉寫的fd2
父子進(jìn)程就可以通過pipe進(jìn)行跨進(jìn)程通信


3.6 Linux的改進(jìn)

當(dāng)文件類型越來越多的時(shí)候,用file_operations結(jié)構(gòu)體代替大量if else
file_operations中保存read write的函數(shù)指針

struct file {const struct file_operations *f_op;void *private_data;//這個(gè)很重要 }struct file_operations {ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); };

我覺得這樣子理解更加合適:一切皆文件接口

四、普通文件

4.1重要數(shù)據(jù)結(jié)構(gòu)

4.1.1 m_inode

file中f_inode指向就是m_inode,也就是file對(duì)應(yīng)的真實(shí)實(shí)現(xiàn)。
i_dev:代表塊設(shè)備號(hào)
i_zone[9]:代表數(shù)據(jù)塊號(hào)

struct m_inode {unsigned short i_mode;//15-12文件類型,11-9保存執(zhí)行文件設(shè)置,8-0保存文件權(quán)限unsigned short i_uid;//文件宿主的用戶idunsigned long i_size;//文件長(zhǎng)度unsigned long i_mtime;//修改時(shí)間unsigned char i_gid;//文件宿主的組idunsigned char i_nlinks;//硬鏈接的次數(shù)unsigned short i_zone[9];//對(duì)應(yīng)數(shù)據(jù)塊 0-6直接是塊號(hào),7一次間接塊,8二次間接塊,一個(gè)塊是1KB=1024Byte//因?yàn)閴K號(hào)用short來表示,也就是2Byte,所以一個(gè)塊可以存放512個(gè)塊號(hào),所以一次塊512個(gè),二次塊就是512*512。//所以變相的可以算出一個(gè)文件的最大size是7+512+512*512 kb//一般邏輯塊的大小會(huì)和buffer_head大小一樣。 /* these are in memory also */struct task_struct * i_wait;unsigned long i_atime;unsigned long i_ctime;unsigned short i_dev;//設(shè)備號(hào)unsigned short i_num;unsigned short i_count;unsigned char i_lock;unsigned char i_dirt;unsigned char i_pipe;unsigned char i_mount;unsigned char i_seek;unsigned char i_update; };


4.1.2 buffer_head

b_dev設(shè)備號(hào)
b_blocknr數(shù)據(jù)塊號(hào)
b_data指向一塊內(nèi)存
所有buffer_head會(huì)被存放在一個(gè)hash表中

struct buffer_head {char * b_data; /* pointer to data block (1024 bytes) */unsigned long b_blocknr; /* block number */ //塊號(hào)unsigned short b_dev; /* device (0 = free) */ //設(shè)備號(hào)unsigned char b_uptodate;unsigned char b_dirt; /* 0-clean,1-dirty */unsigned char b_count; /* users using this block */unsigned char b_lock; /* 0 - ok, 1 -locked */struct task_struct * b_wait;struct buffer_head * b_prev;struct buffer_head * b_next;struct buffer_head * b_prev_free;struct buffer_head * b_next_free; };

可以調(diào)用下面兩個(gè)接口,完成數(shù)據(jù)塊的讀寫,這背后的實(shí)現(xiàn)就要看塊設(shè)備驅(qū)動(dòng)怎么實(shí)現(xiàn)的。

先記住,buffer_head(設(shè)備號(hào)+塊號(hào)+內(nèi)存地址)+讀寫指令 可以完成一次信息的交換。
ll_rw_block(READ,bh); ll_rw_block(WRITE,bh);

4.2 讀文件

4.2.1 file_read

根據(jù)(filp->f_pos)/BLOCK_SIZE計(jì)算對(duì)應(yīng)的塊號(hào)nr
根據(jù)inode->i_dev和nr調(diào)用bread獲得buffer_head
調(diào)用ll_rw_block(READ,bh)請(qǐng)求數(shù)據(jù)塊的數(shù)據(jù)
將buffer_head中b_data拷貝到用戶空間的buf

int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) {int left,chars,nr;struct buffer_head * bh;if ((left=count)<=0)return 0;while (left) {if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {if (!(bh=bread(inode->i_dev,nr)))//4.2.2break;} elsebh = NULL;nr = filp->f_pos % BLOCK_SIZE;chars = MIN( BLOCK_SIZE-nr , left );filp->f_pos += chars;left -= chars;if (bh) {char * p = nr + bh->b_data;while (chars-->0)put_fs_byte(*(p++),buf++);brelse(bh);} else {while (chars-->0)put_fs_byte(0,buf++);}}inode->i_atime = CURRENT_TIME;return (count-left)?(count-left):-ERROR; }
4.2.2 bread

根據(jù)設(shè)備號(hào),數(shù)據(jù)塊號(hào),創(chuàng)建一個(gè)buffer_head

/** bread() reads a specified block and returns the buffer that contains* it. It returns NULL if the block was unreadable.*/ struct buffer_head * bread(int dev,int block)//從dev,block獲得buffer_head,一般用這個(gè)就可以 {struct buffer_head * bh;if (!(bh=getblk(dev,block)))//拿一塊空閑的buffer_headpanic("bread: getblk returned NULL\n");if (bh->b_uptodate)return bh;ll_rw_block(READ,bh);//將硬件的數(shù)據(jù)讀取到buffer_headwait_on_buffer(bh);if (bh->b_uptodate)return bh;brelse(bh);//釋放鎖return NULL; }

4.3 寫文件

4.3.1 file_write

根據(jù)(filp->f_pos)/BLOCK_SIZE計(jì)算對(duì)應(yīng)的塊號(hào)block,如果文件不夠大,需要擴(kuò)容。
根據(jù)inode->i_dev和block調(diào)用bread獲得buffer_head
將用戶空間的buf拷貝到buffer_head中b_data。

int file_write(struct m_inode * inode, struct file * filp, char * buf, int count) {off_t pos;int block,c;struct buffer_head * bh;char * p;int i=0;/** ok, append may not work when many processes are writing at the same time* but so what. That way leads to madness anyway.*/if (filp->f_flags & O_APPEND)pos = inode->i_size;elsepos = filp->f_pos;while (i<count) {if (!(block = create_block(inode,pos/BLOCK_SIZE)))//如果寫文件的時(shí)候發(fā)現(xiàn)文件不夠大,就要擴(kuò)容break;if (!(bh=bread(inode->i_dev,block)))break;c = pos % BLOCK_SIZE;p = c + bh->b_data;bh->b_dirt = 1;c = BLOCK_SIZE-c;if (c > count-i) c = count-i;pos += c;if (pos > inode->i_size) {inode->i_size = pos;inode->i_dirt = 1;}i += c;while (c-->0)*(p++) = get_fs_byte(buf++);brelse(bh);}inode->i_mtime = CURRENT_TIME;if (!(filp->f_flags & O_APPEND)) {filp->f_pos = pos;inode->i_ctime = CURRENT_TIME;}return (i?i:-1); }
4.3.2 sys_sync

ll_rw_block將buffer_head的臟數(shù)據(jù)同步到塊設(shè)備

int sys_sync(void)//系統(tǒng)調(diào)用,同步塊設(shè)備和內(nèi)存高速緩存中數(shù)據(jù) {int i;struct buffer_head * bh;sync_inodes(); /* write out inodes into buffers *///將修改的inode數(shù)據(jù)寫入到buffer_head.bh = start_buffer;for (i=0 ; i<NR_BUFFERS ; i++,bh++) {wait_on_buffer(bh);if (bh->b_dirt)ll_rw_block(WRITE,bh);//真的寫到塊設(shè)備中}return 0; }

五、塊設(shè)備

5.1 內(nèi)部結(jié)構(gòu)


struct d_inode { //塊設(shè)備中對(duì)應(yīng)的inode的結(jié)構(gòu)體unsigned short i_mode;unsigned short i_uid;unsigned long i_size;unsigned long i_time;unsigned char i_gid;unsigned char i_nlinks;unsigned short i_zone[9]; }; struct dir_entry { //目錄unsigned short inode;//inodechar name[NAME_LEN];//inode對(duì)應(yīng)的文件名 };


5.2 mount("dev/block/sda0","/sdcard")

第一步:從dev/block/sda0中讀取第0塊inode塊上的數(shù)據(jù),讀取第一個(gè)d_inode的數(shù)據(jù),并構(gòu)建內(nèi)存中的m_inode。

第二步:將m_inode的i_num和"sdcard"按照dir_entry的結(jié)構(gòu)體存放在"/"目錄對(duì)應(yīng)m_inode指向的i_zone數(shù)據(jù)區(qū)域


5.3 int fd = open("/sdcard/1.txt")

第一步:找到m_inode("sdcard")

讀取"/"對(duì)應(yīng)的m_inode("/")的 i_zone[9]的數(shù)據(jù)到內(nèi)存中
根據(jù)"sdcard"得到inode號(hào),拿到"sdcard"對(duì)應(yīng)的m_inode("sdcard"),m_inode已經(jīng)在mount中創(chuàng)建。

第二步:創(chuàng)建m_inode("1.txt")

讀取m_inode("sdcard")的 i_zone[9]的數(shù)據(jù)到內(nèi)存中
根據(jù)"1.txt",拿到1.txt文件對(duì)應(yīng)的d_inode的號(hào)
計(jì)算d_inode號(hào)找到對(duì)應(yīng)的d_inode結(jié)構(gòu)體存放在塊設(shè)備的塊號(hào),塊號(hào)=inode/一個(gè)塊最多存放的d_inode結(jié)構(gòu)體
讀取的塊號(hào)對(duì)應(yīng)數(shù)據(jù)到內(nèi)存中,讀取對(duì)應(yīng)的d_inode數(shù)據(jù),構(gòu)建m_inode("sdcard")

第三步:將fd指向file指向m_inode

創(chuàng)建file指向m_inode("1.txt")
file[fd]指向file
返回fd


從此形成fd->file->m_inode的對(duì)應(yīng)關(guān)系,write read close 都可以對(duì)應(yīng)的轉(zhuǎn)化成file的操作,對(duì)應(yīng)的m_inode的操作

六、目前Linux的架構(gòu)

構(gòu)建了一個(gè)VFS層,虛擬文件系統(tǒng),各類文件系統(tǒng)可以更好的兼容,EXT4,F2FS
文件系統(tǒng)和塊設(shè)備的數(shù)據(jù)交互,用BIO代替了buffer_head
新增了Block Layer層對(duì)BIO進(jìn)行合并調(diào)度

? 回復(fù)「?籃球的大肚子」進(jìn)入技術(shù)群聊

回復(fù)「1024」獲取1000G學(xué)習(xí)資料

總結(jié)

以上是生活随笔為你收集整理的Linux Storage入门学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。