• 操作系统学习笔记--进程与线程


    目录

    进程

    概念

    组成:程序控制块PCB、程序段、数据段

    特征

    状态

    通信:进程之间的信息交换

    低级通信方式:PV操作

    高级通信方式

    共享存储

    分类

    消息传递

    分类

    管道通信

    线程

    概念

    属性

    状态:就绪、运行、阻塞

    线程的组织与控制

    线程控制块TCB包括内容:

    线程的创建

    线程的终止

    实现方式

    用户级线程(ULT)

     内核级线程(KLT)

     组合方式

    多线程模型

    一对一

    多对一

    多对多

    处理机调度

    概念

    基本准则

    分类

    不能进行进程调度与切换的情况

    调度方式

    闲逛进程

    典型调度算法

    先来先服务(FCFS)调度算法

    短作业优先(SJF)调度算法

    高响应比优先(HRRN)调度算法

    优先级调度算法

    优先级类型

    时间片轮转(RR)调度算法

    多级反馈队列调度算法

    进程同步与互斥

    进程同步

    概念

    进程互斥

    概念

    临界资源

    访问过程:

    访问遵循原则

    软件实现互斥方法

    单标志法

    双标志后检查

    Peterson算法

    硬件实现互斥方法

    中断屏蔽方法

    TestAndSet(TS/TSL)指令

    Swap(XCHG)指令

    信号量

    概念

    分类

    整形信号量

    记录型信号量

    实现进程同步

    实现进程互斥

    实现进程的前驱关系

    经典同步问题

    生产者-消费者问题

    多生产者-多消费者问题

    吸烟者问题

    读者写者问题

    哲学家问题

    管程

    概念

    组成

    基本特征

    互斥锁

    自旋锁

    死锁

    概念

    产生必要条件

    处理策略

    死锁预防

    避免死锁

    死锁的检测和解除

    检测

    资源分配图

    死锁定理

    解除


    进程

    概念

    不同的角度有不同的定义

    1. 进程是程序的一次执行过程
    2. 进程是一个程序及其数据在处理机上顺序执行时所发生的活动
    3. 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位
    • 进程:是动态的,是程序的一次执行过程
    • 程序:是静态的,就是个存放在磁盘的可执行文件,就是一系列的指令集合

    组成:程序控制块PCB、程序段、数据段

    程序控制块PCB:PCB 中应该包含操作系统对其进行管理所需的各种信息,如进程描述信息、进程控制和管理信息、资源分配清单和处理机相关信息。

    程序段:程序代码存放的位置

    数据段:程序运行时使用、广生的运算数据。如全局变量、局部变量、宏定义的常量就存放在数据段内

    ps:PCB是进程存在的唯一标志

    特征

    动态性进程的最基本的特征,进程是程序的一次执行过程,是动态的产生、变化和消

    亡。

    并发性:内存中有多个进程实体,各进程可并发执行。

    独立性:进程是能独立运行、独立获得资源、独立接受调度的基本单位。

    异步性:各个进程按各自独立的、不可预知的速度向前推进,操作系统要提供进程同步机制来解决异步问题。

    结构性:每个进程都会配置一个PCB。结构上看,进程由程序段、数据段和PCB组成。

    状态

    • 创建态:进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配
    • 运行态:进程占用CPU,并在CPU上运行的状态
    • 就绪态:进程已经具备运行条件,但由于未分配CPU 无法运行状态
    • 阻塞态:进程因等待某个事件发生而暂时不能运行的状态
    • 终止态:进程结束,或出现错误,或被系统终止,进入终止状态

    ps:运行态、就绪态、阻塞态是进程的基本状态

    通信:进程之间的信息交换

    低级通信方式:PV操作

    高级通信方式

    共享存储

    在通信进程中间存在一块可直接访问的共享空间,通过同步互斥工具(P/V)对这片空间写/读

    分类
    • 低级方式:基于数据结构
    • 高级方式:基于存储区

    ps:进程空间独立,不可互相直接访问。进程内的线程共享进程空间

    ​​​​​​​

    消息传递

    进程通过系统提供的发生消息接受消息两个原语进行数据交换。这种方式隐藏了通信实现细节,使通信过程对客户透明,简化了通信程序的设计,是当前使用最广泛的进程间通信机制

    分类
    • 直接通信方式:发生进程直接把消息发生给接收进程,并将它挂在接受进程的消息缓冲队列上,接收进程从消息缓冲队列取得消息
    • 间接通信方式:发生进程把消息发送到某个中间实体,接收进程从中间实体取得消息。这种中间实体称为信箱。这种通信方式广泛用于计算机网络中
    管道通信

    管道通信是消息传递的一种特殊方式,半双工通信。所谓管道,是指用于连接一个读进程和写进程以实现它们之间的通信的一个共享文件(pipe文件/管道文件),管道机制提供以下三方面协调能力:互斥、同步、确定对方存在

    ​​​​​ps:只要管道区非空即可读出/写入 

    线程

    概念

    线程是“轻量级”进程,被包含在进程中,是进程的一个实体,是被系统独立调度和分配的最小单元,是一个基本的CPU执行单元,也是程序执行的最小单元。一个线程可创建和撤销另一个线程,同一个进程的线程可并发执行。

    属性

    1. 线程是一个轻型的实体。它不拥有系统资源,但每个线程都应有一个唯一的标识符和一个线程控制块,线程控制块记录了线程执行的寄存器和栈等现场状态
    2. 不同的线程可执行相同的程序。即同一个服务程序被不同的用户调用时,操作系统把他们创建成不同的线程
    3. 同一个进程的各个线程共享该进程所拥有的资源
    4. 线程是处理机的独立调度单位,多个线程是可以并发执行的。在单CPU的计算机系统中,各线程共享该进程所拥有的资源
    5. 一个线程被创建后,便开始了它的生命周期,直至终止。线程在生命周期内会经历阻塞态、运行态和就绪态

    状态:就绪、运行、阻塞

    线程的组织与控制

    线程控制块TCB包括内容:

    1. 线程标识符
    2. 一组寄存器,包括程序计数器、状态寄存器和通用寄存器
    3. 线程运行状态
    4. 优先级
    5. 线程专有存储区:保护现场
    6. 堆栈指针:用于过程调度时保持局部变量及返回地址

    线程的创建

    用户程序启动时,通常仅有一个称为“初始化线程”的线程正在执行,其主要功能是用于创建新线程。在创建新线程时,需要利用一个线程创建函数,并提供相应的参数,如指向线程主程序的入口指针,堆栈的大小,线程优先级等。线程创建函数执行完成后,将返回一个线程标识符

    线程的终止

    当一个线程完成它的任务后,或线程在运行中出现异常而要被强行终止时,由终止线程调用相应的函数执行终止操作,被终止后不会立即释放所占用的资源。但有些线程一旦被创建便一直运行,不会终止。

    实现方式

    用户级线程(ULT)

    优点:

    1. 线程切换不需要转换到内核空间,节省了模式切换的开销
    2. 调度算法可以是进程专用的,不同的进程可根据自身的需要,对自己的线程选择不同的调度算法
    3. UTL的实现与操作系统平台无关,对线程管理的代码是属于用户进程的一部分

    缺点:

    1. 系统调用的阻塞问题,当线程执行一个系统调用时,不仅该线程阻塞,而且进程内的所有线程都被阻塞
    2. 不能发挥多处理机优势,进程中仅有一个线程能执行

     内核级线程(KLT)

    优点:

    1. 能发挥多处理机的优势,内核能同时调度同一个进程的多个线程并行执行
    2. 如果一个进程中的一个线程被阻塞,内核可调度该进程中的其他线程占用处理机,也可调度其他进程中的线程
    3. 内核支持线程具有很小的数据结构和堆栈,线程切换比较快、开销小
    4. 内核本身也可采用多线程技术,可以提高系统的执行速度和效率

    缺点:同一进程的线程切换需从用户态切换到核心态进行,系统开销大

     组合方式

    多线程模型

    一对一

    将每个用户级线程映射到一个内核级线程

    优点:当一个线程被阻塞后,允许另一个线程运行,故并发能力强

    缺点:每创建一个用户线程,相应地就需要创建一个内核进程,开销较大

    多对一

    将多个用户级线程映射到一个内核级线程

    优点:线程管理是在用户空间进行的,因此效率较高

    缺点:如果一个线程在访问内核时阻塞,则整个进程堵塞。在任何时刻只能有一个线程能够访问内核

    多对多

    将n个用户级线程映射到m个内核级线程(n>=m)

    特点:既克服了多对一模型并发度不高的缺点,又克服了一对一模型的一个用户进程占用太多内核级线程而开销的缺点,此为也拥有其他两种模型的优点

    处理机调度

    概念

    处理机调度是对处理机进行分配,即从就绪队列中按照一定的算法(公平、高效)选择一个进程并将处理机分配给它运行,以实现进程并发地执行。

    基本准则

    1. CPU利用率
    2. 系统吞吐量
    3. 周转时间。周转时间=完成时间-等待时间
    4. 等待时间。等待时间=周转时间-运行时间
    5. 响应时间。响应时间=(等待时间+要求服务时间)/要求服务时间

    分类

    作业调度(高级调度):按一定的原则从外存上处于后备状态的作业中挑选一个(或多个)作业,给它(们)分配内存、输入/出设备等必要的资源,并建立相应的进程,以使它 (们)获得竞争处理机的权利。简言之,作业调度就是内存与辅存之间的调度。对于每个作业只调入一次、调出一次。执行频率最低

    中级调度(内存调度):提高内存利用率和系统吞吐量。将那些暂时不能运行的进程调至外存等待,把此时的进程状态称为挂起态。当它们已具备运行条件且内存又稍有空闲时,由中级调度来决定把外存上的那些己具备运行条件的就绪进程,再重新调入内存,并修改其状态为就绪态,挂在就绪队列上等待。

    进程调度(低级调度):按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。进程调度是操作系统中最基本的一种调度,执行频率最高

    不能进行进程调度与切换的情况

    1. 在处理中断的过程中
    2. 进程在操作系统内核程序临界区中
    3. 其他需要完全屏蔽中断的原子操作过程中

    调度方式

    • 非剥夺调度(非抢占)方式。非剥夺调度方式是指当一个进程正在处理机上执行时,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在执行的进程继续执行,直到该进程完成或发生某种事件而进入阻塞态时,才把处理机分配给更为重要或紧迫的进程。这种方式的优点是实现简单、系统开销小,适用于大多数的批处理系统,但它不能用于分时系统和大多数的实时系统
    • 剥夺调度(抢占)方式。剥夺调度方式是指当一个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给这个更为重要或紧迫的进程。采用剥夺式的调度,对提高系统吞吐率和响应效率都有明显的好处。但“剥夺”不是一种任意性行为,必须遵循一定的原则,主要有优先权、短进程优先和时间片原则等。

    闲逛进程

    若系统中没有就绪进程,就会调度闲逛进程运行。闲逛不需要CPU之外的资源,因此不会被阻塞

    典型调度算法

    先来先服务(FCFS)调度算法

    • 算法规则:按照作业/进程调度到达的先后顺序进行调度
    • 适用情况:属于不可剥夺算法,可用于进程调度、作业调度
    • 优点:算法简单,对长作业有利,有利于CPU繁忙型作业,不会导致某进程或作业得不到服务(不会导致饥饿
    • 缺点:效率低,对短作业不利,不利于I/O繁忙型作业

    短作业优先(SJF)调度算法

    • 算法规则:以作业的长短来计算优先级,作业越短,其优先级越高
    • 适用情况:属于抢占/非抢占算法,可用于进程调度、作业调度
    • 优点:对短作业有利,“最短的”平均等待时间及平均周转时间
    • 缺点:不公平,对长作业不利,,未考虑作业的紧迫程度,可能产生饥饿现象

    ps:SRTN最短剩余时间优先算法是抢占算法

    高响应比优先(HRRN)调度算法

    • 算法规则:在每次调度时先计算进程/调度的响应比,选择响应比最高的进行服务 ​​​​​​​
    • 适用情况:属于非抢占算法可用于进程调度、作业调度
    • 优点:综合考虑了等待时间和运行时间。等待时间相同时,要求服务时间最短的优先(SFJ)。要求服务时间相同时,等待时间最短的优先(FCFS
    • 缺点:会导致长作业饥饿问题

    优先级调度算法

    • 算法规则:每个作业/进程有各自的优先级,调度时选择优先级最高的作业/进程
    • 适用情况:属于抢占/非抢占算法,可用于进程调度、作业调度
    • 优点:用优先级区分紧急程度、重要程度,适用于实时操作系统
    • 缺点:可能导致饥饿
    优先级类型
    • 静态优先级:创建进程时确定,之后一直不变。
    • 动态优先级:创建进程时有一个初始值,之后会根据情况动态地调整优先级。

    ps:如果某进程在就绪队列中等待了很长时间,则可以适当提升其优先级。如果某进程占用处理机运行了很长时间,则可适当降低其优先级

    时间片轮转(RR)调度算法

    • 算法规则:按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片。若进程未到一个时间片内执行完,则剥夺处理机,將进程重新放到就绪队列队尾重新排队。
    • 适用情况:属于抢占算法,只用于进程调度
    • 优点:公平,响应快,适用于分时操作系统,不会导致饥饿
    • 缺点:高频率的进程切换引起较大的开销不区分任务紧急程度

    多级反馈队列调度算法

    • 算法规则:
      1. 设置多级就绪队列,各级队列优先级从高到低,时问片从小到大
      2. 新进程到达时先进入第1级队列,按FCFS原则排队等待被分配吋间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。若此时己经是在最下级的队列,则重新放回该队列队尼
      3. 只有第k级队列为空时,才会为k+1 级队头的进程分配时间片
    • 适用情况:属于抢占算法,可用于进程调度
    • 优点:对各类型进程相对公平 (FCFS的优点);每个新到达的进程都可以很快就得到响应(RR的优点);短进程只用较少的时间就可完成(SPF的优点);不必实现估计进程的运行时间(避免用户作假);可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/O密集型进程
    • 缺点:会产生饥饿现象

    具体过程详解看王道考研-操作系统:​​​​​​​2.2_6_调度算法(2)_哔哩哔哩_bilibili

    进程同步与互斥

    进程同步

    概念

    同步也称直接制约关系,它指的是多个进程一起完成某个任务,这些进程因为合作、因为需要在某些位置上协调他们的工作次序而产生了某些制约关系。

    进程互斥

    概念

    进程互斥也称问接制约关系。当某个进程A在访问临界区使用临界资源时,另一个B进程必须等待,直到4进程访问结束并释放打印机资源后,B进程才能去访问。

    临界资源

    是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式,实现共享的资源

    ps:属于临界资源的硬件:打印机,磁带机等;软件:消息队列,变量,数组,缓冲区等

    访问过程:
    1. 进入区。为了进入临界区使用临界资源,在进入区要检查可否进入临界区,若能进入临界区,则应设置正在访问临界区的标志,以阻止其他进程同时进入临界区。
    2. 临界区。进程中访问临界资源的那段代码,又称临界段。
    3. 退出区。将正在访问临界区的标志清除。
    4. 剩余区。代码中的其余部分。
    访问遵循原则
    • 空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。
    • 忙则等待。当己有进程进入临界区时,其他试图进入临界区的进程必须等待。
    • 有限等待。对请求访问的进程,应保证能在有限时问内进入临界区。
    • 让权等待。当进程不能进入临界区时,应立即释放处理器,防止进程忙等待。

    软件实现互斥方法

    单标志法
    • 算法思想:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予
    • 优点:可确保每次只允许一个进程进入临界区
    • 缺点:违背了“空闲让进”,造成了资源利用不充分
    双标志后检查
    • 算法思想:先将自己的标志设置为 TRUE,再检测对方的状态标志,若对方标志为TRUE,则进程等待;否则进入临界区。
    • 优点:解决了“忙则等待”的问题
    • 缺点:违背了“空闲让进”和“有限等待”,造成了资源利用不充分,可能会产生饥饿现象
    Peterson算法
    • 算法思想:为了防止两个进程为进入临界区而无限期等待,又设置了变量 turm,每个进程在先设置自己的标志后再设置 turn 标志。这时,再同时检测另一个进程状态标志和不允许进入标志,以便保证两个进程同时要求进入临界区时,只允许一个进程进入临界区。​​​​​​​
    • 优点:遵循了“忙则等待”、“空闲让进”、“有限等待”
    • 缺点:违背了“让权等待”的原则

    硬件实现互斥方法

    中断屏蔽方法
    • 原理:利用“开/关中断指令”实现
    • 优点:简单、高效
    • 缺点:不适用于多处理机只适用于操作系统内核进程,不适用于用户进程
    TestAndSet(TS/TSL)指令
    • 原理:把“上锁”和“检查”操作用硬件的方式变成了一气呵成的原子操作执行,过程中不允许被中断
    • 优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境
    • 缺点:不满足“让权等待” 原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致“忙等”。
    Swap(XCHG)指令

    和TS无太大区别

    信号量

    概念

    信号量机制:是一种功能较强的机制,可用来解决互斥与同步问题,它只能被两个标准的原语

    wait(S)和 signal(S)访问,也可记为“P操作”和“V操作”

    分类

    整形信号量

    整型信号量被定义为一个用于表示资源数目的整型量 S

    特点:未遵循“让权等待”原则

    记录型信号量

    除需要一个用于代表资源数目的整型变量 value 外,再增加一个进程链表L,用于链接所有等待该资源的进程。

    ps:当S.value<=0时,资源被分配完,系统调用block原语阻塞

    特点:遵循了“让权等待”原则

    实现进程同步

    1. 分析什么地方需要实现 “同步关系”,即必须保证“一前一后”执行的两个操作(或两向代码)
    2. 设置同步信号量S,初始为0。
    3. 在“前操作” 之后执行 V(S)
    4. 在“后操作” 之前执行 P(S)

    实现进程互斥

    1. 分析并发进程的关键活动,划定临界区(如:对临界资源打印机的访问就应放在临界区)
    2. 设置互斥信号量mutex,初值为 1
    3. 在进入区 P(mutex)一一申请资源
    4. 在退出区 V(mutex)一一释放资源

    ps:mutex表示进入临界区的名额。

    实现进程的前驱关系

    1. 要为每一对前驱关系各设置一个同步信号量
    2. 在“前操作” 之后对相应的同步信号量执行V操作
    3. 在“后操作” 之前对相应的同步信号量执行P操作

    经典同步问题

    生产者-消费者问题

    1)问题描述

    系统中有一组生产者进程和一组消费者进程,生产者进程每一次生产一个产品放入缓冲区,消费者进程每次从缓沖区中取出一个产品并使用。(注:这里的“产品”理解为某种数据)。

    生产者、消费者共享一个初始为空、大小为n的缓冲区。

    只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。

    只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。

    缓沖区是临界资源,各进程必须互斥地访问。

    2)问题分析

    该问题中出现的主要的两种关系:

    1. 生产者一消费者之问的同步关系表现为:一旦缓冲池中所有缓冲区均装满产品时,生广者必须等待消费者提供空缓沖区;一旦缓冲池中所有缓冲区全为空时,消费者必须等待生广者提供满缓冲区。
    2. 生广者一消费者之问还有互斥关系:由于缓冲池是临界资源,所以任何进程在对缓沖

    区进行存取操作时都必须和其他进程互斥进行。

    PV操作题目分析的步骤:

    1. 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
    2. 整理思路。根据各进程的操作流程确定PV操作的大致顺序。
    3. 设置信号量。设置需要的信号量,并根据题目条件确定信号量的初值。(互斥信号量初

    值一般为1,同步信号量的初值需要看对应资源的初始值是多少)

    3)如何实现

    互斥的实现是在同一个进程中进行的一对PV操作。

    同步的实现是在两个进程中进行的,在一个进程中执行P操作,在另一个进程中执行V

    操作。

    多生产者-多消费者问题

    吸烟者问题

    读者写者问题

    哲学家问题

    管程

    概念

    代表共享资源的数据结构,以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序

    组成

    1. 管程的名称
    2. 局部于管程内部的共享结构数据说明
    3. 对该数据结构进行操作的一组过程(或函数)
    4. 对局部于管程内部的共享数据设置初始值的语句

    基本特征

    1. 局部于管程的数据只能被局部于管程的过程所访问;
    2. 一个进程只有通过调用管程内的过程才能进入管程访问共享数据:
    3. 每次仅允许一个进程在管程内执行某个内部过程。

    互斥锁

    解决临界区最简单的工具

    ps:一个进程在进入临界区时应获得锁;在退出临界区时释放锁。

    • 获得锁:acquire()
    • 释放锁:releasc()

    ps:acquire0或 release0的执行必须是原子操作,因此互斥锁通常采用硬件机制实现。

    特点:忙等待,违反了“让权等待”,等待期间不需要切换上下文,适用于多处理器系统

    自旋锁

    需要连续循环忙等的互斥锁(如单标志法、TSL指令、swap指令)

    死锁

    概念

    是指在并发环境下多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。

    产生必要条件

    1. 互斥条件:只有对必须互斥使用的资源的争抢才会导致死锁 。
    2. 不剥夺条件:进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放。
    3. 请求和保持条件:进程己经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其他进程占有,此时请求进程被阻塞,但又对自己己有的资源保持不放。
    4. 循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程己获得的资源同时被下一个进程所请求。

    ps:必须同时满足上述4个条件才会发生死锁

    处理策略

    死锁预防

    破坏死锁产生的四个必要条件中的一个或几个

    1. 破坏互斥条件:一般不可行
    2. 破坏不剥夺条件:当某个进程请求新资源无法满足时,立即释放所占有的资源
    3. 破坏请求和保持条件:静态分配法。进程在运行前一次申请完它所需要的全部资源
    4. 破坏循环等待条件资源有序分配策略
    避免死锁

    用某种方法防止系统进入不安全状态,从而避免死锁(银行家算法)

    ps:死锁一定是在不安全状态下,不安全状态不一定会导致死锁

    死锁的检测和解除

    允许死锁的发生,不过操作系统会负责检测出死锁的发生,然后采取某种措施解除死锁。

    检测
    资源分配图

    圆圈代表一个进程;框代表一类资源;框内的一个圆代表一类资源中的一个资源

    两种结点:进程结点和资源结点(资源结点可能有多个〕

    两种边:

    1. 进程结点->资源结点:代表一个进程结点请求一类资源。
    2. 资源结点->进程结点:代表这类资源已经分配给了指向的进程结点。
    死锁定理

    用于检测系统状态,以确定系统中是否发生了死锁。

    解除
    1. 资源剥夺法。将某些死锁进程锁占有的资源剥夺井分配给其他进程。但是应该防止被挂起的进程长时间得不到资源饿死。
    2. 撤销进程法。强制撒销部分死锁进程或者全部死锁进程
    3. 进程回退法。让一个或多个死锁进程回退到足以避免死锁的地步。这个就要求记录进程的历史消息,设置还原点。


    ​​​​​​​

  • 相关阅读:
    java计算机毕业设计客户关系智能管理系统源码+系统+mysql数据库+lw文档+部署
    电脑如何打开软键盘,教大家Win10如何打开软键盘的方法
    vue2项目中使用element ui组件库的table,制作表格,改表格的背景颜色为透明的
    基于C语言实现的全局光照明模型
    tcp checksum 0xffff instead of 0x0000 see rfc 1624
    1205. 每月交易II
    Multi-Path Transport 的误区
    预定义ContentProvider
    webpack快速入门-核心概念
    掷骰子的多线程应用程序2基于互斥量的线程同步(复现《Qt C++6.0》)
  • 原文地址:https://blog.csdn.net/m0_65204379/article/details/131811014