Linux IO 子系统
传统IO(读/写)
- CPU copy:用户buffer => 内核buffer ----------------------------------------> 拷贝* 1
- DMA copy:内核buffer => 硬件 ------------------------------------------------>拷贝 * 1
- 上下文切换:用户态 => 内核态 => 用户态 ------------------------------------->上下文切换 * 2
PageCache技术
Linux IO 栈
- 文件系统层:治理pagecache
- 块层:治理块设施的IO队列,对IO申请进行合并、排序
- 设施层:通过DMA和内存进行交互,负责数据传输
IO形式:
- 传统 Buffer IO:磁盘 => pagecache => 用户空间 -------------------------------------------------------------------------> 拷贝 * 2
- mmaped- IO:磁盘 => pagecache =>映射到用户空间,把pagecache映射到用户的地址空间外面 -----------> 拷贝 * 1
- Direct IO:用户态和块IO层做对接,放弃了pagecache,从磁盘间接向用户态拷贝数据;益处:快,DMA拷贝,本人负责cache ----> 拷贝 * 1
- Buffer IO:偏移 + 长度
- mmaped IO:数据按页对齐
- Direct IO:读写是底层存储块设施大小的整数倍
Linux内存
地址空间
- 分段机制:逻辑地址 => 线性地址 GDT(段描述符)
- 分页机制:线性地址 => 物理地址
碎片
搭档零碎:将闲暇页分为11个链表,每个链表中页块中间断页的大小别离是1、2、4 .. 1024
申请:申请 4 ,看4
- 有:调配
- 没有:看8,分成两个4,将另一半挂到块大小为4的链表下
- 开释:看搭档是否闲暇,是则合并
- 劣势:合并时地址只有一位不同,十分疾速定位
slab零碎:
- slab 层有三个slab链表,slab-full、slab-partial、slab-empty
- 每个链表有多个page,每个page都分为若干个object
劣势:
- 将频繁应用的对象缓存起来,缩小调配、初始化和开释对象的工夫开销,如PCB、inode、lock
- 缩小搭档零碎调配小块内存造成的外部碎片
Linux 过程与线程
- fork() + exec() = spawn()
- COW => 创立开销只有复制页表和PCB块
- fork() => clone(零碎调用) => do_fork()
do_fork() => copy_process()
- 拷贝 task_struct、内核栈
- 清零
- 共享关上的文件描述符、信号处理函数
- 线程创立指定额定参数:
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND