操作系统

本文详细介绍了操作系统的核心组成部分——内核与shell,包括操作系统的基本特征、内核的系统调用。接着深入探讨了计算机体系结构及内存管理,如虚拟内存、虚拟页式内存管理和进程与线程的概念、状态及调度。文中还阐述了进程间通信的IPC机制,如管道、FIFO、消息队列、信号量和共享存储,并提到了同步与异步的概念及其在系统中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.kernel与shell

从整体上来说,操作系统一般分为内核和外壳两大部分。操作系统的内核是实现操作系统基本功能的程序模块的集合,在机器的核心态下运行;操作系统的外壳,是指运行在内核之上的、完成OS外层功能(如命令解释、机器诊断等)的程序,他们运行在机器的用户态下,是一种开放式结构,其功能可方便地修改或增删。

计算机系统都有两种状态,即核心态和用户态,某一时刻二者必然占其一。
用户态:用户具有较低特权的执行状态,在这种状态下,处理机只能执行规定的指令,访问指定的寄存器和存储区,用户程序通常只能在这一级别执行。
核心态:核心态是操作系统内核的运行状态,在这种状态下,处理机具有较高的特权,能执行一切指令,可以访问所有的寄存器和存储区。

操作系统的基本特征

1.并发:并发是指宏观上一段时间内能运行多个程序,而并行是指同一时刻能运行多个指令。并行需要硬件支持,如流水线或者多处理器。操作系统引入进程和线程,使得程序能否并发运行。
2.共享:共享是指操作系统中的资源可以被多个并发进程共同使用。有两种共享方式:互斥共享和同时共享。互斥共享的资源称为临界资源,需要用同步机制来实现对临界资源的访问。
3.虚拟:虚拟技术把一个物理实体转换为多个逻辑实体。主要有两种虚拟技术:时分复用和空分复用技术。如多个进程在同一处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。
4.异步:异步指进程不是一次性执行完毕,而是走走停停,以不可知的速度向前推进。每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。 "异步模式"非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。

内核的系统调用

1.进程控制:fork();exit();wait();
2.进程通信:pipe();shmget();mmap();
3.文件操作:open();read();write();
4.设备操作:ioctl();read();write();
5.信息维护:getpid();alarm();sleep();
6.安全:chmod();umask();chown();

二.计算机体系结构及内存管理

1.虚拟内存

虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。

覆盖技术把程序按逻辑结构,那些不会同时执行的共享一块内存,按时间先后来运行。

交换技术将暂时不能运行的程序放入外存,换入换出内容的大小为整个程序的地址空间,增加了处理器的开销。

2.虚拟页式内存管理

用页管理,请求调页和页面置换功能。在磁盘中存储未被映射的页。
当需要的页不在内存中,我们称其为缺页中断,我们需要用适当的页面置换算法选择当前内存中驻留的页面置换出去。

(1)最优页面置换算法

计算它的下一次访问之前,还需等待多长时间,选择时间最长的,作为被置换的页面。

(2)先进先处算法

选择在内存中驻留时间最长的页面。

(3)最近最久未使用LRU

选择最久未被使用的淘汰,用双向链表+map实现

(4)时间页面置换

用比特位标志该页面被访问过没有,所有页面组织成环,指针指向最老的页面,若其访问标识位为0,立即淘汰,否则置为 0,直到找到第一个0淘汰。

(5)最不常用算法

选择访问次数最少的那个页面,用桶和链表实现。通常结合时间权重。

Belady现象:在采用某种算法时,分配更多的内存页反而导致缺页率提升的现象。

3.虚拟段式内存管理

相当于二维分页,程序的地址空间划分成多个拥有独立地址空间的段,每个段上的地址空间划分成大小相同的页。这样既拥有分段系统的共享和保护,又有分页系统的虚拟内存功能。
页的大小不可变,段的大小可变。
页的大小是2的整数幂。

4.内存分配

(1)连续内存分配:

