IO读写+Epoll多路复用,计算机底层解析
更具体的解析视频地址:https://www.bilibili.com/video/BV11K4y1C7rm?from=search&seid=1779865754374798584&spm_id_from=333.337.0.0&vd_source=12d06e602c3462c026d1a4781241f2d4
程序是如何调用 内存+磁盘+CPU+网卡的
1.内存:
一个简单的C#程序在硬盘里面就是文件,只有被加载到内存中才会有主线程,变成一个进程程序
而电脑开机第一个夹菜到内存里面的就是Kernel(内核)
Kernel(内核) :
相当于一个管理,管理计算机的网卡磁盘等硬件 而Kernel(内核)进入到内存第一件事就是创建一个GDT(全局描述附表)
GDT:
把Kernel(内核) 进程所在的内存空间和其他进程的内存空间划分出来 相当于我们的内存里面就存两部分数据 Kernel(内核) 内存+其他程序的内存 +其他如DMA
为什么要什么划分:因为Kernel(内核) 管理了计算机的硬件等,如果不划分 其他进程去随便操作里面的东西就会造成黑屏蓝屏等问题
GDT会开启保护模式:使其他进程是不能访问硬件资源(磁盘网卡等)
CPU:
指令集概念,指令集又有rang0 rang1 rang2 rang3的概念
普通进程的指令集的级别是3 Kernel(内核) 的指令级别是0
所以CPU是从内存里面找到进程读取他们的指令集
有了上面的概念呢解析 那么我们一个普通的进程想要进行IO操作,但是又有GDT又不能访问 怎么办?
Kernel(内核)是能直接访问硬件资源,但是GDT又不能普通进程访问Kernel(内核) 的内存空间,于是Kernel(内核) 对外暴露了一个接口使其能访问(系统调用软中断,kernel提供一个syscall),
但也就造成了我们的进程每次想要访问磁盘资源都会去请求Kernel(内核) 的接口 IO成本太高了,如果一个服务进程 有10W个客户端来链接,但是只有两个人发了信息,还是得请求10W次这样就造成了极大的浪费 复杂度也是O(n)O1次请求(n=10W)
所以我们要解决这个问题 于是 就有了Epoll IO多路复用
Epoll 返回的是IO状态 读写是需要程序自己完成的
IO Redis
Redis worker单线程 但是使用的又是epoll多路复用器 用epoll告诉redis 即使有十万个客户端 也只需要读那几个
kafak 和kernel 为了减少对kernel系统调用 使用了 kernel的缓存页 kafak+kernel共享一部分内存 然后把数据刷入到磁盘, 所以kafak只需要把数据push到自己本地的内存 kernel就能把数据刷到磁盘,避免kernel自己系统调用,有缓存有会有数据丢失问题
零拷贝:sendfile-系统调用 在kernel里面 前提是数据不需要加工,已经在内存片区里面 使用sendfile的参数 输入输出就行
本文来自博客园,作者:12不懂3,转载请注明原文链接:https://www.cnblogs.com/LZXX/p/16557430.html