操作系统 线程 进程 IO模型

64位和32位的区别

  • 运行能力不同:64位CPU一次可以处理8个字节的数据;32位CPU一次可以处理4个字节的数据

  • 内存寻址能力不同:64CPU的最大寻址空间为2^64,理论可达16TB,64位CPU会设有不同的地址总线的数量,对应不同大小的寻址空间;32位CPU的最大寻址空间为4GB

  • 运行软件不同:32位和64位CPU的指令集不同,64位操作系统可以兼容运行32位的软件,32位的操作系统不可以运行64位的软件

Linux下的线程

  • Linux实现的是基于核心轻量级进程的“一对一”线程模型,一个线程实体对应一个核心轻量级进程,线程之间的管理在核外函数库中实现

进程和线程的区别

  • 进程是资源调度和分配的基本单位,线程是CPU调度和分派的基本单位

  • 一个进程可以拥有多个线程

  • 进程是程序的一次执行,线程是进程中的代码段,进程通过线程同时运行不同段的代码

  • 进程切换需要保存CPU现场信息并恢复要切换来的进程的CPU现场信息,开销比较大;线程切换只需要切换寄存器信息,开销比较小

  • 进程拥有独立的内存空间,线程拥有独立的栈,共享内存空间

系统线程数量上限

  • /usr/include/bits/local_lim.h中查看

  • 对Linux threads来说,这个值一般是1024;对NPTL来说没有硬性限制,受限于线程栈占用的内存,一般默认线程栈是8M

杀死一个进程

  • kill pid:系统向程序发送信号,程序接收到信号后先释放资源,再关闭程序

  • kill -9 pid:-9表示强制执行

Linux下的IO模型

  • 阻塞IO,当前IO操作未完成时不能执行其它的操作

  • 非阻塞IO,轮询机制,当前数据报没有准备好的时候,也不会阻塞程序

  • IO多路复用:一个进程监控多个文件描述符的机制,本质上也是阻塞IO,效率比阻塞IO高

  • 信号驱动IO模型:内核准备好数据之后通知进程,进程调用信号处理函数来获取数据报

  • 异步IO模型:内核一方面去取数据报内容,一方面将程序控制权还给应用进程,应用进程继续处理其他事务,非阻塞状态

同步&异步,阻塞&非阻塞

  • 同步和异步:消息通知机制

    • 同步:处理者自己等待消息是否被触发

    • 异步:触发机制通知处理者

  • 阻塞和非阻塞:程序等待消息通知时的状态(能不能干其它任务)

    • 阻塞:等待时挂起

    • 非阻塞:等待时继续执行其它任务

  • 同步非阻塞:需要在两个任务之间来回切换,检查等待的任务是否完成,效率比较低下

  • 举例

    • 同步阻塞:小明一直盯着下载进度条,到 100% 的时候就完成。

      同步体现在:等待下载完成通知;
      阻塞体现在:等待下载完成通知过程中,不能做其他任务处理;
    • 同步非阻塞:小明提交下载任务后就去干别的,每过一段时间就去瞄一眼进度条,看到 100% 就完成。

      同步体现在:等待下载完成通知;
      非阻塞体现在:等待下载完成通知过程中,去干别的任务了,只是时不时会瞄一眼进度条;【小明必须要在两个任务间切换,关注下载进度】
    • 异步阻塞:小明换了个有下载完成通知功能的软件,下载完成就“叮”一声。不过小明仍然一直等待“叮”的声音(看起来很傻,不是吗)。

      异步体现在:下载完成“叮”一声通知;
      阻塞体现在:等待下载完成“叮”一声通知过程中,不能做其他任务处理;
    • 异步非阻塞:仍然是那个会“叮”一声的下载软件,小明提交下载任务后就去干别的,听到“叮”的一声就知道完成了。

      异步体现在:下载完成“叮”一声通知;
      非阻塞体现在:等待下载完成“叮”一声通知过程中,去干别的任务了,只需要接收“叮”声通知即可;【软件处理下载任务,小明处理其他任务,不需关注进度,只需接收软件“叮”声通知,即可】

I/O多路复用

  • 概念:一种机制,通过一个进程监视多个描述符,当某个描述符准备就绪时通知程序进行相应的读写操作;与多线程+阻塞I/O相比,可以监听多个文件描述符,不用创建和维护线程或进程,大大减少了系统的开销。

  • 支持I/O多路复用的系统调用:select、poll、epoll

    • select:最初解决IO阻塞问题的方法。调用后select函数会阻塞,直到有描述符就绪或超时,当select函数返回后,可以通过遍历fdset找到就绪的描述符。

      • 优点:良好的跨平台支持

      • 缺点

        • 单个进程打开的文件描述符(FD)有一定的限制,32位系统的默认值是1024,64位系统的默认值是2048

        • 轮询方式扫描socket,FD数量较多时效率低下

        • 需要维护一个用来存放大量FD的数据结构,在用户态和内核态传递该结构时的复制开销比较大

    • poll:本质上和select没有区别,通过基于链表的存储方式解决了最大连接数量受限的问题

      • 优点:基于链表存储,没有最大连接数量的限制

      • 缺点

        • 大量的FD数组被整体复制于用户态和内核态之间

        • 轮询排查方式

        • 水平触发

    • epoll:使用“事件”的就绪通知方式,只返回状态发生变化的文件描述符,解决了轮询的瓶颈

      • 优点

        • 没有最大并发连接的限制,1G能监听10万个端口

        • 事件就绪通知的方式(回调函数),效率不会随FD的增加而下降,效率得到提升

        • 内存拷贝,利用mmap减少复制开销

      • 对文件描述符操作的两种方式:LT模式和ET模式

        • LT模式:默认模式,同时支持block和no-block socket。内核通知一个文件描述符是否就绪了,可以选择不对这个就绪的FD进行IO操作,内核会继续通知

        • ET模式:高速工作方式,只支持no-block socket。内核通知一个文件描述符是否就绪了,如果不对这个就绪的FD进行IO操作,内核不会再次通知,除非某个操作导致那个FD不再是就绪状态了

  • select/poll/epoll对比

    • 一个进程能打开的最大连接数

      • select:32位1024个,64位2048个,可以修改并重新编译内核,性能可能会受到影响

      • poll:基于链表存储,没有最大连接数的限制

      • epoll:有很大的上限,1G内存约10万个连接,2G内存约20W连接

    • FD剧增后带来的IO效率问题

      • select、poll:每次调用时都采用轮询方式遍历,随着FD的增加,遍历速度会线性下降

      • epoll:根据每个FD上的回调函数实现,活跃的socket才会主动调用callback,活跃的socket较少的情况下没有线性性能下降的问题,但是socket都很活跃的情况下,可能存在性能问题

    • 消息传递方式

      • select、poll:内核空间到用户空间的拷贝

      • epoll:mmap映射,内核空间和用户空间共享内存

  • 选择:当连接数少且连接都十分活跃的情况下,select和poll和性能可能会比epoll好,因为epoll机制需要很多的函数回调

socket编程的线程通信模型,BIO/NIO/AIO

同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。其中BIO是一个连接一个线程。NIO是一个请求一个线程。AIO是一个有效请求一个线程。
​
同步:select轮询查看channel是否处于就绪状态
异步:channel处于就绪状态之后通过回调函数通知线程epoll
​
阻塞:应用程序在获取网络数据的时候,如果网络传输数据很慢,那么程序就一直等待,直到传输完毕为止。
非阻塞:应用程序直接可以获取已经准备就绪的数据,无须等待
  • BIO:同步阻塞IO,服务器实现模式为一个连接一个线程,可能会造成不必要的线程开销,可以通过线程池机制改善

    • 适用于连接数目比较小且固定的架构,对服务器资源要求比较高,并发局限于应用中,程序简单直观容易理解

  • NIO:同步非阻塞IO,服务器实现模式为一个请求一个线程,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理。用户进程需要时不时询问IO操作是否就绪

    • 适用于连接数目多且连接比较短的架构,并发局限于应用中,编程比较复杂

    • 数据准备好之后,再交由应用进行处理,数据的读取/写入在应用线程中完成,节省了数据准备时间

    • 缓冲区 buffer:NIO基于块进行数据处理,NIO中所有数据的读取都通过缓冲buffer进行处理

    • 通道 channel:对数据的读取和写入要通过channel,通道是全双工的,可以更好的映射底层操作系统的API

    • 选择器 selector:提供选择已经就绪的任务的能力,同步&非阻塞(可以同时轮训多个channel)

  • AIO:异步非阻塞IO,具有异步能力,对socket和IO都起作用,是一种在读写操作结束之前允许进行其他操作的IO处理

    • 适用于连接数目比较多且连接比较长的架构,充分调用OS参与并发操作,编程比较复杂

    • 与NIO相比,使用回调函数,读完之后再通知应用,可以胜任重量级,读写过程长的任务