首次适配:找到第一个适合的就分配这个连续内存。简单,但容易产生大的空闲块和很多外部碎片。
最优适配:找到最合适的,需要按尺寸排列的空闲块列表,重分配需要搜索并合并相邻的分区。当分配小尺寸时非常有效,但重分配慢。
最差适配:找到最不合适的。容易出现大内存无法分配的现象。

(2)非连续内存分配:

优点:
1.一个程序的物理地址是非连续的
2.更好的内存利用和管理
3.允许共享代码和数据
4.支持动态加载和动态链接

分段:把数据分配到多个物理地址空间。如堆/运行栈,可以使用权限保护机制实现。
这样段访问的方式就变成:段块+段偏移 --> 段寄存器+地址寄存器实现
分页:分段里的大小是动态分配的,但页的大小是固定的。
物理内存被分成大小相等的帧,一个内存地址是一个二元组(帧号,帧偏移)

页寻址机制:
1.页映射到帧
2.页是连续的虚拟内存
3.帧是非连续的物理内存
4.不是所有的页都有对应的帧
5.通过页表+页帧判断是否是合法内存地址

分页机制性能问题:访问一个内存单元需2次内存访问,因为页表也在内存中。
解决方式:缓存 --> TLB近期访问页帧转换

三.进程与线程

1.进程

定义:一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程。

组成:程序的代码、程序处理的数据、程序计数器,指向下一条即将运行的指令、一组通用的寄存器和当前值/堆/栈、一组系统资源(如打开的文件)。
一个程序由多个进程组合,进程有核心态和用户态的区别,但程序是静态的。

特点
1.动态:并发和并行执行。
2.独立性:不同进程相互不影响。
3.制约性:因访问共享资源/数据相互产生制约。

PCB进程控制结构:操作系统用PCB来描述进程的基本情况及运行变化的过程.PCB是进程存在的唯一标识
1.进程标识:本进程标识,父进程标识,用户标识。
2.处理机状态信息保存区:保存进程运行状态信息
1)用户可见寄存器:用户可使用数据。
2)控制和状态寄存器:程序计数器PC,程序状态字PSW。
3)栈指针:过程调用/系统调用/中断处理需要用到。
3.进程控制信息:
1)调度和状态信息
2)进程间通信信息
3)存储管理信息
4)进程所用资源
5)有关数据结构链接信息

2.进程状态

进程生命周期管理
1.进程创建:start --> ready
2.进程运行:内核选择一个就绪进程运行
3.进程等待:等待被内核调度
4.进程唤醒:进程只能被别的进程或者OS唤醒
5.进程结束:正常退出/错误退出(自愿)、致命错误/被其它进程所杀

Running运行态:在CPU上运行
Ready就绪态:获取了一切资源,一旦得到CPU就运行
Blocked阻塞态:等待某一事件而暂停

进程阻塞:三种阻塞
1.请求服务无法马上完成
2.启动某种耗时操作
3.需要的数据未到达

进程只能自己阻塞自己,阻塞是要占CPU资源的,和睡眠不同。

进程挂起:进程在挂起时,没有占用内存空间,处在挂起状态的进程映像在磁盘上。
1.阻塞挂起(Blocked-suspend):等待某事件的出现,在外存中
2.就绪挂起(Ready-suspend):只要进入内存,就运行

OS维护状态队列,管理PCB,每个队列因为优先级还分不同队列。

3.fork()和exec()

fork():对子进程分配内存,复制父进程的内存和CPU寄存器到子进程里,开销昂贵。
首先,系统让新的进程与旧的进程公用一个代码段,因为它们的程序还是相同的,对于数据段和堆栈段,系统则复制一份给新的进程,这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。而如果两个进程要共享什么数据的话,就要用另一套函数(shmget/shmat/shmdt)来操作。现在,已经是两个进程了,对于父进程,fork函数返回了子进程的进程号,而对于子程序,fork函数则返回0,这样,对于程序,只要判断fork函数的返回值,就知道自己是处于父进程还是子进程。
事实上,目前大多数的unix系统在实现上并没有作真正的copy。一般的,CPU都是以“页”为单位分配空间的,象INTEL的CPU,其一页在通常情况下是4K字节大小,而无论是数据段还是堆栈段都是由许多“页”构成的,fork函数复制这两个段,只是“逻辑”上的,并非“物理”上的,也就是说,实际执行fork时,物理空间上两个进程的数据段和堆栈段都还是共享着的,当有一个进程写了某个数据时,这时两个进程之间的数据才有了区 别,系统就将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到最小。

