前面实现了线程池,如果我们使用线程池就是有一个连接到来就把它丢进工作队列,然后让线程竞争,在这个过程中又会产生一个问题,我们浪费了主进程,它只是干了一件把任务丢进线程池工作队列的操作,然后就啥也没干了,所以我们把IO操作单独拿出来给主线程来干,线程池里的线程就只干解析的事情。
一个简单http_server的实现(4)-线程池
为什么要线程池
之前实现的那个简陋的服务器只能接受一个连接,这显然是不行的,所以我们可以用多线程来解决这个问题
但是如果来一个连接就开一个线程那么连接很多的时候就会有开很多的线程,还是会影响性能,所以需要线程池,即固定最大可以开的线程,然后将线程管理起来,来一个连接就把它加入工作队列,然后呢让空闲的线程去竞争这个任务。
一个简单http_server的实现(3)
http请求
在可以进行网络通信之后,我们需要知道浏览器和我的服务器之间通信的规则
首先浏览器在和我的服务器建立通信之后会发出一个http请求到我的服务器
一个http请求的组成为:一个请求行,后面跟随零个或多个请求报头,然后是一个空的文本行来结束报头
后面接着是请求体
然后每一行的结尾都是\r\n
,空行就是只有\r\n
请求行
请求行的格式为<method> <url> <version>
method就是请求的方法包括GET,POST,OPTIONS,HEAD,PUT,
DELETE,TRACE等,这次就先实现最基本的GET方法,报头就先忽略
url就是资源定位符
version就是http版本
一个简单http_server的实现(1)
最近在学习网络编程的知识,所以准备实现一个http服务器,写博客来记录一下学习的过程
RIO
RIO是csapp中提到的一个健壮的I/O包,为什么要使用这个来进行文件的读写,是因为接下来的socket编程中不适合使用c标准I/O
从零实现一个操作系统-day14
虚拟内存管理
虚拟内存就是对每一个进程而言,对它来说它认为它独占所有4G内存,进程内的地址就是以这4G的虚拟内存来表示的,当要执行时,cpu通过分段机制和分页机制将虚拟地址转换成物理内存地址进行访问。同时一个进程也不是所有的页都在内存中,只有部分在内存中,当需要的页不在内存时产生一个缺页中断,然后进行调度,将需要的页调入内存
从零实现一个操作系统-day13
物理内存管理
由于之前采用了平坦模式,也就是整个内存一段,所以这里就不用管段的处理了。
分页
参考:https://www.cnblogs.com/peterYong/p/6556619.html#_label8
分页就是将主存,程序执行的线性地址空间,还有外存都在逻辑上划分位固定大小的块,这样的好处是降低内存碎片的影响,每一页的大小不能太大,也不能太小,x86采用的是一页4KB,4GB的主存就可以分为2^20个页
对存储空间进行逻辑划分之后,寻址时就要由相应的映射,对于每一个进程来说都有这么一个映射来将自己的逻辑地址映射到物理的地址上,这个映射的结构就是页表,页表也存放在内存中,对于一个进程来说,如果要映射全部4GB的空间需要32/8*2^20=4MB的页表,如果进程多了这会消耗大量内存,显然不合适
从零实现一个操作系统-day12
中断控制芯片的初始化
参考:https://blog.csdn.net/longintchar/article/details/79439466
中断控制芯片8259A由主从两个芯片级联而成
从片的输出接在主片的IRQ2上,所以一共可以接受15个设备的中断信号,中断控制芯片的作用就是管理外接设备的中断
首先要对芯片进行初始化,初始化该芯片就是初始化一组寄存器ICW寄存器
当地址线的A0=0时主片的端口的0x20,从片的端口是0xA0
从零实现一个操作系统-day11
IDT
昨天弄完了GDT,今天来弄IDT,IDT就是中断描述符表。和GDT类似。
中断就是一个电信号,它可以打断cpu当前的操作,让cpu执行你指定的中断处理函数,等执行完,cpu会回去继续执行它之前的操作,就像你移动鼠标,就是产生了一个中断,让cpu先帮你移动鼠标。
既然打断cpu让他执行你指定的中断处理函数,那么中断就是有编号的,让cpu知道应该执行哪一个中断处理函数,intel的处理器支持256个中断,也就是有0-255个中断编号
和GDT一样,有中断描述符,大小为8字节,也是放在内存中,由IDTR寄存器保持IDT的位置和大小
从零实现一个操作系统-day10
保护模式
保护模式是从80386时代引入的,之前的8086只有实模式,实模式有1MB的寻址空间(2 ^ 20),而保护模式有4GB的寻址空间,且支持分页等操作
保护模式对内存段的访问做了限制,对于内存段的性质和允许的操作给出了定义,所以每一个段有一个段描述符,占8个字节,段描述符有很多,只能放在内存里,其中最重要的全局段描述符表(GDT),GDT的相关信息存在cpu的寄存器GDTR中
GDTR有48位,其中0 - 15位表示GDT的边界,也就是GDT段的大小,16 - 47位这32位存的是GDT的基地址,所以GDT段的大小最多为65536字节,也就是可以存8192个段描述符
也就是我们通过GDTR寄存器获取GDT的位置和大小,然后GDT中存储了所有段描述符
cup加电后工作在实模式,而进入保护模式后就需要GDT和GDTR,所以我们需要在进入保护模式之前就设置好GDT和GDTR,但是实模式只有1MB的寻址空间,所以一开始的GDT只能放在这里,进入保护模式后还可以更改
从实模式进入保护模式只需要修改CR0寄存器的第0位,为0表示实模式,为1表示保护模式
具体的分段策略
分段是cpu为了兼容以前的程序所保留的,所以我们一般绕过分段直接用分页技术,而绕过分段的方法就是把4GB的空间分成一段,整个虚拟地址的其实位置是0,长度为4G,这样偏移地址和段机制处理后的地址是同一个数
当然并不是给所有的段相同的描述符,数据段和代码段是不同的描述符
段描述符的结构
参考: https://blog.csdn.net/longintchar/article/details/50489889
看这个,就不搬运了