Reactor模型

  • 同步I/O的事件分发器

  • 注册读就绪事件和相应的事件处理器;事件分发器等待事件;事件到来,激活事件分发器,分发器调用对应的事件处理器;事件处理器完成实际的读操作

  • Proactor是异步事件分发器,完成读或者写操作后通知事件处理器,事件处理器直接处理缓冲区的数据即可,不需要再自己读取

内存碎片

  • 内部碎片:已经分配给进程但是进程不使用的存储块;直到进程释放它或者进程结束后,系统才有可能利用这个存储块

  • 外部碎片:还没有分配出去的存储块,但是由于太小了无法分配给新的进程;伙伴系统算法

提高系统并发性

  • 提高CPU并发计算能力

    • 多进程&多线程

    • 使用线程,减少进程切换

    • 减少不必要的锁,考虑无锁编程

    • 考虑进程优先级

    • 考虑系统负载

  • 改进IO模型

    • 使用DMA技术

    • 异步I/O

    • 改进多路I/O就绪通知策略

    • 内存映射

    • 直接I/O

    • Sendfile

死锁的条件

  • 互斥条件:一个资源一次只能被一个进程访问

  • 请求与保持条件:进程因请求资源而阻塞时,对已获得的资源保持不放

  • 不剥夺条件:进程已经获得的资源,在未使用完之前不能强行剥夺,只能进程自行释放

  • 循环等待条件:若干资源形成一种头尾相接的循环等待资源的关系

解决方法

  • 预防死锁:破坏死锁产生的必要条件:1.互斥条件(不可破坏);2.请求与保持条件(一次申请全部资源);3.不可剥夺条件(不能满足要求时先释放资源再申请);4.循环等待条件(线性排队)
  • 避免死锁:银行家算法,系统在为进程分配资源之前,首先计算此次分配的安全性,如果是安全的再进行分配。安全是指,存在一个进程序列,按照这个顺序为各个进程分配资源,所有进程都能顺利完成运行
  • 解除死锁:剥夺资源、撤销进程

线程切换过程

  • 控制权的转换

  • 根据优先级切换上下文

    • 用户级上下文:正文、数据、用户堆栈和共享存储区

    • 寄存器上下文:通用寄存器、程序寄存器、处理器状态寄存器、栈指针

    • 系统上下文:进程控制块、内存管理信息、内核栈

进程通信

管道,速度比较慢

  • 无名管道:半双工通信方式,用于有亲缘关系的进程之间的通信,单独构成了一种文件系统,只存在内存当中
  • 有名管道:可用于所有进程之间的通信,以文件的形式存放在文件系统当中

消息队列

  • 基于链表的一个队列,存放在内核缓冲区中,容量受系统的限制

共享内存

  • 存放在内存当中,速度更快,但是要注意同步的问题

进程状态转换

线程阻塞状态包括三种

  • 等待阻塞:运行中的线程执行wait()方法会进入该状态
  • 同步阻塞:没有获取到锁的线程进入该状态
  • 超时阻塞:执行sleep(time)或者wait(time)方法进入该状态

进程调度方式

  • 先来先服务调度算法
  • 短进程优先调度算法
  • 优先级调度算法
  • 高响应比优先调度算法
  • 时间片轮转算法
  • 多级反馈队列调度算法

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值