exec():一个进程一旦调用exec类函数,它本身就死亡了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段和堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另外一个程序了。不过exec类函数中有的还允许继承环境变量之类的信息,这个通过exec系列函数中的一部分函数的参数可以得到。

3.线程

线程:进程中的一条执行流程。
解决问题:1.实体间可以并发执行 2.实体间共享相同的地址空间
优点:
1.一个进程可以同时存在多个线程
2.线程之间可以并发执行
3.线程之间可以共享地址空间和文件等资源
缺点:一个线程崩溃,会导致其所属进程所有线程崩溃

进程是资源分配单位 线程是CPU调度单位
进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈。线程同样具有就绪,等待,阻塞三种基本状态。同样具有状态之间的转换关系。

线程能减少并发时间和空间的开销
1.线程创建时间短
2.线程终止时间短
3.同一进程内线程切换时间比进程短(页表切换开销)
4.由于同一进程内各线程共享内存和文件资源,可直接进行不通过内核的通信。

进程与线程的比较
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

  1. 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

  2. 线程的划分尺度小于进程,使得多线程程序的并发性高。

  3. 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

  4. 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

  5. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

线程的实现
以下三种实现方式是通过判断操作系统看不看得到区分的

1.用户空间实现【用户线程】
不依赖与操作系统的内核,有一组用户级的线程函数来完成对线程的管理,包括线程的创建、终止、同步和调度。其缺点是一个线程阻塞,整个进程在等待,当一个线程开始运行后,除非主动交出CPU使用权,否则它所在的进程,其它的线程都无法执行。并且分配的时间片会小,时间慢。

2.内核实现【内核线程】

由操作系统的内核来完成线程的创建、终止和管理。(windows)
内核线程就是内核的分身,一个分身可以处理一件特定事情。这在处理异步事件如异步IO时特别有用。内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间。支持多线程的内核叫做多线程内核(Multi-Threads kernel )。
内核线程只运行在内核态,不受用户态上下文的拖累。

处理器竞争:可以在全系统范围内竞争处理器资源;

使用资源:唯一使用的资源是内核栈和上下文切换时保持寄存器的空间

调度:调度的开销可能和进程自身差不多昂贵

同步效率:资源的同步和数据共享比整个进程的数据同步和共享要低一些。

3.轻量级进程
它由内核支持的用户线程,一个进程可有一个或者多个轻量级进程,每个轻量级进程由一个单独的内核进程来支持。轻量级进程(LWP)是建立在内核之上并由内核支持的用户线程,它是内核线程的高度抽象,每一个轻量级进程都与一个特定的内核线程关联。内核线程只能由内核管理并像普通进程一样被调度。

轻量级进程由clone()系统调用创建,参数是CLONE_VM,即与父进程是共享进程地址空间和系统资源。

与普通进程区别:LWP只有一个最小的执行上下文和调度程序所需的统计信息。

处理器竞争:因与特定内核线程关联,因此可以在全系统范围内竞争处理器资源

使用资源:与父进程共享进程地址空间

调度:像普通进程一样调度

轻量级线程(LWP)是一种由内核支持的用户线程。它是基于内核线程的高级抽象,因此只有先支持内核线程,才能有LWP。每一个进程有一个或多个LWPs,每个LWP由一个内核线程支持。这种模型实际上就是恐龙书上所提到的一对一线程模型。在这种实现的操作系统中,LWP就是用户线程。

