c++后台开发面试常见知识点总结(三)操作系统

  • 静态链接库和动态链接库的区别
  • 一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止
  • DebugRelease的区别
  • 临界区互斥量信号量事件进程互斥与同步
  • 进程有哪几种状态,状态转换图,及导致转换的事件
  • 进程由运行态进入就绪态和阻塞态的原因
  • 进程切换
  • 进程调度算法
  • 死锁
  • 哲学家就餐问题
  • linux运行时内存映像
  • 通过虚拟地址访问内存的优势
  • 缓存是数据交换的缓冲区(称为Cache
  • 线程访问某数据
  • 无名管道  FIFO(命名管道)消息队列信号量信号共享内存

1.    静态链接库和动态链接库的区别:

(1)       静态链接库在编译阶段链接,动态链接库库在加载和运行阶段链接。

(2)       在任何给定的文件系统中,只有动态链接库的一个副本,静态库的内容被复制和嵌入到引用它们的每一个执行文件中

(3)       在内存中,一个动态链接库的.text节的一个副本可以被不同的正在运行的进程共享;静态链接库的函数的代码会被复制到每个运行进程的代码段中。

(4)       如果想使用一个静态库的最新版本,必须显式地将程序与更新了的库重新链接;而如果想使用动态链接库最新版本只需要使用动态链接库的新版本替代当前的版本。

(5)       静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。

2.    进程和线程的区别:

(1)       进程是资源分配、调度的最小单位,线程是CPU调度的最小单位。

(2)       进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。

(3)       线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以进程间通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。

(4)       多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另一个进程造成影响。

注:上述提到的资源包括可重用资源:处理器、I/O部件、内存、文件、数据库、信号量

可消耗资源:信号、中断、消息

3.    多进程和多线程的选择

(1)       需要频繁创建、销毁的选用多线程。

(2)       需要频繁切换的选用多线程

(3)       要求共享某些变量的选用多线程。

(4)       可能要扩展到多机分布的用多进程,多核分布的用多线程

(5)       强相关的处理用多进程,弱相关的用多线程。

4.    fork函数

子进程得到与父进程用户级虚拟地址空间相同(但是独立的)一份副本,包括代码和数据段、堆、共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本。

(1)       调用一次,返回两次。fork函数被父进程调用一次,但是却返回两次——一次是返回到父进程,一次是返回到新创建的子进程。在父进程中,fork返回子进程的PID。在子进程中,fork返回0

(2)       并发执行。父进程和子进程是并发运行的独立进程。内核能够以任意方式交替执行它们的逻辑控制流中的指令。

(3)       相同但是独立的地址空间。如果能够在fork函数在父进程和子进程返回后立即暂停这两个进程,我们会看到两个进程的地址空间都是相同的。每个进程有相同的用户栈、相同的本地变量值、相同的堆、相同的全局变量值,以及相同的代码。

(4)       共享文件。子进程继承了父进程所有的打开文件。

5.    一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止。

6.    Debug和Release的区别

(1)       Debug:调试版本,包含调试信息,所以容量比Release版本大很多,并且不进行任何优化(优化会使调试复杂化,因为源代码和生成的指令间关系会更复杂),便于程序员调试。Debug模式下生成两个文件,除了.exe或.dll文件外,还有一个.pdb文件,该文件记录了代码中断点等调试信息。

(2)       Release:发布版本,不对源代码进行调试,编译时对应用程序进行优化,使得代码大小和运行速度上都是最优的。Release模式下生成一个文件.exe或.dll文件。

7.    编译语言和脚本语言的区别

(1)脚本语言语法简单,比较容易掌握;编译语言具有严谨,复杂语法。

(2)脚本语言在运行时被解释器解释成指令后立即被执行;编译语言被编译成可执行目标文件后被执行。

(3)因此,脚本语言不需编译,但运行速度慢;编译语言需要编译,运行速度较快。

8.    线程安全

(1)       线程安全就是多线程访问时,采用了加锁机制(同步互斥机制),当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程访问结束,其他线程才可使用。不会出现数据不一致或者数据污染。

(2)       线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

注:怎么判断线程安全:多线程编程中,对类的对象的操作不需要使用额外的同步机制,也能保证对象不会处于无效状态。

9.    临界区

用于解决互斥问题。临界区保证同一时刻只有一个线程可以访问被保护起来的资源或代码段,所有其他试图访问被保护起来的资源或代码段的线程将被挂起,并一直持续到当前正在访问被保护起来的资源或代码段的线程访问完毕。临界区对象被释放后,其他线程可以继续抢占临界区对象的使用。

特点:临界区不是内核对象,不能够用于进程之间的互斥,但临界区更节省资源更有效率。

10. 互斥量

用于解决互斥问题。互斥量允许同一时刻只有一个进程访问互斥资源,所有其他试图访问互斥资源的进程将被挂起,并一直持续到访问互斥资源的线程访问完毕。互斥量被释放后,其他线程可以继续抢占互斥资源的使用。

11. 信号量

信号量是进程间同步、互斥的一种机制。信号量允许多个进程访问共享资源,但对同一时刻访问共享资源的进程的数目的上限有要求。

注:

(1)在信号量上定义了三个操作:初始化、P操作、V操作

(2)P、V操作为原语操作

(3)信号量可分为二元信号量,用于解决互斥问题;多值信号量,用于解决同步问题

12. 事件

事件机制,允许一个线程在处理完一个任务后,主动唤醒另一个线程执行任务。

自动事件:当一个事件得到通知时,等待该事件的线程只有一个线程变为可调度线程。

人工事件:当一个事件得到通知时,等待该事件的所有线程均变成可调度线程。

13. 进程互斥与同步

(1)进程互斥:各进程之间竞争使用互斥资源,这一关系称为进程互斥。

(2)进程同步:指系统中多个进程中发生的事件存在某种时序关系,需要相互合作,共同完成一项任务。

14. 进程有哪几种状态,状态转换图,及导致转换的事件

运行状态:进程正在处理机上运行。在单处理机环境下,每一时刻最多只有一个进程处于运行状态。

就绪状态:进程已处于准备运行的状态,即进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行。

阻塞状态,又称等待状态:进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理机)或等待输入/输出完成。即使处理机空闲,该进程也不能运行。

