IO多路复用
使用IO多路复用(linux中通过epoll来实现)可能效率还并不能比得上多线程 + 同步阻塞的方法。其主要的优势在于能够处理更多的连接,多线程 + 同步阻塞IO的方式会开辟更多的线程,线程开启的开销还是比较大的,如果换做使用线程池,那么在多线程切换的时候实际上也消耗了部分时间。
针对连接较少的情况 :
多线程 + 同步阻塞IO的方式更加适合,因为其处理效率更高
针对IO并发量很大的情况:
开辟多线程实际上内存消耗、时间消耗较大,此时使用IO多路复用效果会更好
进程和线程的区别与联系
- 进程是对运行程序的封装,是系统进行资源分配和调度的基本单位,而线程是进程的子任务,作为CPU资源分配和调度的基本单位
- 进程的创建需要系统分配内存以及CPU,文件描述符等资源,销毁也需要进行相应的回收,所以进程的管理开销是比较大的,但是线程的开销则比较小
- 进程之间并不会相互影响,但是一个线程崩溃可能会导致进程崩溃,从而影响其他线程
- 联系 : 进程与线程之间关系:线程是存在进程的内部,一个进程中可以有多个线程、一个线程只能存在一个进程中;
进程、线程之间的通信方式
进程之间通信方式:
- 管道 : 管道是属于半双工的,双方需要通信时,需要简历两个管道。管道实际上就是一个内核缓冲区,进程通过先进先出的方式从缓冲区中读取数据。对于匿名管道而言,其只能够支持父子进程之间的通信;而有名管道支持非亲缘关系进程之间的通信;
- 信号量 : 信号量实际上是一个计数器,用于控制多个进程对共享资源的访问。信号量实际上只有等待以及发送两种操作,等待就是将其值减一或者挂起进程,发送就是将其值加一或者将进程恢复到运行状态;
- 共享内存 : 共享内存允许两个或者多个进程共享一个给定的存储区,这一段存储区可以被两个或者多个进程映射到自身的地址空间中。当一个进程将某些信息写入到共享内存后,可以被其他使用这个共享内存的进程简单读取。其中共享内存的执行效率最高,但是需要使用锁或者其他机制进行同步;
- 消息队列 ;消息队列是一个链表,是一系列保存在内核中消息的列表,用户进程可以向消息队列中按照一定规则添加新消息,也可以从消息队列中读取消息(消息队列可以不同按照队列次序进行读取,而是可以根据自定义条件接收特定类型的消息)
- 套接字 : 套接口也是一种进程间的通信机制,与其他通信机制不同的是,可以用于不同机器间的通信
线程之间的通信方式:
- 使用全局变量
- 使用信号机制
- 使用事件的方式通知
进程的一些调度方式
- 先来先服务 : 按照作业达到任务队列的顺序调度,但是效率不高,性能不好。不利于短作业操作
- 短作业优先 : 每次从队列里面选出预计运行时间最短的作业来运行 (不利用长作业)
- 最短剩余时间优化 : 当某一个作业正在运行时,如果突然队列中进入某个作业更短时间运行,那么中断当前运行时间,选择处理时间更短的作业运行
- 时间片轮转 : 将系统CPU处理划分为若干个时间片,进程按照先后顺序进行排列,每次都是调度队首的进程,当执行完一个时间片后,计时器发出时钟中断请求,并将该进程移动到队尾。该调度方式能够在某一时间段内相应所有的用户请求。
操作系统的内存管理
- 物理内存管理
- 单一连续分配 : 内存分为系统区和用户区,系统区仅供操作系统使用,用户去为用户提供;
- 固定分区匹配 : 将用户内存空间划分为若干个固定大小的区域
- 动态分区 ; 先将进程放入到内存中,然后根据进程的大小动态建立分区,但是通过该方式可能会出现一些内存碎片的问题
- 非连续的内存分配管理方式:
- 分页存储管理 : 通过页表进行关系映射,将用户程序的页号与内存中的块号进行映射(提高内存利用率)分页的思想在于 : 将主内存空间划分为大小相等且固定的块,块相对较小,其作为主存的基本单位。而每个进程以块为单位进行划分,进程在执行时以块为单位逐个申请主存中的块空间;
- 分段存储管理 : 分段的目的是方便编程、信息保护和共享、动态增长以及动态链接等
- 段页式存储管理 : 先将程序分段、每段再进行分页,所以正常来说需要查三次内存,先查段,在查页,最后查数据
- 页和段的区别 : 页是物理单位固定大小系统定义,所以地址空间是一维的,程序员只要记一个地址符号就行了。段是逻辑单位用户定义,所以地址空间是二维的,既要给出段名,也要给出段内地址。
- 虚拟内存管理
死锁产生的必要条件
- 互斥 : 一个资源每次只能被一个进程所使用
- 占用并请求 : 一个进程因请求资源而阻塞,对已经获得的资源不释放
- 不可剥夺 : 进程在获得资源后,在没有使用结束前是不能够被强行剥夺的
- 循环等待 : 若干个进程之间形成一种头尾相接的循环等待资源关系
死锁的原因 :
- 系统资源不足
- 进程运行推进顺序不当
- 资源分配不当
出现死锁,如何恢复?
- 重新启动 ;但是其代价很大,不仅包括死锁的进程还有没有死锁的进程
- 终止进程 : 终止参与死锁的进程并回收所占资源
- 剥夺资源 : 剥夺死锁进程占有的全部或者部分资源
- 进程回退 : 让参与死锁的进程回退到以前没有发生死锁的某一点
- 另外还有银行家算法等,可以帮助你如何避免死锁
孤儿进程以及僵尸进程时为什么,如何形成的?
- 孤儿进程是父进程执行完任务退出后,子进程还在执行任务。孤儿进程会被init进程收养并完成状态收集
- 僵尸进程是子进程完成并退出后,父进程并没有使用wait或者waitpid对他们的状态进行收集,这些子金册灰姑娘的进程描述依旧还是会保留在系统中,这些子进程成为僵尸进程
- 如何处理僵尸进程 :
- 通过fork两次的办法,将子进程的父进程变为init进程
- 子进程退出时,需要向父进程发送SIGCHID信号,通过这个信号父进程能够调用wait来处理僵尸进程