由于每个LWP都与一个特定的内核线程关联,因此每个LWP都是一个独立的线程调度单元。即使有一个LWP在系统调用中阻塞,也不会影响整个进程的执行。

轻量级进程具有局限性。

首先,大多数LWP的操作,如建立、析构以及同步,都需要进行系统调用。系统调用的代价相对较高:需要在user mode和kernel mode中切换。

其次,每个LWP都需要有一个内核线程支持,因此LWP要消耗内核资源(内核线程的栈空间)。因此一个系统不能支持大量的LWP。

上下文切换
上下文切换(Context Switch) 或者环境切换
在操作系统中,CPU切换到另一个进程需要保存当前进程的状态并恢复另一个进程的状态:当前运行任务转为就绪(或者挂起、删除)状态,另一个被选定的就绪任务成为当前任务。上下文切换包括保存当前任务的运行环境,恢复将要运行任务的运行环境。
进程上下文用进程的PCB(进程控制块,也称为PCB,即任务控制块)表示,它包括进程状态,CPU寄存器的值等。

通常通过执行一个状态保存来保存CPU当前状态,然后执行一个状态恢复重新开始运行。
支持多任务处理是CPU设计史上最大的跨越之一。在计算机中,多任务处理是指同时运行两个或多个程序。从使用者的角度来看,这看起来并不复杂或者难以实现,但是它确实是计算机设计史上一次大的飞跃。在多任务处理系统中,CPU需要处理所有程序的操作,当用户来回切换它们时,需要记录这些程序执行到哪里。上下文切换就是这样一个过程,他允许CPU记录并恢复各种正在运行程序的状态,使它能够完成切换操作。

在上下文切换过程中,CPU会停止处理当前运行的程序,并保存当前程序运行的具体位置以便之后继续运行。从这个角度来看,上下文切换有点像我们同时阅读几本书,在来回切换书本的同时我们需要记住每本书当前读到的页码。在程序中,上下文切换过程中的“页码”信息是保存在进程控制块(PCB)中的。PCB还经常被称作“切换帧”(switchframe)。“页码”信息会一直保存到CPU的内存中,直到他们被再次使用。

在三种情况下可能会发生上下文切换:中断处理多任务处理用户态切换

在中断处理中,其他程序”打断”了当前正在运行的程序。当CPU接收到中断请求时,会在正在运行的程序和发起中断请求的程序之间进行一次上下文切换。

在多任务处理中,CPU会在不同程序之间来回切换,每个程序都有相应的处理时间片,CPU在两个时间片的间隔中进行上下文切换。对于一些操作系统,当进行用户态切换时也会进行一次上下文切换,虽然这不是必须的。
操作系统或者计算机硬件都支持上下文切换。一些现代操作系统通过系统本身来控制上下文切换,整个切换过程中并不依赖于硬件的支持,这样做可以让操作系统保存更多的上下文切换信息

4.CPU调度

CPU调度指标
1.CPU使用率
2.吞吐率:在单位时间内完成的进程数量
3.周转时间:一个进程从初始化到结束
4.等待时间:进程在就绪队列中的等待总时间
5.响应时间:从一个请求到产生一次响应的总时间

调度算法
FCFS:先来先服务 平均等待时间波动较大
SRT:段作业优先,分可抢占和不可抢占的。可能导致饥饿
HRRN:最高响应比优先,有额外的上下文切换
Round Robin:轮询,平均等待时间较差
Multilevel FeedBack Queues:多级反馈队列
Fair Share Scheduling:公平共享调度,公平是第一要素

FFS控制用户对系统资源的访问
1.一些用户组比其它用户组更加重要
2.保证不重要的组无法垄断系统
3.未使用的资源按照每个组所分配的资源的比例来分配
4.没有打到资源使用率目标的组获得更高的优先姐

实时调度
正确性依赖其时间和功能两方面的一种操作系统
强实时系统:在保证的时间内必须完成
弱实时系统:要求重要的进程的优先级更高,尽量完成

