Linux操作系统1
用户态和内核态的区别用户态和内核态是CPU硬件层面的两种运行模式核心区别在于“权限大小“和”资源访问范围“CPU指令与内存读写。1、权限级别不同内核态拥有最高特权级别Ring 0可以运行所有CPU指令访问所有的内存空间直接控制所有硬件设备。用户态拥有最低的特权级别Ring 3)禁止执行特权CPU指令关机、挂起进程、修改页表只能访问自己的进程内存空间禁止直接操控硬件。2、内存空间隔离内核态拥有独立的内核空间所有进程的内核空间都映射同一块物理内存空间用户态进程不可见不可访问用户态拥有独立的用户空间用户态拥有的是虚拟地址空间彼此隔离不一致一个进程的崩溃不影响其他进程3、容错性内核态崩溃意味着整个操作系统宕机可能出现蓝屏等…用户态崩溃进程退出操作系统回收资源系统依旧可以运行4、用户态-内核态用户态通过特定的门触发CPU中断陷入内核系统调用主动请求内核服务比如read()、write()读写文件send()、recv()网络IOmalloc()申请空间等本质上是CPU执行了某指令int 或 syscall让CPU自己触发中断硬件中断网卡收到远端发送的数据键盘敲击输入…是硬件中断通过中断控制器通知CPU。运行异常CPU运算时发现除0CPU执行时发现页表还没分配物理空间缺页异常用户态-内核态是有开销的具体要做几件事上下文切换寄存器内容替换CPU缓存TLB快表失效最重要的一点等。减少系统调用能够提高程序运行的性能比如使用内存池避免频繁申请内存比如epoll进行批量操作将IO操作集中。5、栈空间内核态有内核栈Linux下是4KB或者8KB用户态使用用户栈通常8MB可以调整操作系统本质上是一批描述资源的数据结构中断处理函数。用户态和内核态本质上是CPU在执行进程的指令时的不同状态当进程执行的指令只访问用户空间定义的数据不涉及对操作系统管理的资源的操作时就是用户态当执行的指令访问操作系统空间定义的数据或者访问操作系统管理的资源文件、硬件、内核数据结构等时就是内核态。系统调用理解了用户态和内核态的区别之后对于系统调用的理解自然也就清晰了。1、为什么需要系统调用第一为了隔离操作系统是一切资源的管理者对于一些不应该由用户程序直接访问或者操作的资源应该请操作系统代劳这样能够保证系统的安全和防止恶意程序随意篡改系统数据和损坏硬件。第二为了统一抽象Linux下一切皆文件那么对于磁盘、显示器、键盘、网卡等等不同的硬件设备的读写我们都有一个统一的接口read()ANDwrite()它到底是怎么实现的呢structfile{...conststructfile_operations*f_op;//文件操作用来关联系统调用和驱动程序...};structfile_operations{//读取ssize_t(*read)(structfile*,char__user*,size_t,loff_t*);//写入ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);};2、怎么实现的当CPU执行int 0x80或者syscall)时触发软中断陷入内核态拿着系统调用号去系统调用表中查找对应的系统调用方法比如说read()系统调用然后这个系统调用内部就会调用对应文件的操作比如file-f_op-read(...)。操作完成之后会返回用户态执行下一条指令。3、常见的系统调用进程控制fork()创建子进程exec()执行新程序、exit()结束进程文件操作open()打开文件read()文件读write()文件写close()文件关闭设备通信socket()网络套接字connect()连接网络信息维护getpid()获取进程IDtime()获取系统时间由于系统调用会触发中断陷入内核涉及上下文切换和缓存失效等开销比较大所以高并发服务中尽量让IO处理更加集中而不是频繁陷入内核导致性能降低。Linux内核和Windows内核的区别从内核架构上来说Linux把进程调度、内存管理、文件系统、设备驱动都集成在同一层面好处是这样不同服务之间的沟通效率高不需要进程间通信。坏处是一旦某个模块出错容易导致系统全面崩溃。Windows则是把不同的服务分到不同的层面微内核核心在最顶层各种系统服务隔离在不同的层次优点正好对应Linux的缺点也就是抗风险能力较强不会因为某个服务的出错导致系统全面崩溃。缺点就是效率的损耗不同的系统服务间需要通信带来了额外开销。从软件生态来说Linux是开源的系统内核可以随意组合不同的系统服务比如图形化界面其他新的硬件驱动等。代价就是开发学习成本高。Windows是闭源的商业化系统市面上外设可以自动识别代价就是内核无法修改对于嵌入式不友好比如没法塞进路由器中。从日常的配置说Linux的设置都写在配置文件中想要修改IP地址或者其他什么配置只需要修改配置文件即可。备份后适合写脚本批量自动化管理Windows的设置汇总在数据库里好处是图形化界面对新手友好坏处是结构复杂并且备份不直观。如果是服务器追求极致性能使用Linux开源透明且可操控性强。如果想省心、桌面游戏等使用Windows兼容性强用户基数大。物理地址逻辑地址虚拟地址/线性地址的关系mov eax, ds:[0x1234][0x1234]是偏移量CPU做几件事第一步从ds寄存器中取出段选择符比如5第二步拿着段选择符索引去内存的GDT全局描述符表找到段描述符第三步段描述符中记载下列信息基地址假设是平坦模式的0x00000000段界限确保偏移量没超检查类型检查特权级别Ring 0/3第四步计算地址——线性地址段基地址0偏移量0x1234线性地址/虚拟地址经过页表映射找到物理地址。线性/虚拟地址————物理地址structtask_struct//进程/线程描述{structmm_struct*mm;//用户进程-》用户空间内核线程-》nullstructmm_struct*active_mm;//内核线程可以使用任意进程的地址空间};structmm_struct{//页表pgd_t*pgd;//指向第一级页表MMU进行物理地址转换时需要加载到CR3/TTBRx寄存器的物理地址structvm_area_struct*mmap;//指向虚拟区间链表structrb_rootmm_rb;//红黑树快速查找vm_area//代码段数据段堆栈段共享区等起始和结束地址unsignedlongstart_code,end_code,start_data,end_data;//代码段数据段unsignedlongstart_brk,brk,start_stack;//栈和堆unsignedlongarg_start,arg_end,env_start,env_end;//...};//除了程序主体和文件映射外还用来分配内存线程的私有栈共享内存等都要分配vm_area_structstructvm_area_struct{unsignedlongvm_start;//起始unsignedlongvm_end;//结束structfile*vm_file;//映射的文件————只有一个没错这就是为什么要红黑树。};MMU是集成在CPU中的硬件它根据寄存器中的页表的地址拿着虚拟地址去查询页表先查询快表再查询多级页表如果页表项中不一定是叶子页表也可能是上级、中间…的物理地址为空存在位p0就触发缺页中断执行缺页中断处理函数。如果物理地址不为空存在位p1判断权限位读/写/执行和当前CPU特权级用户态/内核态是否匹配本次访问请求。权限不足比如试图写入只读内存MMU触发保护性缺页中断访问异常交给操作系统处理。权限通过取出物理页框号与虚拟地址中的偏移量拼接计算出完整的物理地址。随后将该虚拟——物理映射关系缓存在快表中更新页表项中的“访问位”辅助操作系统进行页面置换如果写入更新“脏位”辅助操作系统判断该位置和磁盘是否一致决定换出时是直接丢弃还是先刷新到磁盘。最后CPU拿到物理地址进行操作。CPU使用率和Load平均值CPU使用率和Load平均值是衡量系统负载的两个指标描述不同的维度。CPU使用率单位时间内CPU处于非空闲时间的百分比。反映CPU繁忙程度Load平均值特定时间段一整块时间内处于R可运行状态和D不可中断睡眠一般是磁盘IO等待锁资源状态平均进程数量高CPU使用率意味着CPU在全力运行高Load可能是CPU繁忙也可能是大量进程等待IO。Load/核心数 1.0资源够用Load/核心数 1.0刚好满负荷Load/核心数 1.0过载实际场景CPU高如90%Load低如1.0CPU正在全力处理一个复杂计算任务但没有额外的任务排队比如只跑一个单线程程序。状态健康算力吃满。CPU低如10%Load高如10.0异常信号说明CPU没怎么干活但大量进程堵在D状态不可中断睡眠。这通常意味着磁盘I/O极度缓慢如机械硬盘高负载或内存严重不足导致频繁交换Swap。状态I/O瓶颈。CPU高Load也高说明CPU已经算不过来了而且排队的人越来越多比如跑了太多CPU密集型任务。状态CPU算力严重不足需要扩容。CPU低Load也低系统完全空闲非常健康。补充进程状态ps aux/ajxa所有终端所有用户的进程如果没带x只显示前台/关联进程u面向用户的形式输出用户名列/CPU内存占用比x无控制终端不依赖终端的守护进程j面向作业输出包括父进程PPID、进程组PGID、会话SID等Linux内核定义了几种进程状态Rrunning不一定在运行中也可能在运行队列中Ssleeping进程等待事件也叫可中断睡眠————对应不可中断睡眠DDdisk sleep不可中断睡眠等待IO结束不被信号杀死Tstopped发送SIGSTOP停止进程发送SIGCONT继续运行Xdead返回给父进程的状态Zzombie僵尸进程父进程没回收子进程只能杀死父进程让僵尸进程变成孤儿进程然后initPID1领养这个进程Init一直wait()等待退出发现这个子进程状态是Z就获取退出码将tast_struct从内核抹除掉。CPU是怎么执行程序/任务的1、程序————进程编译链接.c/.java/.cpp…文件被编译器转换成机器指令打包成ELF格式的可执行文件存放在硬盘。加载./a.outshellfork()子进程然后execve()程序替换将这个文件的指令和数据加载到虚拟地址空间中。内核层面是创建新的task_struct和mm_structvm_area_struct等一系列的数据结构建立映射MMU配合操作系统建立页表映射入口跳转操作系统将CPU的程序计数器PC寄存器指向该程序入口地址_strat交出控制权给这个进程2、硬件循环取指令CPU根据程序计数器PC的地址从缓存或者主存中取指令译码控制单元CU将二进制指令拆成“操作码”和“操作数”执行算术逻辑单元ALU执行计算或者判断访存指令需要读写内存mov指令MMU翻译物理地址CPU访问缓存或者主存读写数据写回将ALU计算结果或者访存读取的数据写回寄存器组中3、多进程调度时钟中断到来时执行对应的中断处理函数操作系统把当前进程时间片-1如果为0就设置调度标志位为1返回用户态前检查标志位是否为1为1就调用进程调度的处理函数不为1就不发生切换。除了这种时间片耗尽的情况还有阻塞时主动调用休眠以及硬件中断唤醒高优先级进程会抢占CPU。发生进程切换会保存上下文信息PC程序计数器栈顶栈底指针通用寄存器组到task_struct中TLB失效内核空间的数据任在物理内存中用户空间数据缓存会被最近最常使用算法慢慢替换。负数如何表示正数的补码就是原码负数的补码是正数的按位取反1。正数50000 0101负数-51111 1011为什么这么设计方便计算减法0000 01011111 10111 0000 0000丢弃溢出位如何识别补码的值先看符号位正数就直接用负数就取反1得到绝对值再带上-号。为什么能表示的负数比正数多因为0被归类为正数比如八位有符号整数表示范围-128~1271000 0000表示-128它不能由正数取反1得到因为正数表示不了128——1000 0000访问磁盘为什么比访问内存慢好几个数量级寄存器——L1缓存——内存——固态硬盘——机械硬盘1ns 1ns 100ns 10us 10ms固态硬盘访问时间是内存的100倍1、物理运动和电子流动内存VS机械硬盘内存靠电子流动机械硬盘要磁头读取要定位柱面磁道扇区天然慢。2、电荷和浮栅内存VS固态硬盘内存使用电容充放电可以按字节读写固态硬盘使用浮栅晶体管写入要按页写擦除按块擦写之前如果块里有旧数据还要先整块擦除ms级别3、总线协议和软件栈开销CPU可以直接通过内存控制器通过总线访问内存几乎不经过操作系统干预硬盘数据要通过中断和DMA帮助CPU搬运磁盘数据进内存通知CPU文件读写翻译成扇区读写还要操作系统经过文件系统EXT2/3/4和块设备驱动的封装翻译。4、寻址方式不同内存是按字节寻址磁盘是块寻址哪怕只想读一个字节也要加载一整个块进内存实际上为了解耦合每次都读取一页数据进内存这种数据传输带来了更大的时间开销键盘敲下一个键操作系统发生了什么硬件层产生扫描码发送中断信号给中断控制器通知CPU获取中断号操作系统上下文切换CPU收到中断请求保护当前执行的上下文PC栈指针寄存器通用寄存器组等然后获取中断号去中断向量表中查找对应的中断处理方法执行中断处理CPU执行操作系统预先注册好的中断处理方法。具体操作读取数据键盘中断处理程序从键盘控制器的寄存器中读取扫描码数据转换键盘驱动将扫描码转换为操作系统使用的虚拟键码存入缓冲区转换好的虚拟键码还有按下或者释放动作存入一个环形缓冲区等待上层应用使用应用层面应用监听键盘事件操作系统将按键事件打包好给上层应用应用处理程序收到事件从内核读取数据调用对应的程序比如图形接口处理绘制显示图形系统将像素数据写入显卡缓冲区显卡持续扫描这个缓冲区将最终结果显示在屏幕上并行和并发并发是逻辑上的同时并行是物理上的同时。并发通过进程调度实现的多任务交替推进操作系统在单个CPU核心上通过时钟中断不断减少一个进程的时间片直到时间片耗完标志位设为1返回用户态前检查标志位如果为1就触发软中断执行进程调度中断处理。或者硬件触发比如键盘触发比如之前等待在IO事件的休眠进程被唤醒抢占CPU。并行多核CPU同一时刻执行不同的任务系统负责并发调度多核硬件负责并行执行。进程调度每调度一个活动队列的新进程旧进程就放入过期队列中直到一方空了就交换这两个的值每个CPU都应该有一个运行队列并发通过进程调度实现的多任务交替推进操作系统在单个CPU核心上通过时钟中断不断减少一个进程的时间片直到时间片耗完标志位设为1返回用户态前检查标志位如果为1就触发软中断执行进程调度中断处理。或者硬件触发比如键盘触发比如之前等待在IO事件的休眠进程被唤醒抢占CPU。并行多核CPU同一时刻执行不同的任务系统负责并发调度多核硬件负责并行执行。进程调度每调度一个活动队列的新进程旧进程就放入过期队列中直到一方空了就交换这两个的值每个CPU都应该有一个运行队列[外链图片转存中…(img-iV9pXMDe-1784142161399)]