首页 > 技术文章 > C10K问题和多进程模型

saintdingspage 2019-06-15 08:56 原文

收录编辑来自马哥教育相关课程

  • 内核空间的相关程序在调度用户空间里的进程的时候,也占用了cpu资源......

nginx可以作为两种类型的反向代理 http 和smtp(mail)

C10K问题,

当一个主机的连接数过多的时候,单独一片网卡,响应在一个套接字上的请求,如何通过一个进程,或一组线程对请求提供服务? 显然,阻塞模式就太糟糕了

  • 多进程模型
以apache为例, 监听在80套接字上的http进程,接收用户请求,通过生成子进程响应客户请求,销毁用户空闲子进程(做到了专客户专进程的效果)
内核要调度进程,cpu要分配给时间片(但cpu的资源必定有限),
为了让访问者感受不到阻塞,内核调度程序对进程要进行切换 分配给进程2的时间片一旦完成,就把进程2转入睡眠(阻塞)状态,
再执行进程n.....如此往复执行 但某一时刻真正执行的只有一个进程,通过切换,客户感受不到等待,切换的工作由内核负责。
然而内核空间的相关程序完成这种用户空间的进程调度,也是需要占用cpu资源的,但实际问题并未得到解决(进程如果过多,那么消耗在切换的时间和cpu资源就会激增,但对解决实际问题无用)
例如,请求一个网页
实际上就是用户请求访问服务器硬盘上的一个网页(html php......皆有可能),然而用户空间的进程并不能直接访问,需要通过内核空间的调度程序去完成,在内核相关程序完成网页的读取和返回这段状态,
用户空间的进程处于睡眠状态(wait)其实就是阻塞,如果内核未完成读取网页并返回结果,那么即使唤醒这一请求,也无助于解决什么问题,因而这一状态也称之为 不可中断睡眠

 物理内存,分为两部分,内核空间(buffer,cache) 进程空间(内有多个进程运行)(数据读取完毕,暂时放进内核空间,接下来复制到进程空间,供进程访问)

数据从硬盘加载到内存的过程,内存一般是要分页的,如果不分页那可能是堆,数据从磁盘加载到内存的页上面,每次I/O加载一个页面的数据,磁盘一般是分块的,每块1k,2k,4k不等,假设要读取的数据内存大小为4K,
那么根据页的大小,一次I/O读几个块,完成从硬盘数据到内存的加载(每块为2k,一次I/O读取两个块
每块为1K,一次I/O读取4个块......)
  •  DMA(direct memory access)
还以文件加载为例,如果文件大小需要占据10个内存页,磁盘上每个块大小2k,根据上面的论述,一次I/O要填充一个内存页,那么可以得出,有20k大小的文件数据需要加载,读取哪些磁盘块,加载到哪个内存地址,
都需要CPU参与决策!加载到内存页仅仅是处于缓冲的需要,最终是要映射/复制到进程可以访问的内存空间中去,接下来,如何选择空闲的内存空间,从内存的哪一部分开始分配,也都需要CPU参与决策,另外,从磁盘
哪一部分加载数据,需要驱动程序参与,而驱动程序也需要cpu资源得以运行,这些行为都发生在内核空间,因而我们说加载一个文件到内存,内核运作十分繁忙,那么降低内核对CPU的占用,尽可能让cpu处理其他程序
(进程),DMA机制应孕而生
  • DMA工作过程
DMA是一个主板上的芯片,DMA机制下,文件加载过程是,内核找到一片连续的缓存空间,把起始地址给DMA,该芯片是一个控制芯片,具有CPU的部分功能:访问内存,复制数据,有传输数据----占据系统总线的能力,
有控制系统总线,数据总线,控制总线的能力;cpu分配完连续缓存的起始地址,并钦定完读取哪些磁盘块之后,就把总线控制权让渡给DMA芯片,DMA读取磁盘数据加载到内存,这一过程占据数据总线,
DMA发送指令读取第几个磁盘块,这一过程占用控制总线,读到哪个内存地址,也涉及占用数据总线

这样一来,cpu有更多的精力处理请求进程,而把加载数据的功能让渡给DMA履行,请求到数据的进程直接通过网卡和用户进行交互,而无需占用PCI总线

  • DMA加载数据后
DMA完成加载数据后,产生中断,通知CPU(插入信号),DMA进入睡眠状态,由内核把加载完成的数据复制给请求进程,

这就是操作系统难以研发的原因-----涉及了复杂的仲裁机制

综上所述,内核空间根据用户空间的请求读取相应数据后,会先放到内存的内核空间,再复制到内存的进程空间以供请求进程访问,那么在多个请求请求同一个页面的业务场景下,虽然可以通过缓存,加速对

其他请求的访问速度,但是进程空间中会有多份相同的数据......这就是多进程模型不足的地方,冗余数据!

  • 总结---多进程模型
线程切换过多,占用cpu资源
各进程地址空间独立,很多重复数据,内存利用效率低

 

推荐阅读