多处理器调度
多处理器系统中线程调度通常有如下四种方式:
1、负载共享
它不把进程分给具体的处理器,系统维护一个全局的就绪线程队列,当某个处理器空闲时,就从该队列中选择一个线程。
负载共享的方法有:
① FCFS,即按顺序排队,选队首线程投入运行。
② 最少线程数优先(Smallest Number of Threads First),即共享就绪队列按优先级构造,具有未调度线程个数最少的作业其线程的优先级最高。
③ 抢占式最少线程数优先,是对最少线程数优先法的改造。如果新到来的作业所拥有的线程个数比当前运行作业的还少,就发生抢占。
负载共享方式的优点是负载分布在不同的处理器上;不需要集中调度,操作系统的调度程序可以运行在不同的处理器上。同时它也有若干缺点:对该全局队列占用的内存区必须互斥访问,可能成为瓶颈问题;由于被抢占的线程未必能在相同的处理器上恢复执行,因而降低本地高速缓存的效率;把所有线程看做公用线程池,一个进程的所有线程未必能同时获得处理器,从而严重损害处理器性能。
2、成组调度
这种方法把一组相关线程作为一个单位同时调到一组处理器上运行,一一对应,所有成组线程一起开始和结束它们的时间片。
成组调度可使一个进程的所有线程一起运行,若其中一个线程向另一个发出请求,能立即得到该信息且能立即回答。因此在一个时间片中,同一个进程的各线程间可以发送和接收大量的信息,大大方便了线程间的通信。
3、专用处理器分配
这是成组调度的极端形式。当一个进程被调度时,它的每个线程被分配到一个处理器上,在该进程完成之前,处理器由相应的线程专用。
这种方法会浪费处理器的时间。当一个线程为了与另一个线程同步而等待I/O时,该线程专用的处理器就闲置了。但是,在由几十甚至上百个处理器组成的高度并行系统中,处理器的利用率不再是最重要的问题。此外,在一个应用程序的生存期中完全避免了进程切换,因而大大加速了程序的执行。
4、动态调度
这种方法允许在进程执行期间动态改变其线程的数目。操作系统的调度职责主要限 于处理器的分配,并且遵循以下原则:当一个作业请求一个或多个处理器时,如果有空闲的处理器,就使用它们,以满足请求;否则,如果提出请求的作业是刚到来的,则从当前分得多个处理器的任何一个作业中拿出一个处理器分给该作业;如果任一部分请求都不能满足,该作业就保持未完成状态,直至有处理器可供它使用或该作业取消这个请求;当释放一个或多个处理器时,扫描当前尚未处理过的请求处理器的作业队列,且为队列中尚未分到处理器的每个作业分配一个处理器,然后再次扫描该队列,按FCFS方式分配其余的处理器。动态调度方法优于成组调度或专用处理器分配方法,但是这种方法的开销较大。

1.对称多处理器(SMP):每个处理器运行自己的调度程序;在调度中同步。
2.优先级翻转:低优先级进程抢占了共享资源,影响了高优先级进程的运行。高优先级进程反而受制于高优先级的进程。

5.同步与异步

由于系统缺陷,结果依赖于并发执行或者事件的顺序/事件,有不可重现和不确定性的缺点。可以用不被打断的指令避免。
原子操作是指一次不存在任何中断或者失败的执行。

临界区:指进程中的一段代码,需要访问共享资源,并且当另一个进程处于相应代码区域时不会被执行的代码区域。(访问共享资源的代码)

互斥:当一个进程处于临界区并访问共享代码时,没有其它进程会处于临界区并且访问任何相同的共享资源。

死锁:两个或以上的进程,在相互等待对方完成特定任务,而最终没法将自身任务进行下去。

饥饿:一个可执行的进程,被调度器持续忽略,以至于虽然处于可执行状态但不能执行。

上下文的切换导致线程不安全。

禁用中断

没有上下文切换,因此没有并发。整个系统都会为你停下来,可能导致其它线程处于饥饿状态(如果临界区无限长的话)

基于软件的方法