就绪状态 -> 运行状态:处于就绪状态的进程被调度后,获得处理机资源(分派处理机时间片),于是进程由就绪状态转换为运行状态。

运行状态 -> 就绪状态:处于运行状态的进程在时间片用完后,不得不让出处理机,从而进程由运行状态转换为就绪状态。此外,在可剥夺的操作系统中,当有更高优先级的进程就绪时,调度程度将正执行的进程转换为就绪状态,让更高优先级的进程执行。

运行状态 -> 阻塞状态:当进程请求某一资源(如外设)的使用和分配或等待某一事件的发生(如I/O操作的完成)时,它就从运行状态转换为阻塞状态。进程以系统调用的形式请求操作系统提供服务,这是一种特殊的、由运行用户态程序调用操作系统内核过程的形式。

阻塞状态 -> 就绪状态:当进程等待的事件到来时,如I/O操作结束或中断结束时,中断处理程序必须把相应进程的状态由阻塞状态转换为就绪状态。

15. 进程由运行态进入就绪态和阻塞态的原因

(1)时间片用完

(2)在可抢占的操作系统中,有更高优先级的进程就绪

(3)进程请求某一资源的使用和分配

(4)进程等待某一个时间的发生(如I/O操作完成)

(5)进程需要和其他进程保持同步

(6)进程运行完毕

(7)在不可抢占的操作系统中,进程由核心态转入用户态时系统产生一次调度,将最高优先权的就绪进程投入运行。

16. 进程切换

进程切换主要包括两部分工作:

(1)切换全局目录以加载一个新的地址空间

(2)切换内核栈和硬件上下文,其中硬件上下文包括了内核执行新进程需要的全部信息,如CPU相关寄存器(程序计数器、程序状态寄存器)

注:切换过程包括了对原来运行进程各种状态的保存和对新的进程各种状态的恢复。

17. 进程调度算法

(1)       批处理系统中采用的调度算法:

① 先来先服务(FCFS):按进程就绪的先后顺序使用CPU(非抢占式)

优缺点:公平、实现简单、长进程后面的短进程需要等待很长时间,不利用用户体验

② 最短作业优先(SJF):具有最短完成时间的进程优先执行(非抢占式)

思路:先完成短的作业,改善短作业的周转时间

优缺点:

最短的平均周转时间:在所有进程同时可运行时,采用SJF调度算法可以得到最短的平均周转时间

不公平:源源不断的短任务到来,可能使长的任务长时间得不到运行->产生“饥饿”现象

③ 最短路径剩余空间时间优先(SRTN)(抢占式)

④ 最高响应比优先:是一个综合的算法,调度时,首先计算每个进程的响应比R;之后,总是选择R最高的进程执行;折中权衡。

响应比R=周转时间/处理时间=(处理时间+等待时间)/处理时间=1+(等待时间/处理时间)

