计算机:操作系统

📅 2026/7/30 3:52:43
计算机:操作系统
进程和线程的区别进程是资源分配和调度的基本单位。操作系统为它分配了独立的内存空间。线程是cpu 调度 和 执行的最小单位是进程内的执行单元。一个进程至少有一个线程一个进程可以运行多个线程这些线程共享同一块内存。资源开销:进程由于每个进程都有独立的内存空间创建和销毁进程的开销较大。进程间切换需要保存和恢复整个进程的状态因此上下文切换的开销较高。线程线程共享相同的内存空间创建和销毁线程的开销较小。线程间切换只需要保存和恢复少量的线程上下文因此上下文切换的开销较小。进程开销大有独立地址空间、页表、资源创建销毁都要重新分配 / 回收。线程开销小共享进程资源只需要独立栈和上下文轻量得多。通信与同步:进程由于进程间相互隔离进程之间的通信需要使用一些特殊机制如管道半双工、消息队列、共享内存等。线程由于线程共享相同的内存空间它们之间可以直接访问共享数据线程间通信更加方便。安全性:进程由于进程间相互隔离一个进程的崩溃不会直接影响其他进程的稳定性。线程由于线程共享相同的内存空间一个线程的错误可能会影响整个进程的稳定性。并行和并发有什么区别并行是指在同一时刻执行多个任务这些任务可以同时进行. 例如在多核 CPU 上每个子任务都在不同的处理单元如多个 CPU 核心上执行,从而加速整体任务的完成。并发是指在相同的时间段内(宏观上同时)执行多个任务但是微观上是交替执行的。例如单核 CPU 上 多个任务通过时间片轮转或事件驱动的方式轮流占用处理器从而实现在一个时间段内完成多个任务。它关注的是任务的逻辑上同时执行。并发提出的需求1、提高资源利用率当任务因为I/O操作阻塞是CPU可以切换到其他任务执行充分利用处理器资源2、提高用户体验并行提出的需求1、计算速度更快例如 图像处理 GPU解释一下用户态和内核态用户态和内核态的区别用户态和内核态是操作系统为了 保护系统资源和实现权限控制 而设计的两种不同的CPU 运行级别。用户态非特权模式程序只能访问受限资源无法直接操作硬件或内核数据。所有普通应用程序都在此态运行。内核态特权模式程序可执行任何指令直接访问硬件和内核核心。操作系统内核、驱动程序等在此态运行。在什么场景下会发生内核态和用户态的切换系统调用当用户程序需要请求操作系统提供的服务时会通过系统调用进入内核态。异常当程序执行过程中出现错误或异常情况时CPU 会自动切换到内核态以便操作系统能够处理这些异常。中断外部设备如键盘、鼠标、磁盘等产生的中断信号会使 CPU 从用户态切换到内核态。操作系统会处理这些中断执行相应的中断处理程序然后再将 CPU 切换回用户态。中断信号-用户态到内核态—中断处理中断是 CPU 执行过程中被紧急事件打断转去处理中断服务程序处理完再恢复执行的机制。进程调度算法你了解多少调度算法分为两类非抢占式调度算法一旦进程 / 线程开始运行必须等它主动让出 CPU别人才能上、抢占式调度算法由操作系统决定非抢占式先来先服务按照请求的顺序进行调度。这种调度方式简单但是能导致较长作业阻塞较短作业。适合CPU繁忙型作业的系统不适用I/O繁忙型作业系统短作业等待时间可能很长不利于短作业最短作业优先优先选择估计运行时间最短的进程该进程完后从就绪队列中来运行。但是如果一直有短作业到来那么长作业永远得不到调度造成长作业 “饥饿” 现象。长作业不利抢占式最短剩余时间优先** 基于最短作业优先改进按剩余运行时间的顺序进行调度。当一个新的作业到达时其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少则挂起当前进程运行新的进程。否则新的进程等待。最短优先改进依旧长作业不利时间片轮转为每个进程分配一个时间片进程轮流执行时间片用完后切换到下一个进程。时间片长度很关键时间片太短导致过多的进程上下文切换降低CPU效率时间片太长可能引起对短作业进程的响应时间变长。优先级调度为每个进程分配一个优先级按优先级进行调度。可以分别设定抢占式和非抢占式为了防止低优先级的进程永远等不到调度可以随着时间的推移增加等待进程的优先级。多级反馈队列调度时间片轮转调度算法和优先级调度算法的结合。将进程分为不同的优先级队列每个队列有自己的调度算法。「多级」表示有多个队列每个队列优先级从高到低同时优先级越高时间片越短。「反馈」表示如果有新的进程加入优先级高的队列时立刻停止当前正在运行的进程转而去运行优先级高的队列兼顾了长短作业同时有较好的响应时间用户能够快速得到反馈高响应比调度算法高响应比优先调度算法主要是权衡了短作业和长作业。每次进行进程调度时先计算「响应比优先级」然后把「响应比优先级」最高的进程投入运行。优先权 等待时间 要求服务时间 要求服务时间 \text{优先权} \frac{\text{等待时间} \text{要求服务时间}}{\text{要求服务时间}}优先权要求服务时间等待时间要求服务时间​从上面的公式可以发现如果两个进程的「等待时间」相同时「要求的服务时间」越短「响应比」就越高这样短作业的进程容易被选中运行如果两个进程「要求的服务时间」相同时「等待时间」越长「响应比」就越高这就兼顾到了长作业进程因为进程的响应比可以随时间等倍的增加而提高当其等待时间足够长时其响应比便可以升到很高从而获得运行的机会进程间有哪些通信方式每个进程的用户地址空间都是独立的一般而言是不能互相访问的但内核空间是每个进程都共享的所以进程之间要通信必须通过内核。管道分为匿名管道和命名管道匿名管道是一种半双工的通信方式数据只能单向流动而且只能在具有父子关系的进程间使用(特殊文件只在内存中不存在文件系统中父子共享文件描述符所以可以使用)。命名管道也是半双工的通信方式但是它允许在不相关的进程间通信会创建一个管道类型的文件。消息队列允许进程发送和接收消息而消息队列是保存在内核的消息链表可以设定优先级。缺点存在于内核之中消息大小有限制通信过程中存在用户态与内核态之间切换并且数据拷贝开销用户-内核内核-用户。共享内存共享内存的机制就是拿出一块虚拟地址空间来映射到相同的物理内存中。这样这个进程写入的东西另外一个进程马上就能看到了都不需要拷贝来拷贝去传来传去大大提高了进程间通信的速度。共享内存是最快的进程通信方式。解决用户态到内核态的开销只是建立共享内存需要内核态建立用了共享内存通信方式带来新的问题那就是如果多个进程同时修改同一个共享内存很有可能就冲突了信号量是一个整型计数器可以用来控制多个进程对共享资源的访问主要用于实现进程间的互斥与同步。防止一个进程正在访问共享资源时其他进程也访问该资源。信号是一种异步通信机制用于发送通知到进程告知其发生了某种事件例如CtrlC 组合键、除0错误。进程可以忽略、捕获该信号或执行默认操作。Socket 套接字最初用于网络通信但也可用于同一台主机上的进程间通信如Unix Domain Socket。次要互斥锁一种信号量用于保护共享数据结构防止多个进程同时访问。条件变量与互斥锁配合使用用于进程间的同步等待某些条件成立。解释一下进程同步和互斥以及如何实现进程同步和互斥进程同步解决的是“协作”问题。它是指多个并发进程之间为了完成共同的任务需要协调它们的执行顺序。例如进程A负责生产数据进程B负责打印数据那么B必须在A之后执行。同步就是用来保证这种“前驱后继”关系的机制。进程互斥解决的是“竞争”问题。当多个进程需要访问同一个共享资源比如打印机、共享内存中的变量时互斥确保同一时刻只允许一个进程进入临界区访问共享资源的代码段访问该资源。这就好比电话亭一个人进去使用了其他人就必须在外面排队等待保证了数据的一致性和正确性。解决进程同步和互斥的问题有很多种方法互斥锁Mutex:互斥锁是一种同步机制用于实现互斥。每个共享资源都关联一个互斥锁进程在访问该资源前需要先获取互斥锁使用完后释放锁。只有获得锁的进程才能访问共享资源。信号量:信号量是一个整型计数器它表示系统中某种资源的数量。它会配合两个原子操作PV操作来使用P 操作申请资源。它会检查信号量的值如果值大于0资源可用则将其减1并继续执行如果值等于0资源不足则进程被阻塞进入等待队列。V 操作释放资源。它将信号量的值加1如果此时有进程在等待队列中则唤醒其中一个。通过将信号量初始化为1我们可以用它来实现互斥即互斥锁的功能。通过将信号量初始化为0我们可以用它来实现同步例如确保进程B在P操作上等待直到进程A执行V操作后才被唤醒。条件变量与互斥锁配合允许进程在某个条件不满足时阻塞等待并在条件满足时被唤醒。一些概念临界区访问共享资源的代码段。进入这个区域前需要先获取锁退出临界区后释放该锁。这确保同一时间只有一个进程可以进入临界区。条件变量条件变量用于在进程之间传递信息以便它们在特定条件下等待或唤醒。通常与互斥锁一起使用以确保等待和唤醒的操作在正确的时机执行。互斥解决竞争问题同步解决协作问题而互斥是同步的特例互斥锁属于同步机制。什么是死锁如何预防死锁死锁是系统中多个进程因争夺资源而造成的一种僵局。当每个进程都持有一定的资源并等待其他进程释放它们所需的资源时如果这些资源都被其他进程占有且不释放就导致了死锁。死锁只有同时满足以下四个条件才会发生互斥条件同一时刻一个进程占用了某个资源时其他进程无法同时占用该资源。请求保持条件一个线程因为请求资源而阻塞的时候不会释放自己的资源。不可剥夺条件资源不能被强制性地从一个进程中剥夺只能由持有者自愿释放。循环等待条件多个进程之间形成一个循环等待资源的链每个进程都在等待下一个进程释放所占有的资源。避免死锁通过破坏死锁的四个必要条件之一来预防死锁。破坏互斥条件将资源改为共享方式如只读文件但有些资源天生互斥如打印机难以实现。破坏请求保持条件采用一次性分配即进程在运行前一次性申请所有需要的资源若资源不足则等待但会导致资源利用率低和饥饿。破坏不可剥夺条件允许抢占例如进程申请新资源失败时系统强制释放其已占有的资源如CPU寄存器但实现复杂且可能造成数据不一致。破坏循环等待资源有序分配法给所有资源编号进程必须按编号递增顺序申请资源这样就不会形成循环链。检测死锁通过检测系统中的资源分配情况来判断是否存在死锁。例如可以使用资源分配图或银行家算法进行检测。解除死锁例如可以通过抢占资源、终止某些进程等方式来解除死锁。检测死锁资源分配图用有向图表示进程和资源的关系如果图中存在环路且环路中的资源均只被一个进程占有则可能发生死锁。死锁检测算法类似于银行家算法通过查找可以完成的进程来简化图若最终所有节点无法被消除则存在死锁。检测时机可定时触发或当CPU利用率骤降时触发。银行家算法1、每个进程事先声明最大资源需求。2、系统在分配资源时计算如果满足此次请求是否还存在一个安全序列即所有进程都能按某个顺序完成。3、只有处于安全状态时才分配资源否则让进程等待。死锁解除终止进程一次性终止所有死锁进程或逐个终止直到死锁解除。选择终止的进程通常考虑优先级、运行时间、已使用资源等因素。资源抢占从某些进程中强制剥夺资源给其他进程但需要回滚被剥夺的进程到安全状态以防止数据不一致。系统重启简单粗暴但代价高。介绍一下几种典型的锁互斥锁定义 互斥锁是最基本的锁确保同一时刻只有一个线程能访问被保护的临界区。工作原理 每个共享资源都关联一个互斥锁线程在进入临界区前必须获取锁若锁已被其他线程持有则当前线程会被阻塞释放CPU进入睡眠状态由操作系统在锁释放时唤醒它。这个过程涉及两次上下文切换开销较大。适应场景 适合保护执行时间较长的临界区代码被锁住的代码否则上下文切换比执行时间更长得不偿失。自旋锁定义自旋锁采用忙等待机制线程在获取锁失败时会持续循环检查锁状态而不释放CPU。工作原理 当锁被其他线程持有时线程会忙等待即不断循环检查锁是否可用不会主动释放CPU。它在用户态完成锁的获取避免了上下文切换但会一直占用CPU。适应场景自旋锁适合保护那些执行时间非常短的临界区代码被锁住的代码避免cpu被无效占有比如只修改一个变量。在多核系统中如果锁持有时间很短自旋锁效率更高。其他的锁都是基于这两个锁的读写锁定义读写锁将共享资源的访问分为读和写两种模式。读锁是共享的允许多个线程同时读写锁是排他的只允许一个线程写。工作原理当没有写锁时多个读锁可以同时获得写锁必须等待所有读锁和写锁释放后才能获得。读写锁可以用互斥锁和条件变量实现也可用自旋锁实现。适应场景读操作远多于写操作的场景能显著提升并发性能。悲观锁定义悲观锁认为多线程同时修改共享资源的概率比较高所以访问共享资源时候要上锁确保数据安全。典型实现互斥锁、自旋锁、读写锁都是悲观锁乐观锁定义乐观锁认为多线程同时修改共享资源的概率比较低因此不加锁直接操作但在更新时会检查数据是否被其他线程修改过若冲突则重试或放弃。典型实现 Git、在线文档编辑 冲突概率极低的场景可避免加锁开销但冲突重试成本较高。讲一讲你理解的虚拟内存虚拟内存是一种内存管理技术它为每个进程提供一个独立的、连续的虚拟地址空间它不是真实存在的而是通过映射与实际物理地址空间对应这样就可以使每个进程看起来都有自己独立的连续地址空间并允许程序访问比物理内存 更大的地址空间每个程序都可以认为它拥有足够的内存来运行。需要虚拟内存的原因内存扩展程序可以使用的内存空间可以超过物理内存的容量。当物理内存不足时操作系统会把暂时不用的数据页换出到磁盘需要时再换入从而让程序“感觉”拥有巨大的内存。内存隔离与保护每个进程运行在独立的虚拟地址空间中一个进程无法直接访问另一个进程的内存这防止了恶意或错误的程序破坏其他进程的数据。同时页表项中可以设置读写权限实现代码段只读、数据段可写等保护机制。简化内存管理对程序员而言他们只需要关心连续的虚拟地址而不用操心物理内存的碎片化、分配和回收等复杂问题。操作系统可以更灵活地管理物理内存例如将不连续的物理页组合成连续的虚拟空间。内存映射文件虚拟内存还可以用于将文件映射到内存中这使得文件的读取和写入可以像访问内存一样高效。通过页表内存映射文件 把磁盘上的文件直接映射到进程的虚拟地址空间。以后读写文件不用 read/write直接用指针访问内存就行。物理内存管理虚拟内存允许操作系统动态地将数据和程序的部分加载到物理内存中以满足当前正在运行的进程的需求。当物理内存不足时操作系统可以将不常用的数据或程序暂时移到硬盘上从而释放内存以便其他进程使用。包含在内存拓展之中线程同步的方式线程同步机制是指在多线程编程中为了保证线程之间的互不干扰协调它们之间的执行顺序。常见的线程同步机制有以下几种互斥锁每个共享资源都关联一个互斥锁线程在访问该资源前需要先获取互斥锁使用完后释放锁。只有获得锁的线程才能访问共享资源。可以回答适合场景条件变量条件变量用于线程间通信允许一个线程等待某个条件满足而其他线程可以发出信号通知等待线程。通常与互斥锁一起使用。读写锁读写锁将共享资源的访问分为读和写两种模式。读锁是共享的允许多个线程同时读写锁是排他的只允许一个线程写。信号量是一个整型计数器支持两个原子操作P、V操作用于控制多个线程对共享资源进行访问的工具。常见的内存页面置换算法页面置换算法是 当出现缺页异常需调入新页面而内存已满时选择被置换的物理页面。也就是说选择一个物理页面换出到磁盘然后把需要访问的页面换入到物理页。算法的目标是尽可能减少页面的换入换出的次数。页面的换入和换出由于磁盘速度很慢I/O 会阻塞进程效率降低常见页面置换算法有最佳置换算法(OPT)、先进先出FIFO、最近最久未使用算法LRU、时钟算法Clock等。最佳置换算法置换在「未来」最长时间不访问的页面。但是实际系统中无法实现因为程序访问页面时是动态的我们是无法预知每个页面在「下一次」访问前的等待时间。先进先出FIFO置换算法也就是最先进入内存的页面最先被置换出去内存驻留时间最长的页面。最近最久未使用置换算法LRU发生缺页时选择最长时间未被使用的页面进行置换。性能比FIFO高时钟算法CLOCKClock 算法的核心思想是通过使用一个指针 (称为时钟指针) 在环形链表上遍历检查页面是否被访问过当需要进行页面置换时Clock 算法从时钟指针的位置开始遍历环形链表。如果当前页面的访问位为 0表示该页面最久未被访问可以选择进行置换。将访问位设置为 1继续遍历下一个页面。如果当前页面的访问位为 1表示该页面最近被访问过它仍然处于活跃状态。将访问位设置为 0并继续遍历下一个页面如果遍历过程中找到一个访问位为 0 的页面那么选择该页面进行置换。最不常用LFU当发生缺页时考虑页面的访问频率淘汰访问次数最少的页面。熟悉哪些Linux命令文件操作ls列出当前目录内容。cd进入指定目录。pwd打印当前路径。cp复制文件或目录到另一个文件、目录。cp 源文件 目标文件目标文件不存在复制源文件并改为目标文件名目标文件存在且是目录复制到目标文件夹下目标文件存在且不是目录会覆盖该目标文件名不变保留源mv移动或重命名文件。mv 源文件名 目标文件目标文件不存在直接改名为目标文件目标文件存在且是目录移动到目标文件夹下目标文件存在且不是目录会覆盖该目标文件名不变删除源。rm删除文件或目录。touch创建空文件或更新文件时间戳。不能创建目录file查看文件的描述信息where非系统标配等价于which -a 列出所有路径which$PATH中可执行路径 查找命令的执行路径whereis查找执行路径以及相关二进制文件文件内容查看cat查看文件内容。head查看文件的前几行。head --lines数量 文件名tail查看文件的后几行常用于查看日志文件。tail – lines数量 文件名less翻页方向 上下均可more翻页方向 向下grep查找文件、内容符合条件的部分文件编辑vi或vim强大的文本编辑器nano文本编辑器易上手有快捷键提示权限管理chmod更改文件或目录的访问权限。chown更改文件或目录的所有者和 / 或所属组。磁盘管理df查看磁盘空间使用情况。网络管理ifconfig或ip addr查看和配置网络接口。ping测试网络连接。netstat查看网络状态和统计信息。ssh安全远程登录。进程管理ps查看当前运行的进程。静态 ps aux 可以查看所有进程以及详细信息top实时查看当前运行的进程所有且详细kill杀掉某进程。软件包管理根据 Linux 发行版不同命令可能有所不同apt-getDebian/Ubuntu安装、更新和删除软件。echo打印Linux中如何查看一个进程如何杀死一个进程如何查看某个端口有没有被占用1. 查看进程用ps命令查看当前运行的进程比如ps aux可以列出所有进程及其详细信息但它显示的是静态的列表。top 可以实时查看当前运行的进程的详细信息2. 杀死进程首先用ps或top命令找到进程的 PID进程 ID。然后用kill命令加上进程 ID 来结束进程例如kill -9 PID。-9是强制杀死进程的信号。默认的kill PID等价于kill -15让进程自己清理资源后退出。3. 查看端口占用使用lsof -i:端口号可以查看占用特定端口的进程没有输出表示端口空闲。或者用netstat -tulnp | grep 端口号这会显示监听在该端口的服务及其进程 ID。注意|是匿名管道将前一个进程的信息给后一个进程信息需要两者有父子关系半双工通信。说一下 select、poll、epollI/O 多路复用允许单个线程同时监控多个文件描述符FD。当某个 文件描述符 就绪可读、可写或异常时系统调用会返回通知应用程序进行后续处理。解决的痛点对比阻塞 I/O避免了为每个连接创建一个线程的巨大资源开销内存、上下文切换。对比非阻塞轮询避免了用户态不断发起系统调用去检查状态极大降低了 CPU 消耗。select、poll、epoll等系统调用是用来实现I/O 多路复用selectselect是一个最早的 I/O 多路复用实现方案它可以监视多个文件描述符的可读、可写和错误状态。查询时需要将所有文件描述符FD集合从用户态拷贝到内核态由内核进行线性轮询。缺点数量限制使用固定大小的位数组文件描述符通常最大为1024效率低下每次调用都要全量拷贝 文件描述符 集合(用户态到内核态内核态到用户态)O(n) 遍历开销随 文件描述符 数量增加而线性增长。重复设置每次调用返回后原有的 文件描述符 集合会被修改就绪的为1下次调用需重新初始化需要监控的设置为1。pollpoll是select的一种改进避免了select中文件描述符数量有限的问题。改用了基于链表的pollfd结构缺点依然存在用户态到内核态的全量拷贝和内核态的线性轮询对于大量的文件描述符性能依然不够高效。epollepoll是 Linux 特有的 I/O 多路复用机制相较于select和pollepoll使用事件通知的方式只有在文件描述符就绪时内核才会通知应用程序而且不需要应用程序轮询。无重复拷贝文件描述符 注册后常驻内核只有在发生变化时才操作减少了数据拷贝开销。这个操作是主动将这个就绪的 fd 添加到内核维护的“就绪链表”中。总结select是最早的 I/O 多路复用技术但受到文件描述符数量和效率方面的限制。poll克服了文件描述符数量的限制但仍然存在一定的效率问题。epoll是一种高效的 I/O 多路复用技术尤其适用于高并发场景但它仅在 Linux 平台上可用。一般来说epoll的效率要比select和poll高但是对于活动连接较多的时候由于回调函数触发的很频繁其效率不一定比select和poll高。所以epoll在连接数量很多但活动连接较小的情况性能体现的比较明显。文件描述符File Descriptor简称FD是操作系统尤其是类Unix系统如Linux、macOS中用于表示打开的文件、网络连接、管道等I/O资源的抽象概念。它是一个非负整数类似于一个“索引”进程通过它来访问和管理这些资源。本质文件描述符是一个小的非负整数由内核在进程打开文件时分配。进程后续的读写操作都通过这个整数进行内核根据它找到对应的文件对象。