为了对n个设备使用总线的请求进行裁决_各种模型下的web请求处理

多进程模型

apache的工作:

ac8e210bdb4591ae536c78f6670212fe.png
apache多进程模型

在用户控件中有两组进程。有着控制权限的httpd进程,监听80套接字端口,随时接受用户的请求。当有用户请求来了,生成一个子进程去处理请求,其本身不处理任何请求,httpd是管理这些进程的。做到一个进程处理一个用户请求。(早期的web多进程模型)

多进程模型带来的问题:

(1)进程是一个非常重量级的资源实体,本身的开销很大,是一个单独要在cpu上调度的单位。需要分配内存资源,在一定程度上要分配cpu时间片,内核还需要调度这些进程,导致大量的进程切换。为什么会有大量的进程切换?cpu内核数是有限的(假设只有一个),在某一时刻,真正正在处理的只有一个进程,所以需要轮流执行(假设每个进程执行10ms)。由内核处理进程的切换,内核内部自己有程序(eg:进程调度程序),观测每一个进程的属性,发现接下来需要执行的进程(这里拿pid为2的进程举例),将2号进程唤醒,将2号进程载入到cpu的各种寄存器中来,将cpu的运行指针指向2号进程的地址空间,然后内核自己退出(睡眠),2号进程运行,10ms后进程运行结束,内核重新工作,将2号进程转入睡眠状态,依次类推。所以切换非常频繁,消耗大量时间。在内核空间中消耗的时间都是额外的开销。

(2)当多个请求请求的内容是相同的资源,那么每个进程的进程空间会有很多重复的数据,内存使用效率低。

具体的工作流程:

0132ce3ddf8d3fb8332b41462d9ccbfe.png
一次请求的过程

一个请求过来,一个进程处理,用户进程无法访问硬件资源(硬盘,数据库),假如说用户请求的是一个页面。通过系统调用,转入内核模式,该进程转入睡眠状态(这里的睡眠其实就是阻塞,产生了IO调用,等待内核返回资源),等待的过程中进程是不能给用户响应(称为不可中断睡眠)进程即处于wait态。

内核调用驱动程序硬盘取数据(因为要调用驱动程序去磁盘上取数据,所以此时cpu是没有空闲的是一直在为当前IO工作),将数据加载到放到内核自己的内存空间中(buffer,cache)。进程是不能直接访问内存空间的,所以将数据复制到进程的空间,进程才能拿到数据,并响应请求。

图中的DMA是什么?

直接内存访问(Direct Mmemory Access)。是一个芯片 ,有访问内存的能力,有复制数据的能力(有数据传输占据系统总线的能力),控制系统总线,数据总线,控制总线的能力。内核告知DMA需要的数据的起止地址。当DMA工作的时候,cpu就可以空闲出来,可以去处理其他任务(比如将已准备好数据的进程相应给用户),但是当DMA完成将数据从磁盘加载到内存之后,信号告知cpu,cpu会立即中断当前处理的进程,来控制内核将DMA准备好的数据复制到进程空间中。

多线程模型

线程:轻量级进程(Light Weight Process)LWP。是进程内部运行的子单位。linux不支持原生态的线程,linux将线程看做进程对待,只不过跟进程有一些区别。一个进程中有多个并行执行流(线程)。

进程是一个执行流 。当有了线程之后 就是多个并行的执行流,这些线程可以共享进程的数据区域,每一个执行流是独立的实体。所以同理,当一个请求过来,一个线程响应,同样是走上面的取数据的流程,当另一个请求过来时,如果是请求相同的资源,此时数据已经在进程空间中存在这,这个时候就不用重复的系统调用去取数据了。

77e34fe332a49189ba45fcdbb7632d9b.png

每个线程响应一个请求带来的好处:

线程的切换仍不可避免,但是切换属于轻量级;线程之间可以共享进程的资源;对内存的需求就比进程小了很多。其次要注意,线程之间的资源争用依然存在。一个线程正在写资源,另一个线程就读不了资源,但是读不了,就等待(忙等:每隔1ms就来询问,不退出cpu,一直占用cpu (自旋锁 spin lock),闲等:切换出去,不占用cpu)。所以如果一个进程中线程过多,线程快速切换时,会带来线程抖动。

一个线程N个请求

一个线程N个请求会带出很多概念。

首选明确一个线程处理多个请求的时候,是不能阻塞的,一旦阻塞后面的请求都处理不了。当线程处理1号连接的时候,需要访问磁盘资源,线程发起系统调用,该连接就等待IO完成,此时线程去处理后面的连接,当处理到3号连接的时候,1号连接的IO准备好了,线程怎么唤醒1号连接?

也可以这样问,我们知道当一个连接进来之后,为了给他响应资源,那么这个连接就是出于等 待状态(非活动状态)。连接是在内核中,不是在线程中,连接是通过网卡进来的,跟TCP/IP相关的,TCP/IP协议栈的相关的内容都是需要内核处理的,那么线程必须要和内核联系才能唤醒这个连接,怎么联系呢?

同理多进程模型下,一个进程为了响应请求发起系统调用,等待磁盘IO完成,那么进程就阻塞了,cpu就空闲出来了,处理下一个进程,那么磁盘IO完成之后,内存怎么通知进程IO准备完毕呢,或者说第一个进程怎么知道自己的IO准备好了?

1a8ed8dbc1004bfcb7ef240ee707cc7d.png

解答:

内核会输出一种数据结构到用户空间,内核每一次都挨个扫描一下每个IO的文件描述符,而后将他从内核空间输出给到用户空间,这种方式叫做select 。最多支持1024个连接(早期,后面有poll[没有限制],epoll比poll性能更好,IO相关的可以后续的我总结的笔记)。形象理解,来一个进程就准备一个灯泡,灯亮了就说明io好了。假如说一个io准备好了,那么内存每次都要执行一次输出这个一排灯泡,内核控制哪个灯能亮哪个灯不能亮,每一次都要输出一遍,不输出进程是无法理解的。这就是通知机制。

说回单线程模型,因为一个线程多个请求的时候是不能阻塞的,一但阻塞后面的请求都处理不了,所以在IO模型上要使用异步IO即AIO 。不能说请求没完成就阻塞, 用户即等待状态。由此引出多路IO机制:(IO复用)解决多个用户来请求,又能让用户知道自己的要请求的资源是否准备就绪的机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值