虚拟文件系统
cache有对磁盘的cache是磁盘到RAM的cache,innode cache也是。还有cpu的cache相当于RAM在cpu上的cache。
write()->sys_write(VFS)->ext2等的write->物理
- 磁盘 分区:文件,数据,交换区域
文件系统:
ext2 引导块,超级块(包含块大小等),i节点(可对应多级块3IPB,2IPB等),数据
崩溃恢复,元数据不一致,检查要遍历=》日志文件ext3,ext4- 文件,目录(目录项缓存),inode,mount point
file {链表,pathh file_operations}
目录包含文件名,inode编号。目录自身的Inode中的类型不同,rename仅操作目录条目不动文件。
文件名到Inode有多个。硬链接指向一个Inode。软链接指向文件名 - proc
虚拟文件可以向用户呈现内核中的一些信息,也可以用作一种从用户空间向内核发送信息的手段.开发新的:可加载内核模块(LKM)。存在内存中国,动态创建
ext2数据写入
每次更改磁盘会写inode和data位图(超级快),inode数据,data数据
完成附加操作的方法是打开文件,调用lseek()将文件偏移到文件末尾,然后在关闭文件之前对文件发出一个4KB的写入。我们还假设在磁盘上使用的是标准的简单文件系统结构,类似于我们前面章节的文件系统。这个小小的例子包括一个inode位图(只有8位,每个inode一个),一个数据位图(也是8位,每个数据块一个),inode(总共8个,编号为0到7,分布在四个块)和数据块(总共8个,编号为0到7)。下面是这个文件系统的图示:
崩溃恢复要fsck扫超级快,元数据块,数据块
日志记录型文件系统
包括Linux ext3和ext4、ReiserFS、IBM的JFS、SGI的XFS和WindowsNTFS。思想来自数据库的redo log
ext3在2基础上加一个日志块
1.日志记录元信息,数据变化
我们首先将TxB、I[v2]、B[v2]、DB和TxE写入日志。当这些写入完成时,我们将通过检查点来完成对I[v2]、B[v2]和DB的写入。
TxB、I[v2]、B[v2]、DB 可以正常发,因为顺序会乱,跟调度相关。为了确保TxE的写入是原子的,应该将它变成一个512字节的块
1).日志写入:将事务的内容(包括TxB、元数据和数据)写入日志;等待这些写入完成。
2).日志提交:将事务提交块(包含TxE)写入日志;等待写入完成
3).检查点: 将更新的内容(元数据和数据)写入它们对应的最终磁盘位置。
2.只记录元信息
1).数据写入:将数据写入最终位置;等待完成(等待是可选的;详见下文)。
2).日志元数据写入:将BEGIN块和元数据写入日志;等待写入完成。
3).日志提交:将事务提交块(包含TxE)写入日志;等待写入完成;完后后事务(包括数据)就表示已经提交了。
4).检查点元数据:将元数据的内容写入文件系统中的最终位置。
5).释放:稍后,在日志超级块中标记事务。
文件查找
文件查找过程:
● 路径解析
● 读取目录项(dentry)内容
● 根据文件名搜索目录项,获取inode位置
● 读取inode信息
● 定位所要访问的块位置
● 访问相应数据块
为描述方便,将目录项和inode内容统称为元数据。通常,元数据和文件的数据内容存放在不同的区域。
在分布式文件系统中,管理区和数据区一般还分散在不同的物理机器上。
小文件问题:
● 元数据和文件数据一般是分区域的,一次IO访问将实际产生多个IO请求
● 元数据相对较大,缓存代价比较昂贵
● 目录项及目标数据块的检索效率
● 频繁增删改带来的碎片化问题
块IO
硬盘等,随机访问的,区别于字符设备只能顺序访问
- 块缓冲区,已经合成一个页缓存
- 调度 块IO请求队列(一个块设备一个)
linusx电梯 合并请求,临近插入
最终期限 超时时间(读500ms,写5s)三个队列:读FIFO/写FIFO/排序队列同linus=>超时派发队列
预测IO 超时后等几ms,相邻合并
完全公正,每个进程一个队列
空IO,只合并相邻的
sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。fsync等磁盘结束返回
进程地址空间
连续虚拟地址
mm_struct 分配,撤销……{内存区域vm_area_struct红黑树和链表,pgd,所有mm_struct链表,每段起始地址等}
vm_area_strict区间地址等。
虚拟地址=》物理页面 三级页表(pgd,pmd,pte)硬件效率有限,TLB缓存
在堆上分配,sbrk。改变programm break位置,进程可以访问这部分地址,若RAM未分配,内核会在进程是首次访问这些虚拟内存地址时自动分配新RAM页
malloc,free内找/分割,不够sbrk
页缓存(磁盘和内存ms/ns的差距)
页告诉缓存是RAM组成,对应硬盘上的物理块(扇区整数倍但比页小,一般512B/1kb/4kb),
linux 写缓存,标记脏,脏页链表, 回写进程刷会磁盘
缓存回收 LRU 双链(活跃/非活跃)
address_space 每页一个
页内搜索 基树。回收时要反向检查引用的项。根据页内偏移起终范围找vma,起点基树,终点堆,很多个共同引用优先搜索树(堆+基树)。
回写线程flusher 一个设备一个线程,每个收集自己的。以前固定线程数,当一个设备阻塞会阻塞其上个所有线程。因为拥塞发生次数太频繁改一个设备一个线程。
若页属于一个文件(该文件存放在磁盘上文件系统中,如ext4),那么页的所有者就是文件的inode;并且对应的address_space对象存放在VFS inode对象的i_data字段中。
fd与磁盘的关联
fd->file->path->dentry->inode->address_space->page->buffer_head->磁盘块号
https://segmentfault.com/a/11...
IO分类综述
1.磁盘文件,内核有cache,不需要等实际的写入,读取cache没有会让进程休眠,同时读入。所以没有阻塞的概念呢。除非inotify的文件,read无事件时阻塞。可以用信号IO形式。(vfs->cache->disk。DIRECTIO直接VFS->DISK。SYNC模式CACHE后阻塞的DISK。DISK向下有IO等待队列)
read->cache不在page_cache_sync_readhead可能会预读,进程挂起恢复还是从cache读。写不在add_to_page_cache_lru。
DMA是磁盘到cache不需要CPU
directio generic_file_direct_IO取代page_cache_sync_readhead,__blockdev_direct_IO() 会一直等到所有的 I/O 操作都结束才会返回,因此,一旦应用程序 read() 系统调用返回,应用程序就可以访问用户地址空间中含有相应数据的缓冲区。但是,这种方法在应用程序读操作完成之前不能关闭应用程序,这将会导致关闭应用程序缓慢。写要检查缓冲区有先刷回去再写。
2.其他FIFO,套接字,管道,终端,伪终端可以设置阻塞/非阻塞。非阻塞多路复用:select/poll/epoll,信号驱动.以上都需要同步IO操作,即只是告诉就绪(除非是AIO)。读写的过程还是一样的,看各种的自己了比如套接字就是send buf而不是磁盘的cache了。
select(nfds,readxx) nfds比要检查的fd大1,read等感兴趣位图和结果位图,要遍历
什么是就绪?IO不阻塞就是就绪,普通文件一直不阻塞,不能用
select和poll都是水平触发
信号驱动IO IO/文件nofity 边缘触发
epoll 可边缘/水平。
边缘:注意不再通知,还要注意防止饥饿。维护一个就绪文件描述符列表,读到EAGAIN移除,循环读取处理
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。