用户态和内核态

用户态和内核态是操作系统的两种重要运行状态,它们之间通过系统调用、异常和外围设备的中断等方式进行切换。用户态主要运行用户程序,访问受限资源,不能直接进行如硬件操作、内存管理等敏感操作;内核态则运行操作系统程序,操作硬件,拥有最高权限。这种区分机制保证了操作系统的稳定性和安全性。

进程,线程和协程有什么关系和区别?

进程是程序资源分配管理的最小单位,线程是资源调度的最小单位,其中,一个进程可以包含多个线程,而这些线程又共享该进程的资源,而协程是用户态的轻量级线程,不受操作系统的调度,由程序员或库进行控制。协程可以在一个线程中切换执行多个任务,实现了异步编程的效果。并且协程的创建和销毁都由用户空间完成,所以开销非常小;

进程间的通信方式

  1. 管道(Pipe):管道是一种单向通信方式,可以在进程间传输数据。管道只能用于父子进程之间或者兄弟进程之间的通信。
  2. 命名管道(Named Pipe):命名管道是一种单向通信方式,可以在进程间传输数据。与管道不同的是,命名管道可以用于任意进程之间的通信。
  3. 共享内存(Shared Memory):共享内存是通过共享内存块的方式进行进程间的通信
  4. 信号(Signal):信号是一种异步通信方式,进程可以通过发送信号来通知其他进程或者处理特定事件。
  5. 消息队列(Message Queue):消息队列是一种通过消息传递的方式进行进程间的通信.
  6. 套接字(Socket):套接字是一种通过网络进行进程间通信的方式,可以本机通信也可以跨机器通信。

进程调度方式:

进程的调度方式主要分为两大类,一种是非抢占式调度,另一种是抢占式调度。

非抢占式调度(只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态)

  • 先来先服务:按照进程到达的顺序进行调度(简单易实现,但可能导致长作业阻塞短作业)
  • 短作业优先:选择预计执行时间最短的进程(可以最小化平均等待时间,但难以预测作业长度)
  • 高相应比优先:响应比为等待时间/服务时间,响应比高的先执行,可以避免饥饿现象。
  • 非抢占式优先级:创建进程时就设定了优先级。

抢占式调度(一个进程正在处理机上执行时,如果有一个更重要或更紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给更重要紧迫的那个进程)

  • 最短剩余时间优先:最短作业优先的抢占式版本。当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
  • 时间片轮转:将CPU时间划分成一段段时间片,每个进程执行一个时间片,然后轮流切换到下一个进程(提供了良好的响应时间,但可能导致频繁的上下文切换)
  • 多级反馈队列:结合了时间片轮转和优先级调度,动态调整进程的优先级(能够适应不同的系统需求,提高系统性能)
  • 抢占式优先级:优先级随时间动态变化

死锁的产生及解决

死锁是指在多个进程(或线程)之间,每个进程都占有某些资源,同时又等待其他进程释放它所需要的资源,从而导致所有进程都无法继续执行下去的一种状态。

死锁产生的原因通常有以下几种情况:

  • 竞争资源
  • 不恰当的资源分配顺序
  • 循环依赖

解决死锁问题,可以采取以下策略:

  • 预防死锁:通过合理的资源分配策略、避免循环依赖等方式,尽可能地预防死锁的发生。
  • 避免死锁:通过安全序列等方式,避免产生死锁。
  • 检测死锁:可以通过资源分配图等方式检测死锁是否已经发生。
  • 解除死锁:当发现死锁已经发生时,可以采取一些措施解除死锁,比如中断某个进程、回收某个进程占用的资源等。

饥饿进程、孤儿进程、僵尸进程(及解决方法)、守护进程

  • 饥饿进程:饥饿是指系统不能保证某个进程的等待时间上界,从而使该进程长时间等待,当等待时间给进程推进和响应带来明显影响时,称发生了进程饥饿。当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死。
  • 孤儿进程:父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”此时的子进程叫做孤儿进程。(孤儿进程并不是有害的,因为它们最终会被init进程回收资源)
  • 僵尸进程:子进程退出,而父进程并没有收集(调用wait或waitpid获取子进程的状态信息),那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。解决方法:1.确保父进程调用wait或waitpid;2.杀死父进程;
  • 守护进程:守护进程(Daemon)是在一类脱离终端在后台执行的程序, 能处理一些系统级的任务。它不需要用户输入就能运行,而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。通常以 d 结尾, 随系统启动, 其父进程 (ppid) 通常是init 进程。