(2)       交互式系统中采用的调度算法

① 时间片轮转

目标:为短任务改善平均响应时间

解决问题的思路:周期性切换;每个进程分配一个时间片;时钟中->轮换

时间片太长:降级为先来先服务算法;延长短作业的响应时间

时间片太短:进程频繁切换浪费CPU时间

优缺点:公平;有利于交互式计算,响应时间快;由于进程频繁切换,时间片轮转算法要花费较高的开销用于进程的切换。

② 最高优先级调度:选择优先级最高的进程投入运行

③ 多级反馈队列

设置多个就绪队列,第一级队列优先级最高。

给不同就绪队列中的进程分配长度不同时间片,第一级队列时间片最小;

随着队列优先级别的降低,时间片增大;

当第一级队列为空时,在第二级别队列调度,以此类推

各级队列按照时间片轮状方式进程调度

当一个新创建进程就绪后,进入第一级队列

进程用完时间片而放弃CPU,进入下一级就绪队列

由于阻塞而放弃CPU进入想用的等待队列,一旦等待队列发生,该进程回到原来一级就绪队列。

④ 最短进程优先

18. 典型系统所采用的调度算法

Unix:

Windows:基于优先级的抢占式多任务调度

Linux:抢占式调度

19. 大端模式和小端模式

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中

小端模式,是指数据的低字节保存在数据的低地址中,数据的高字节保存在数据的高地址中。

20. 死锁的概念

一组进程中,每个进程都无限等待被该组进程中的另一个进程所占有的资源,这种现象称为进程死锁,这一组进程被称为死锁进程。

21. 死锁、活锁和饥饿

(1)死锁:

(2)活锁:先加锁,在轮询,不断轮询,既无进展也没有阻塞

(3)饥饿:持续有其他的优先级更高的进程请求相同的资源,所申请的资源一直得不到满足。饥饿现象是由资源分配策略决定的。

22. 产生死锁的必要条件

(1)互斥使用

一个资源每次只能给一个进程使用

(2)占有且等待

进程在申请新的资源的同时保持对原有资源的占有

(3)不可抢占

资源的申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放。

(4)循环等待

存在一个进程等待队列{P1,P2,...,P3},

其中P1等待P2占有的资源,P2等待P3占有的资源,...,Pn等待P1占有的资源,形成一个进程等待环路。

23. 死锁定理

(1)如果资源分配图中没有环路,则系统中没有死锁,如果图中存在环路则系统中可能存在死锁。

(2)如果每个资源类中只包含一个资源实例,则环路是死锁存在的充分必要条件。

24. 解决死锁的方法

(1)死锁预防

静态策略:设计合适的资源分配算法,不让死锁发生。

(2)死锁避免

动态策略:以不让死锁发生为目标,跟踪并评估资源分配过程,根据评估结果决策是否分配

(3)让死锁发生

死锁检测与解除

25. 死锁预防

在设计系统时,通过确定资源分配算法,排除死锁发生的可能性

(1)破坏“互斥使用/资源独占”条件

资源转换技术:把独占资源变为共享资源

spoing技术的引入

(2)破坏“占有且等待”条件

实现方案1:要求每个进程在运行前必须一次性申请它要求的所有资源,且仅当该进程所要资源均可满足时才给予一次性分配。

问题:资源利用率低;“饥饿”现象

实现方案2:在允许进程动态申请资源前提下规定,一个进程在申请新的资源不能立即得到满足而变为等待状态之前,必须释放已占有的全部资源,若需要再重新申请。

(3)破坏“不可抢占”条件

当一个进程申请的资源被其他进程占用时,可以通过操作系统抢占这一资源(两个进程的优先级不同)

局限性:适用于状态易于保存和恢复的资源(CPU、内存)

(4)破坏“循环等待”条件

资源的有序分配法:把系统中所有资源编号,进程在申请资源时必须严格按资源编号的递增次序进程,否则操作系统不予分配。

26. 死锁避免

在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁

27. 安全状态

安全状态:如果系统中存在一个由所有进程构成的安全序列P1,...,Pn,则称系统处于安全状态。

安全序列:一个进程序列{P1,...,Pn}是安全地,如果对于没一个进程pi(1<=i<=n);它以后还需要的资源量不超过系统当前剩余资源量与所有进程pi(j<i)当前占有资源量之和。

28. 死锁的检测与解除

允许死锁的发生,但是操作系统不断检测死锁是否真的发生。

一旦死锁发生则采取专门的措施,解除死锁并以最小的代价恢复操作系统运行。

29. 死锁解除的办法:

