MSIPO技术圈 首页 IT技术 查看内容

线程和进程的一些基础知识

2024-03-25

线程间同步方式

互斥锁:给共享资源加一把锁,有锁的线程才能用资源

读写锁:多个线程同时读,只允许一个线程写

信号量:允许多线程同时访问同一资源,但是要控制最大线程数量

屏障:多个线程执行到某个相同的阶段,再一起进行执行

事件:把资源发生的变化通知给所有的线程

PCB

Process Control Block :进程控制块 。操作系统管理进程的数据结构,一个进程一个PCB

PCB包含内容:

  • 进程的描述信息,包括进程的名称、标识
  • 进程的调度信息,包括进程阻塞原因、进程状态(就绪、运行、阻塞等)、进程优先级(标识进程的重要程度)
  • 进程对资源的需求情况,包括 CPU 时间、内存空间、I/O 设备
  • 进程打开的文件信息,包括文件描述符、文件类型、打开模式
  • 处理机的状态信息(由处理机的各种寄存器中的内容组成的),包括通用寄存器、指令计数器、程序状态字 PSW、用户栈指针

进程的状态

  • 创建(new):进程正在被创建,尚未到就绪状态。
  • 就绪(ready):进程已处于准备运行状态,即进程获得了除了处理器之外的一切所需资源,一旦得到处理器资源(处理器分配的时间片)即可运行。
  • 运行(running):进程正在处理器上运行(单核 CPU 下任意时刻只有一个进程处于运行状态)。
  • 阻塞(waiting):又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行。
  • 结束(terminated):进程正在从系统中消失。可能是进程正常结束或其他原因中断退出运行

进程间的通信方式

  • 管道/匿名管道(Pipes):用于有亲缘关系的父子进程或者兄弟进程的通信。
  • 有名管道(Named Pipes) : 匿名管道没有名字,只能用于亲缘关系的进程间通信。有名管道严格遵循 先进先出(First In First Out) 。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
  • 信号(Signal):一种比较复杂的通信方式,用于通知接收进程某个事件已经发生
  • 消息队列(Message Queuing):消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。数据先进先出。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显式地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
  • 信号量(Semaphores):信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
  • 共享内存(Shared memory):使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。这是最有用的进程间通信方式。
  • 套接字(Sockets) : 用于客户端和服务器通过网络进行通信。套接字是支持 TCP/IP 的网络通信的基本操作单元,是不同主机进程双向通信的端点,是通信两方约定,用套接字中的函数来完成通信过

进程的调度算法

  • 先到先服务(FCFS,First Come, First Served) : 谁先来谁先执行,立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
  • 短作业优先(SJF,Shortest Job First) : 估计运行时间最短的进程先执行,立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
  • 时间片轮转(RR,Round-Robin) : 时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。
  • 多级反馈队列(MFQ,Multi-level Feedback Queue)短进程优先,仅照顾了短进程而忽略了长进程 。多级反馈队列既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。,是目前被公认的一种较好的进程调度算法,UNIX 操作系统用它。
  • 优先级(Priority):为进程分配优先级,优先级高的先执行。相同优先级进程先到先服务。根据内存,时间或任何其他资源要求来确定优先级

僵尸进程和孤儿进程

在 Unix/Linux 系统中,子进程通过 fork()系统调用创建,会创建一个新进程,是原有进程的副本。子父进程运行相互独立,有各自的 PCB,父进程结束了,子进程仍可继续运行。

进程调用 exit()系统调用结束运行,内核会释放该进程所有资源,包括打开的文件、占用的内存等,但对应的 PCB 仍在系统中。这些信息只有在父进程调用 wait()或 waitpid()系统调用时才被释放,为了让父进程得到子进程的状态信息。

  • 僵尸进程:子进程已终止,但父进程仍运行,且父进程没有调用 wait()或 waitpid()获取子进程状态信息,释放子进程占用的资源,导致子进程的 PCB 还在系统中,但无法被进一步使用。这种情况,子进程就是“僵尸进程”。
  • 孤儿进程:父进程已终止或者不存在,但子进程仍运行。这种情况,子进程就是孤儿进程。孤儿进程是由于父进程意外终止或未及时调用 wait()或 waitpid()回收子进程导致的。为避免孤儿进程占用系统资源,操作系统会将孤儿进程的父进程设置为 init 进程(进程号为 1),由其回收孤儿进程的资源

Linux 用 Top 命令查找是否有僵尸进程,zombie 值表示僵尸进程的数量,为 0 代表没有僵尸进程

死锁

多个进程/线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,但此资源被其他进程/线程占用,形成死循环。由于进程/线程被无限期地阻塞,因此程序不可能正常终止

举例:进程 A 占用资源 X 并且请求资源 Y,而进程 B 已经占用了资源 Y 并请求资源 X。两个进程都在等待对方释放资源,无法继续执行,陷入了死锁状态

产生死锁的四个必要条件:

  • 互斥:资源必须处于非共享模式,即一次只有一个进程可以使用。如果另一进程申请该资源,那么必须等待直到该资源被释放为止。
  • 占有并等待:一个进程至少应该占有一个资源,并等待另一资源,而该资源被其他进程所占有。
  • 非抢占:资源不能被抢占。只能在持有资源的进程完成任务后,该资源才会被释放。
  • 循环等待:有一组等待进程 {P0, P1,..., Pn}P0 等待的资源被 P1 占有,P1 等待的资源被 P2 占有,……,Pn-1 等待的资源被 Pn 占有,Pn 等待的资源被 P0 占有

死锁的解除:

  • 立即结束所有进程,重启操作系统:这种方法简单,但以前所在的工作全部作废,损失很大。
  • 撤销涉及死锁的所有进程,解除死锁后继续运行:这种方法能彻底打破死锁的循环等待条件,但将付出很大代价,例如有些进程可能已经计算了很长时间,由于被撤销而使产生的部分结果也被消除了,再重新执行时还要再次进行计算。
  • 逐个撤销涉及死锁的进程,回收其资源直至死锁解除。
  • 抢占资源:从涉及死锁的进程中抢占资源,把夺得的资源再分配给涉及死锁的进程直至死锁解除

 

相关阅读

热门文章

    手机版|MSIPO技术圈 皖ICP备19022944号-2

    Copyright © 2024, msipo.com

    返回顶部