1.同一时间临界区最多只有一个线程
2.如果一个线程想要进入临界区,那么它最终会成功
3.有限等待,如果一个线程i处于入口区,那么在i的请求被接收之前,其它线程被接收之前,其它线程进入临界区的时间是有限制的。
4.无忙等待(可选):如果一个进程在等待进入临界区,那么在它可以进入之前会被挂起。

1)共享变量:不满足Progress,使用两个共享数据来控制进程

do{
	flag[i] = true;
	turn = j;
	while(flag[j]&&trun==j);
	CRITICAL SECTION
	flag[i] = false;
	REMAINDER SECTION
}while(TRUE);

2)Bakery算法:N个进程的临界区
进入临界区之前,进程接收一个数字
得到的数字最小的进入临界区
如果Pi和Pj得到相同的数字,那么如果i<j,Pi先进入临界区
编号方案总是按照枚举的增加顺序生成数字

但是需要忙等待

3)更高级的抽象:硬件提供了一些原语:如锁,信号量
test-and-set/exchange 使用忙等的锁
无忙等的锁+睡眠队列+唤醒
锁是更高等级的编程抽象

信号量

一个整型sem,两个原子操作p/v
P():sem-1,如果sem<0,等待
V():sem+1,如果sem<=0,唤醒等待的P

只有P/V能改变信号量,操作必须是原子的,一般用二进制信号量或者计数信号量来控制。
信号量的实现
1.使用硬件原语(禁用中断/原子指令test-and-set)

classSemaphore{
	int sem;
	WaitQueue;//FIFO
}

Semaphore::P(){
	sem--;
	if(sem < 0){
		Add this thread t to Q;
		Block(t); 
	}
}

Semaphore::V(){
	sem++;
	if(sem <= 0){
		Remove a thread t from Q;
		wakeup t;
	}
}
管程

目的:分离互斥和条件同步的关注
什么是管程:一个锁指定临界区,0或者多个条件变量:等待/通知信号量用于管理并发访问共享数据。

实现:
1.需要维护每个条件队列
2.线程等待的条件等待signal

Class Condition{
	int numWaiting = 0;
	WaitQueue q;
}

Condition::wait(lock){
	numWaiting++;
	Add this thread t to q;
	release(lock);
	schedule();//need mutex
	require(lock);
}

Condition::Signal(){
	if(numWaiting > 0){
		Remove a thread t from q;
		wakeup(t);//need mutex
		numWaiting --;
	}
}

在这里插入图片描述

经典同步问题:读者-写者问题

在这里插入图片描述
用信号量解决
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

经典同步问题:哲学家进餐问题

死锁

有死锁一定有环,有环不一定有死锁。
那么没有环一定没有死锁,如果有环,每个资源只有一个实例,那么死锁。否则不一定死锁。

死锁特征(四个条件同时成立)

1.互斥:在一个时间只有一个进程使用资源
2.持有并等待:进程保持至少一个资源正在等待获取其它进程持有的额外资源
3.无抢占:一个资源只能被进程自愿释放,进程已经完成了它的任务之后
4.循环等待:资源成环

死锁处理方法
1.确保不会死锁(会严重降低性能)
2.鸵鸟治理
3.打破四个必要条件
4.死锁避免:需要系统具有一些额外的先验信息提供,确保系统永远不会进入不安全状态。
(银行家算法)

死锁检测 ------ 死锁解决
1.终止所有的死锁进程
2.在一个时间内终止一个进程,直到死锁解决

6.IPC 进程间的通信

进程同步和进程通信的区别
进程同步:控制多个进程按照一定方式进行
进程通信:进程间传输信息

1.管道 用pipe()函数创建,fd[0]用读 fd[1]用写。
2.FIFO命名管道,去除了管道只能在父子进程中的限制。
3.消息队列:
在这里插入图片描述
4.信号量:它是一个计数器,用于为多个进程提供对共享数据对象的访问。
5.共享存储:在这里插入图片描述
6.套接字 Socket
流式套接字 TCP
数据报套接字 UDP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值