(1)撤销所有的死锁进程

(2)按照某种原则逐一地撤销死锁进程

(3)进程回退再启动

(4)按照某种原则逐一抢占资源(资源被抢占的进程必须回退到之前的对应状态)

30. 哲学家就餐问题

(1)最多允许4个哲学家同时坐在桌子周围(死锁预防)

(2)仅当一个哲学家左右两边的筷子都可用时,才允许它拿筷子(死锁避免)

(3)给所有哲学家编号,奇数好的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之

31. 堆和栈的区别

(1)管理方式:栈中的空间由编译器自动分配和释放,堆中的空间由程序显式地释放和分配

(2)存储内容:栈中存储函数的参数值和局部变量;对中存储动态对象

(3)空间大小:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。栈的最大容量是系统预先规定好的,在Windows下,栈的大小是2M因此,能从栈获得的空间较小;堆是向高地址扩展的数据结构,是不连续的内存区域。堆的大小受限于计算机系统中有效的虚拟内存。能从堆获得的空间较大。

(4)分配效率:栈由操作系统自动分配和释放,(计算机在底层对栈提供支持)栈的分配效率比较高;堆的分配由C/C+函数库提供,机制复杂,堆的分配效率要比栈低很多。

(5)碎片问题:对于堆来说,频繁的new/delete操作势必会造成内存空间的不连续,从而造成大量的碎片;栈不会产生空间碎片。

32. linux运行时内存映像

33. 一个源程序到可执行目标文件的过程

(1)预处理阶段:预处理器(cpp)根据以字符#开头的命令,修改原始的C程序。

(2)编译阶段:编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序

(3)汇编阶段:汇编器(as)将一个hello.s翻译成机器语言指令,把这些指令打包成一个叫做可重定位目标程序的格式,并把结果保存在目标文件hello.o中。Hello.o文件是一个二进制文件。

(4)链接阶段:生成可执行目标文件。

34. 虚拟内存

虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存,而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。目前,大多数操作系统都使用了虚拟内存。

虚拟内存别称虚拟存储器。电脑中所运行的程序均需经由内存执行,若当前正在执行的程序占用内存很大或很多,则会导致内存消耗殆尽,为了解决该问题。Windows中运用了虚拟内存技术,即匀出一部分硬盘空间来充当内存使用。当内存耗尽时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张。

35. 通过虚拟地址访问内存的优势

(1)程序可以使用一系列相邻的虚拟地址空间来访问物理内存中不相邻的内存缓冲区

(2)程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为4KB)保存到磁盘文件。数据和代码页会根据需要在物理内存与磁盘之间移动。

(3)每个进程拥有独立的虚拟地址空间,一个进程的代码无法更改正在由另一个进程或操作系统使用的物理内存。因此,可以避免一个进程无意间破坏另一个进程所使用的物理内存中内容。

36. 缓存:

缓存是数据交换的缓冲区(称为Cache),当某一个硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。由于缓存的运行速度比内存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快的运行。

37. 如何实现地址映射

Win32通过两层的表结构实现地址隐射:

第一层为页目录表(4KB大小):分为1024个页目录项,每个页目录项对于一个页表

第二层为页表(4KB大小):分为1024个页表项,每个页表项对应一个内存页,通过有4KB大小

32位地址:前10位为页目录下标,用来寻址页目录项,中间10位为页表下标,用来寻址内存页,后12位用来在物理内存页中找到对应的字节

38. 线程访问某数据

39. 缓存调度:

40. 缓存调度方法:

(1)FIFO

(2)LRU:最近最少使用

(3)LFU:最近使用次数最少

41. LRU实现

核心思想:“如果数据最近被访问过,那么将来被访问的几率也更高”

(1)新加入的数据插入到链表头部

(2)数据被访问,将数据移动到链表头部

(3)当链表满,将链表尾部的数据丢弃

42. LFU实现

“如果数据过去被访问多次,那么将来被访问的频率也更高”

(1)新加入的

43. 无名管道

管道:通常指无名管道,是UNIX系统IPC最古老的形式。

两个局限性:

(1)单向通信

(2)只能用于具有亲缘关系的进程之间

其他特点:

(3)管道的生命周期随着进程终止而结束

(4)它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中

44. FIFO(命名管道)

FIFO,也称为命名管道,它是一种文件类型

FIFO的特点:

(1)它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中

(2)FIFO可以用于无亲缘关系的进程之间的通信

(3)按照先进先出的方式工作

45. 消息队列

消息队列,是消息的的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识

(1)消息队列是基于消息的(管道是基于字节流的),其中的消息具有特定的格式以及特定的优先级

