1、安装文件系统
在shell下输入mount /dev/hd1 /mnt,shell进程接到命令后,会创建一个新进程,新进程调用mount()函数,并最终映射到sys_mount函数执行
代码路径:fs/super.c
int sys_mount(char * dev_name, char * dir_name, int rw_flag)//dev_name为/dev/hd1 dir_name为/mnt { struct m_inode * dev_i, * dir_i; struct super_block * sb; int dev; if (!(dev_i=namei(dev_name)))//获取hd1设备文件i节点 return -ENOENT; dev = dev_i->i_zone[0];//通过i节点,获取设备号 if (!S_ISBLK(dev_i->i_mode)) {//暂不考虑 iput(dev_i); return -EPERM; } iput(dev_i);//释放hd1设备文件i节点 if (!(dir_i=namei(dir_name)))//获取mnt的i节点 return -ENOENT; if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {//如果mnt的节点只被引用过一次,并且不是根i节点,它才能被使用 iput(dir_i); return -EBUSY; } if (!S_ISDIR(dir_i->i_mode)) {//确定mnt不是目录文件 iput(dir_i); return -EPERM; } if (!(sb=read_super(dev))) {//通过设备号,读取设备的超级块 iput(dir_i); return -EBUSY; } if (sb->s_imount) {//确保hd1设备的文件系统没有被安装在其他地方 iput(dir_i); return -EBUSY; } if (dir_i->i_mount) {//确保mnt目录文件i节点没有安装过其他文件系统 iput(dir_i); return -EPERM; } sb->s_imount=dir_i; //将超级块中s_imount与根文件系统中dir_i挂接 dir_i->i_mount=1; //dir的i节点上已经挂接了文件系统 dir_i->i_dirt=1; //dir的i节点信息已经被更改 return 0; /* we do that in umount */ }read_super(dev),把硬盘超级块的信息读到超级块项中(struct d_super_block),硬盘i节点位图和逻辑块位图放入缓冲区,并且把地址保存在超级块中。
hd1的i节点被释放了,因为没有用了。/mnt的i节点没有被释放,因为它的数据i_mount被改变了,i_dirt被设置为1,说明会被同步到虚拟盘上。
用户进程打开一个在硬盘上已存在的文件,并读取文件的内容
void main() { char buffer[12000]; int fd=open("/mnt/user/user1/user2/hello.txt",O_RDWR,0644); int size = read(fd,buffer,sizeof(buffer)); return; }
int sys_open(const char * filename,int flag,int mode) { struct m_inode * inode; struct file * f; int i,fd; mode &= 0777 & ~current->umask; for(fd=0 ; fd<NR_OPEN ; fd++) if (!current->filp[fd])//从当前进程*filp[20]中寻找空闲项 break; if (fd>=NR_OPEN)//检查*filp[20]结构是否已经超出了使用极限 return -EINVAL; current->close_on_exec &= ~(1<<fd); f=0+file_table; for (i=0 ; i<NR_FILE ; i++,f++)//在file_table[64]中寻找空闲项 if (!f->f_count) break; if (i>=NR_FILE) return -EINVAL; (current->filp[fd]=f)->f_count++;//f_count同时加1 if ((i=open_namei(filename,flag,mode,&inode))<0) {//获取/mnt/user/user1/user2/hello.txt的i节点 current->filp[fd]=NULL; f->f_count=0; return i; } /* ttys are somewhat special (ttyxx major==4, tty major==5) */ if (S_ISCHR(inode->i_mode)) { if (MAJOR(inode->i_zone[0])==4) { if (current->leader && current->tty<0) { current->tty = MINOR(inode->i_zone[0]); tty_table[current->tty].pgrp = current->pgrp; } } else if (MAJOR(inode->i_zone[0])==5) if (current->tty<0) { iput(inode); current->filp[fd]=NULL; f->f_count=0; return -EPERM; } } /* Likewise with block-devices: check for floppy_change */ if (S_ISBLK(inode->i_mode)) check_disk_change(inode->i_zone[0]); f->f_mode = inode->i_mode;//用该i节点属性,设置文件属性 f->f_flags = flag;//用flag参数,设置文件操作方式 f->f_count = 1;//将文件引用计数加1 f->f_inode = inode;//文件于i节点建立关系 f->f_pos = 0; return (fd);//返回0 }获取/mnt/user/user1/user2/hello.txt的i节点,这个节点是硬盘上的节点,不是虚拟盘上的节点,所以open_namei与之前有所不同,不同的地方获取/mnt节
点,调用iget获取/mnt节点的时候,实际上获取了硬盘设备的根i节点,具体代码如下:
代码路径:fs/inode.c
struct m_inode * iget(int dev,int nr) { struct m_inode * inode, * empty; if (!dev) panic("iget with dev==0"); empty = get_empty_inode();//从inode_table[32]中,获取空闲的i节点表项 inode = inode_table; while (inode < NR_INODE+inode_table) {//检测指定的i节点是否已经加载过了,本案例mnt目录文件i节点就加载过 if (inode->i_dev != dev || inode->i_num != nr) {//对比设备号和i节点号是否与指定的i节点相匹配 inode++; continue; } wait_on_inode(inode);//暂时不考虑 if (inode->i_dev != dev || inode->i_num != nr) {//暂时不考虑 inode = inode_table; continue; } inode->i_count++;//mnt的i节点i_count加1,变成2 if (inode->i_mount) {//mnt的i节点安装了文件系统 int i; for (i = 0 ; i<NR_SUPER ; i++) if (super_block[i].s_imount==inode) break;//所安装文件系统的超级块 if (i >= NR_SUPER) { printk("Mounted inode hasn‘t got sb\n"); if (empty) iput(empty); return inode; } iput(inode);//mnt的i节点i_count减1,变成1 dev = super_block[i].s_dev;//硬盘的设备号 nr = ROOT_INO;//硬盘的根i节点号 inode = inode_table;//看看硬盘的设备号,硬盘的根i节点号在inode_table[32]中是否存在,本例中,并不存在,get_empty_inode已经覆盖了那个节点 continue; } if (empty) iput(empty); return inode; } if (!empty) return (NULL); inode=empty; inode->i_dev = dev;//新的节点的设备号是硬盘的设备号 inode->i_num = nr;//新的节点的节点号是硬盘根i节点号 read_inode(inode);//给这个inode赋上值 return inode; }
read(fd,buffer,sizeof(buffer),映射到sys_read执行
代码路径:fs/read_write.c
int sys_read(unsigned int fd,char * buf,int count) { 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;//文件的i节点 if (inode->i_pipe) return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO; if (S_ISCHR(inode->i_mode)) return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos); if (S_ISBLK(inode->i_mode)) return block_read(inode->i_zone[0],&file->f_pos,buf,count); if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) { 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; }代码路径:fs/file_dev.c
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)//left为总共的长度,比如现在为4 return 0; while (left) { if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) {//找到该数据的逻辑块号 if (!(bh=bread(inode->i_dev,nr)))//读取一个数据块(1024个字节) break; } else bh = NULL; nr = filp->f_pos % BLOCK_SIZE;//此时f_pos为0,nr为0 chars = MIN( BLOCK_SIZE-nr , left );//此时为4 filp->f_pos += chars;//f_pos现在为4 left -= chars;//left为0 if (bh) { char * p = nr + bh->b_data;//p为缓冲区的地址 while (chars-->0) put_fs_byte(*(p++),buf++);//从缓冲区赋值到内存 brelse(bh);//释放缓冲区 } else { while (chars-->0) put_fs_byte(0,buf++); } }//left为0跳出循环 inode->i_atime = CURRENT_TIME; return (count-left)?(count-left):-ERROR;//返回总的数量 }下面我们看下bmap函数
代码路径:fs/inode.c
... static int _bmap(struct m_inode * inode,int block,int create) { struct buffer_head * bh; int i; if (block<0) panic("_bmap: block<0"); if (block >= 7+512+512*512) panic("_bmap: block>big"); if (block<7) { if (create && !inode->i_zone[block]) if ((inode->i_zone[block]=new_block(inode->i_dev))) { inode->i_ctime=CURRENT_TIME; inode->i_dirt=1; } return inode->i_zone[block];//此时读取inode->i_zone[0]里面的逻辑号 } block -= 7; if (block<512) { if (create && !inode->i_zone[7]) if ((inode->i_zone[7]=new_block(inode->i_dev))) { inode->i_dirt=1; inode->i_ctime=CURRENT_TIME; } if (!inode->i_zone[7]) return 0; if (!(bh = bread(inode->i_dev,inode->i_zone[7]))) return 0; i = ((unsigned short *) (bh->b_data))[block]; if (create && !i) if ((i=new_block(inode->i_dev))) { ((unsigned short *) (bh->b_data))[block]=i; bh->b_dirt=1; } brelse(bh); return i; } block -= 512; if (create && !inode->i_zone[8]) if ((inode->i_zone[8]=new_block(inode->i_dev))) { inode->i_dirt=1; inode->i_ctime=CURRENT_TIME; } if (!inode->i_zone[8]) return 0; if (!(bh=bread(inode->i_dev,inode->i_zone[8]))) return 0; i = ((unsigned short *)bh->b_data)[block>>9]; if (create && !i) if ((i=new_block(inode->i_dev))) { ((unsigned short *) (bh->b_data))[block>>9]=i; bh->b_dirt=1; } brelse(bh); if (!i) return 0; if (!(bh=bread(inode->i_dev,i))) return 0; i = ((unsigned short *)bh->b_data)[block&511]; if (create && !i) if ((i=new_block(inode->i_dev))) { ((unsigned short *) (bh->b_data))[block&511]=i; bh->b_dirt=1; } brelse(bh); return i; } int bmap(struct m_inode * inode,int block) { return _bmap(inode,block,0); } ...请看下图:
此图为文件数据小于7块时i节点的管理示意图
文件数据大于7块,少于7+512块时i节点的管理示意图,第8个成员记录一个数据块的块号,但这个块里面存储的并不是文件数据内容,而是该文件后续512个数据块在外设的“逻辑块号”。因为一个数据块的大小为1024个字节,而每个块号需要占用两个字节,所以一个数据块能存储512个块号。
文件数据大于7+512块时i节点的管理示意图暂不说明。
用户进程在硬盘上新建一个文件,并将内容写入这个文件
void main() { char str1[]="Hello,world"; int fd=creat("/mnt/user/user1/user2/hello.txt",0644); int size=write(fd,str1,strlen(str1)); }
4、新建文件
creat映射到sys_creat
代码路径:fs/open.c
int sys_creat(const char* pathname,in mode) { return sys_open(pathname,O_CREAT |O_TRUNC,mode); }代码路径:fs/open.c
int sys_open(const char * filename,int flag,int mode) { struct m_inode * inode; struct file * f; int i,fd; mode &= 0777 & ~current->umask; for(fd=0 ; fd<NR_OPEN ; fd++) if (!current->filp[fd]) break; if (fd>=NR_OPEN) return -EINVAL; current->close_on_exec &= ~(1<<fd); f=0+file_table; for (i=0 ; i<NR_FILE ; i++,f++) if (!f->f_count) break; if (i>=NR_FILE) return -EINVAL; (current->filp[fd]=f)->f_count++; if ((i=open_namei(filename,flag,mode,&inode))<0) { current->filp[fd]=NULL; f->f_count=0; return i; } /* ttys are somewhat special (ttyxx major==4, tty major==5) */ if (S_ISCHR(inode->i_mode)) { if (MAJOR(inode->i_zone[0])==4) { if (current->leader && current->tty<0) { current->tty = MINOR(inode->i_zone[0]); tty_table[current->tty].pgrp = current->pgrp; } } else if (MAJOR(inode->i_zone[0])==5) if (current->tty<0) { iput(inode); current->filp[fd]=NULL; f->f_count=0; return -EPERM; } } /* Likewise with block-devices: check for floppy_change */ if (S_ISBLK(inode->i_mode)) check_disk_change(inode->i_zone[0]); f->f_mode = inode->i_mode; f->f_flags = flag; f->f_count = 1; f->f_inode = inode; f->f_pos = 0; return (fd); }调用open_namei
代码路径:fs/namei.c
int open_namei(const char * pathname, int flag, int mode, struct m_inode ** res_inode) { const char * basename; int inr,dev,namelen; struct m_inode * dir, *inode; struct buffer_head * bh; struct dir_entry * de; if ((flag & O_TRUNC) && !(flag & O_ACCMODE)) flag |= O_WRONLY; mode &= 0777 & ~current->umask; mode |= I_REGULAR; if (!(dir = dir_namei(pathname,&namelen,&basename)))//获取枝梢i节点 return -ENOENT; if (!namelen) { /* special case: ‘/usr/‘ etc */ if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) { *res_inode=dir; return 0; } iput(dir); return -EISDIR; } bh = find_entry(&dir,basename,namelen,&de);//通过枝梢i节点,找到目标文件hello.txt的目录项,发现不存在 if (!bh) { if (!(flag & O_CREAT)) {//确定用户确实是要新建一个文件 iput(dir); return -ENOENT; } if (!permission(dir,MAY_WRITE)) {//确定用户是否在user2目录文件中有写入权限 iput(dir); return -EACCES; } inode = new_inode(dir->i_dev);//新建i节点 if (!inode) { iput(dir); return -ENOSPC; } inode->i_uid = current->euid;//设置i节点用户id inode->i_mode = mode;//设置i节点访问模式 inode->i_dirt = 1;//将i节点已修改标志置1 bh = add_entry(dir,basename,namelen,&de);//新建目录项 if (!bh) { inode->i_nlinks--; iput(inode); iput(dir); return -ENOSPC; } de->inode = inode->i_num;//设置新目录项的inode bh->b_dirt = 1;//又设置了一遍,目录项所在的缓冲区b_dirt为1 brelse(bh);//释放缓冲区 iput(dir);//释放枝梢i节点 *res_inode = inode; return 0; } .... return 0; }调用new_inode创建新的节点(hello.txt)
代码路径:fs/bitmap.c
... struct m_inode * new_inode(int dev) { struct m_inode * inode; struct super_block * sb; struct buffer_head * bh; int i,j; if (!(inode=get_empty_inode()))//在inode_table[32]中获取空闲i节点项 return NULL; if (!(sb = get_super(dev)))//获取设备超级块 panic("new_inode with unknown device"); j = 8192; for (i=0 ; i<8 ; i++) if ((bh=sb->s_imap[i])) if ((j=find_first_zero(bh->b_data))<8192) break; if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) { iput(inode); return NULL; } if (set_bit(j,bh->b_data))//以上是根据超级块中i节点位图信息,设置i节点位图 panic("new_inode: bit already set"); bh->b_dirt = 1;//i节点位图的缓冲区b_dirt为1 inode->i_count=1;//i_count为1 inode->i_nlinks=1;//链接数为1 inode->i_dev=dev;//设备号 inode->i_uid=current->euid; inode->i_gid=current->egid; inode->i_dirt=1;//i节点b_dirt为1 inode->i_num = j + i*8192;//i节点号 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; return inode; } ...目前hello.txt的i节点(内存中)和i节点位图(缓冲区中)都已经更新。
调用add_entry,新建目录项
代码路径:fs/namei.c
static struct buffer_head * add_entry(struct m_inode * dir, const char * name, int namelen, struct dir_entry ** res_dir) { int block,i; struct buffer_head * bh; struct dir_entry * de; *res_dir = NULL; .... if (!(block = dir->i_zone[0]))//确定user2目录文件第一个文件块在设备上的逻辑块号 return NULL; if (!(bh = bread(dir->i_dev,block)))//将目录文件的内容放入缓冲区 return NULL; i = 0; de = (struct dir_entry *) bh->b_data;//赋值给目录项指针 while (1) { if ((char *)de >= BLOCK_SIZE+bh->b_data) {//暂不考虑 brelse(bh); bh = NULL; block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK); if (!block) return NULL; if (!(bh = bread(dir->i_dev,block))) { i += DIR_ENTRIES_PER_BLOCK; continue; } de = (struct dir_entry *) bh->b_data; } if (i*sizeof(struct dir_entry) >= dir->i_size) {//暂不考虑 de->inode=0; dir->i_size = (i+1)*sizeof(struct dir_entry); dir->i_dirt = 1; dir->i_ctime = CURRENT_TIME; } if (!de->inode) {//在数据块的中间某位置找到空闲项,就在该位置加载目录项 dir->i_mtime = CURRENT_TIME; for (i=0; i < NAME_LEN ; i++) de->name[i]=(i<namelen)?get_fs_byte(name+i):0;//将名字hello.txt存入目录项的结构中 bh->b_dirt = 1;//目录项对应的缓冲块b_dirt为1 *res_dir = de;//返回目录项的引用 return bh; } de++; i++; } brelse(bh); return NULL; }此刻,目录项所在的缓冲区已经更新。
总结:新建文件,建立了hello.txt的i节点,并设置了i节点位图,然后更新的目录项。i节点信息存放在inode_table(没有释放,i_dirt为1)中,i节点位图(常驻缓冲区,b_dirt为1)和目录项(已经释放,但是b_dirt为1)存放在内存缓冲区中。
最后别忘了,还会返回到sys_open继续执行,设置f_pos等参数。
5、写文件
write(fd,str1,strlen(str1))映射到sys_write来执行
代码路径:fs/read_write.c
int sys_write(unsigned int fd,char * buf,int count) { struct file * file; struct m_inode * inode; if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))//获取了file return -EINVAL; if (!count) return 0; inode=file->f_inode;//获取了inode if (inode->i_pipe) return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO; if (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; }代码路径:fs/file_dev.c
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; else pos = filp->f_pos;//此时为0 while (i<count) { if (!(block = create_block(inode,pos/BLOCK_SIZE)))//inode为hello.txt的i节点,block为0 break; if (!(bh=bread(inode->i_dev,block)))//返回新建的逻辑块对应的缓冲区 break; c = pos % BLOCK_SIZE;//此时为0 p = c + bh->b_data; bh->b_dirt = 1;//逻辑块对应的缓冲区b_dirt为1 c = BLOCK_SIZE-c;//1024 if (c > count-i) c = count-i;//c为4 pos += c;//pos为4 if (pos > inode->i_size) { inode->i_size = pos; inode->i_dirt = 1; } i += c;//i为4 while (c-->0) *(p++) = get_fs_byte(buf++);//把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 }
代码路径:fs/inode.c
int create_block(struct m_inode * inode, int block) { return _bmap(inode,block,1); }代码路径:fs/inode.c
static int _bmap(struct m_inode * inode,int block,int create) { struct buffer_head * bh; int i; if (block<0) panic("_bmap: block<0"); if (block >= 7+512+512*512) panic("_bmap: block>big"); if (block<7) { if (create && !inode->i_zone[block]) if ((inode->i_zone[block]=new_block(inode->i_dev))) {inode->i_zone[0]被设置为新的逻辑块的地址 inode->i_ctime=CURRENT_TIME; inode->i_dirt=1; } return inode->i_zone[block]; } .... }下面创建新的逻辑块,new_block
代码路径:fs/bitmap.c
int new_block(int dev) { struct buffer_head * bh; struct super_block * sb; int i,j; if (!(sb = get_super(dev)))//获取设备的超级块 panic("trying to get new block from nonexistant device"); j = 8192; for (i=0 ; i<8 ; i++) if ((bh=sb->s_zmap[i])) if ((j=find_first_zero(bh->b_data))<8192) break; if (i>=8 || !bh || j>=8192) return 0; if (set_bit(j,bh->b_data))//以上是根据超级块中逻辑块位图信心,对新数据块的逻辑块位图进行设置 panic("new_block: bit already set"); bh->b_dirt = 1;//逻辑块位图的缓冲区b_dirt为1 j += i*8192 + sb->s_firstdatazone-1;//逻辑块号 if (j >= sb->s_nzones) return 0; if (!(bh=getblk(dev,j)))//根据设备号和逻辑块号,申请一个空闲缓冲区 panic("new_block: cannot get block"); if (bh->b_count != 1) panic("new block: count is != 1"); clear_block(bh->b_data);//将刚申请的缓冲块中数据清零 bh->b_uptodate = 1;//已更新标志设置为1 bh->b_dirt = 1;//刚申请的缓冲区b_dirt为1 brelse(bh);//释放刚申请的缓冲区 return j; }返回到file_write继续执行。
总结:新建文件,建立了hello.txt的i节点,并设置了i节点位图,然后更新的目录项。i节点信息存放在inode_table(没有释放,i_dirt为1)中,i节点位图(常驻缓冲区,b_dirt为1)和目录项(已经释放,但是b_dirt为1)存放在内存缓冲区中。
总结:写文件,建立了新的逻辑块,并往里拷贝了要存入硬盘的数据,设置了逻辑块位图,也设置了hello.txt的i节点的i_zone[0]。逻辑块信息(已经释放,但b_dirt为1)存放在内存缓冲区,逻辑块位图(常驻缓冲区,b_dirt为1)存放在内存缓冲区。
数据从缓冲区同步到硬盘有两种方法。一种是updata定期同步,另一种是因缓冲区使用达到极限,操作系统强行同步。
具体代码如下
代码路径:fs/buffer.c
int sys_sync(void) { int i; struct buffer_head * bh; sync_inodes(); /* write out inodes into buffers */ bh = start_buffer; for (i=0 ; i<NR_BUFFERS ; i++,bh++) { wait_on_buffer(bh);//如果哪个缓冲区正在使用,就等这个缓冲区解锁 if (bh->b_dirt)//如果b_dirt为1 ll_rw_block(WRITE,bh);//将该缓冲块的内容同步到外设 } return 0; }代码路径:fs/inode.c
void sync_inodes(void) { int i; struct m_inode * inode; inode = 0+inode_table; for(i=0 ; i<NR_INODE ; i++,inode++) {//遍历所有i节点 wait_on_inode(inode); if (inode->i_dirt && !inode->i_pipe)//如果i节点的内容已经被修改过 write_inode(inode);//将i节点同步到缓冲区 } }代码路径:fs/inode.c
static void write_inode(struct m_inode * inode) { struct super_block * sb; struct buffer_head * bh; int block; lock_inode(inode);//先将i节点加锁,以免被干扰 if (!inode->i_dirt || !inode->i_dev) { unlock_inode(inode); return; } if (!(sb=get_super(inode->i_dev))) panic("trying to write inode without device"); block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + (inode->i_num-1)/INODES_PER_BLOCK;//i节点所在的逻辑块号 if (!(bh=bread(inode->i_dev,block)))//将i节点所在逻辑块载入缓冲区 panic("unable to read i-node block"); ((struct d_inode *)bh->b_data)//复制数据 [(inode->i_num-1)%INODES_PER_BLOCK] = *(struct d_inode *)inode; bh->b_dirt=1;//缓冲区b_dirt为1 inode->i_dirt=0;//所以inode的i_dirt为0 brelse(bh);//释放缓冲区 unlock_inode(inode);//解锁 }i节点的信息也被放到了缓冲区来同步。
到目前位置,所有的更新的信息都放入了缓冲区,i节点位图缓冲区内容放入硬盘的i节点位图区域,逻辑块位图缓冲区放入了硬盘逻辑块位图区域,i节点缓冲区放到了硬盘i节点区域,逻辑块缓冲区(目录项和要写的数据)放到了硬盘逻辑块区域。
Linux内核设计的艺术-文件操作,布布扣,bubuko.com
原文:http://blog.csdn.net/jltxgcy/article/details/20833861