(2)消息队列独立于发送和接收进程。进程终止时,消息队列内容不会被删除

(3)消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

注:

消息队列:对于每一个正在执行的Windows应用程序,系统为其建立一个“消息队列”,用来存放可能创建的各种窗口的消息。

消息循环:应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数。

46. 信号量

信号量是进程间同步、互斥的一种机制。信号量允许多个进程访问共享资源,但对访问共享资源的进程的数目的上限有要求。

注:

(1)在信号量上定义了三个操作:初始化、P操作、V操作

(2)P、V操作为原语操作

(3)信号量可分为二元信号量,用于解决互斥问题;多值信号量,用于解决同步问题

47. 信号

一个信号就是一个小消息,信号用于通知接受进程发生了某种类型的事件。信号是在软件层次上对中断机制的一种模拟。

注:

(1)发送信号

(2)接受信号

(3)处理信号(阻塞信号、执行默认行为、执行信号处理程序)

48. 共享内存

共享内存,指两个或多个进程共享一个给定的存储区

特点:

(1)共享内存是最快的一种IPC

对于像管道和消息队列等进程间通信方式,需要在内核和用户空间进行四次的数据拷贝,而共享内存则只需要拷贝两次:一次从输入文件到共享内存区,另一个送共享内存到输出文件

(2)需要同步机制,以协调对共享内存的访问

注:

(1)

(2)进程之间通过映射同一个普通文件实现共享内存,共享内存中的内容往往是在解除映射时才写回文件

49. 套接字

与其他通信机制不同的是,它可用于不同主机的进程间的通信。

50. RPC

用于像调用本地过程一样调用远程过程

51. 僵尸进程、孤儿进程、守护进程

(1)僵尸进程:一个终止了但还未被回收的进程称为僵死进程。

注:shell或者服务器,总是应该回收它们的僵死子进程。即使僵死子进程没有运行,它们仍然消耗系统的内存资源,进程号也会被一直占用。

(2)孤儿进程:父进程执行完成或被终止后仍继续运行的一类进程。这些孤儿进程将被init进程所收养,并由init进程对它们完成状态收集工作。

(3)守护进程:守护进程是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。

52. 用户态和内核态

内核态:CPU可以访问内存中所有的数据,包括外设,例如硬盘、网卡,CPU也可以将自已从一个程序切换到另一个程序。

用户态:只能受限的访问内存,且不允许访问外设,占用CPU的时间可以被抢占。

https://www.cnblogs.com/zemliu/p/3695503.html

53. 消息

消息,就是windows发出的一个通知,告诉应用程序某个事件发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使windows发送一个消息给应用程序。

注:消息本身是作为一个记录(结构体)传递给应用程序的。

54. Windows的消息系统3个组成部分

(1)消息队列:对于每一个正在执行的Windows应用程序,系统为其建立一个“消息队列”,用来存放可能创建的各种窗口的消息。

(2)消息循环:应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数。

(3)窗口过程:每个窗口都有一个窗口过程,即一个回调函数,来接收、处理传递给窗口的消息。处理了一个消息后,它通常要返回一个值给windows。

55.一个消息从产生到被一个窗口响应的过程

(1)系统中发生了某个事件。

(2)Windows把这个事件翻译为消息,然后把它放在消息队列中。

(3)应用程序从消息队列中接收到这个消息。

(4)应用程序把消息传递给一个适当的窗口的窗口过程。

(5)窗口过程响应这个消息并进行处理。

56.SendMessage和PostMessage

(1)PostMessage函数只是向线程消息队列中添加消息,如果添加成功,则返回true,否则返回false,消息是否被处理,或处理的结果,就不知道了。

(2)SendMessage则有些不同,当线程向自己发送消息时,它并不是把消息加到队列里,而是直接翻译消息和调用消息处理,知道消息处理完成后才返回。所以,如果我们希望发送的消息立即被执行,就应该调用SendMessage。

(3)线程向自己发送消息时,SendMessage发送的消息不会被加入到消息队列中,因此,不能通过PeekMessage或GetMessage获取SendMessage发送的消息。

(4)有些消息用PostMessage不会成功。所以不是所有的消息都能够用PostMessage。

57.为什么要用协程(进程和线程的痛点)

多线程程序设计到:

(1)锁机制

(2)设计到线程阻塞状态到可运行状态之间的切换

(3)设计到线程上下文的切换

以上涉及到的任何一点,开销都非常大的。

58. 什么是协程

协程,是一种比线程更加轻量级的存在。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。更重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制。

相关推荐