操作系统OS
1.引论
什么是操作系统?
- 操作系统(Operating System, OS)是计算机系统中管理硬件和软件资源的中间层系统,屏蔽了硬件层的复杂性,为用户提供了便捷的交互方式,如Windows、Linux、MacOS
- 举例:运行在你电脑上的所有应用程序都通过操作系统来调用系统内存以及磁盘等硬件
操作系统本质上是一个运行在计算机上的软件程序。
操作系统就像是硬件使用的负责人,统筹着各种相关事项。

操作系统主要有哪些功能?
- 进程管理:操作系统负责创建、终止进程,并为进程分配资源(如内存)。
- 内存管理:分配和回收内存,确保每个进程有足够的空间运行。
- 文件管理:提供文件创建、删除、读写功能,并管理文件存储结构(如目录)。
- 硬件管理:通过设备驱动程序控制硬件设备,如键盘、鼠标、打印机等。
2.操作系统结构
⭐️⭐️什么是内核?什么是用户态和内核态?
- 内核是操作系统的核心,负责管理计算机硬件(如CPU、内存、硬盘等)和系统资源(如进程管理、文件管理、设备驱动等)。
- 它拥有完全的权限来访问硬件和系统资源。
- 用户态是应用程序运行的状态,权限较低,只能访问自己的内存空间和受限资源,无法直接操作硬件;
- 内核态是操作系统运行的状态,权限最高,可以访问系统的所有资源和硬件设备。
为什么要有用户态和内核态?只有一个内核态不行吗
安全性和稳定性:
- 内核态拥有对硬件和所有资源的完全控制权限,如果应用程序也能直接访问这些资源,就可能导致系统崩溃或被恶意攻击。
- 通过限制用户程序的权限,避免了程序直接操作硬件,防止了对系统的破坏。
用户态和内核态如何切换的?
- 当用户态的程序执行需要内核权限的操作时,它会通过系统调用进入内核态。此时,操作系统会保存当前的用户态信息,并切换到内核态。
- 执行完需要内核权限的操作后,操作系统会返回用户态,恢复执行程序的普通代码。
3.进程和线程
并行和并发有什么区别?
- 并发是指多个任务在同一时间段内交替执行,强调任务的调度和资源共享。
- 并行是指多个任务在同一时刻真正同时执行,通常依赖多个处理器或核心来加速任务。
⭐️⭐️进程线程协程的区别?
- 进程(Process)是系统进行资源分配的基本单位,拥有独立的内存空间和系统资源。
创建、切换和销毁需要操作系统介入,成本较高。- 线程(Thread)是进程内的执行单元,多个线程共享进程的内存和资源。
由操作系统调度,上下文切换成本低于进程。- 协程(Coroutine)是更轻量的执行单元,运行在单个线程中,切换开销小。
由程序控制切换,无需操作系统调度。
⭐️⭐️⭐️进程间的通信方式
- 进程间通信是指不同进程之间进行数据交换的方式。由于每个进程都有独立的地址空间,所以进程之间无法直接访问彼此的数据。因此需要一些机制来实现它们之间的通信
进程间的通信(IPC, Inter-Process Communication)方式有很多,常见的有以下几种:
管道(Pipe):
- 管道是最基本的进程间通信方式,它允许两个进程通过字节流交换数据的机制。管道有两种:匿名管道和有名管道。
- 匿名管道:只能用于具有亲缘关系的进程(如父子进程)进行通信。
- 有名管道:允许无亲缘关系的进程通信。有名管道严格遵循先入先出(FIFO)。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程的通信
消息队列(Message Queue):
- 进程通过消息队列发送和接收消息。消息队列是一种先进先出(FIFO)方式的通信机制,消息可以被多个进程发送和接收。
- 特点:它支持消息的存储和延迟发送。进程可以在消息队列中存储消息,直到另一个进程准备好接收它。
共享内存(Shared Memory):
- 允许多个进程将某一块内存区域映射到自己的地址空间中,通过共享这块内存进行通信
- 特点:速度快,适合大数据量的传输。但需要额外的同步机制来避免数据冲突(比如使用互斥锁)。
信号(Signal):
- 信号是通知接收进程某个事件已发生。进程通过信号来进行通知,接收信号的进程可以根据信号做出响应。
- 优点:简单、快速,适用于进程间的简单通知。
- 缺点:信号只能传递简单的通知,无法传输复杂数据。
信号量(Semaphore):
- 信号量用于控制多个进程对共享资源的访问,通过计数器来决定当前能否访问共享资源
- 优点:可用于解决进程同步和互斥的问题。
- 缺点:使用不当可能导致死锁等问题。
套接字(Socket):
- 套接字允许在网络中的不同计算机或同一计算机中的不同进程间进行通信。通过套接字,进程可以通过网络协议(如TCP/IP)发送和接收数据。
- 特点:适用于不同机器之间的通信,也可以用于同一台机器上的进程通信。但实现相对复杂。
线程间的通信方式(同步方式)
- 线程间的同步是为了防止多个线程在同时访问共享资源时发生冲突或者数据不一致的情况。因为线程是并发执行的,多个线程共享内存区域时,如果不加以控制,就会导致数据不一致或者程序出错。
互斥锁(Mutex):
- 通过锁来保证同一时刻只有一个线程可以访问共享资源,其他线程必须等待锁释放后才能访问。
- 典型实现:
synchronized(Java中的关键字),ReentrantLock(Java中的类)。- 适用场景:需要保证线程安全的共享资源访问。
信号量(Semaphore):
- 用信号量来控制并发访问的线程数量。信号量的计数器表示资源的可用数量,当计数器为零时,线程必须等待。
- 优点:控制访问资源的线程数目,避免资源过载。
- 缺点:可能出现死锁,尤其在没有妥善释放资源时。
条件变量(Condition Variable):
- 允许线程在某个条件未满足时进入等待状态,直到其他线程通知条件已满足。
- 典型实现:
Object.wait()和Object.notify(),Condition.await()和Condition.signal()。- 适用场景:线程之间的协调,如生产者-消费者模型。
什么是进程上下文切换?什么是线程上下文切换?
- 进****程上下文切换是操作系统在不同进程之间切换时,需要保存当前进程的状态,然后加载另一个进程的状态。它会涉及到保存和恢复进程的内存、寄存器等信息,开销比较大
- 线程上下文切换是在同一个进程内,操作系统在不同线程之间切换时,保存和恢复线程的状态。因为线程共享进程的内存,切换的开销比进程切换小。
进程切换时要恢复哪些东西?
进程切换时,操作系统需要恢复以下几个关键部分:
- 程序计数器(PC):指示下一条要执行的指令的地址。
- 寄存器的值:包括通用寄存器和控制寄存器等,确保恢复进程的计算状态。
- 内存映射:恢复进程的地址空间和页表等内存管理信息,确保进程能找到自己的数据。
- 堆栈指针:恢复进程的栈空间,确保程序的调用和局部变量能继续正常工作。
- 进程状态信息:通过进程控制块(PCB)保存进程的各种信息,包括进程ID、优先级等
进程的状态及其状态的转化?
进程在生命周期中通常有五种状态:新建、就绪、运行、阻塞和结束。
- 新建状态:进程正在创建中,还没有开始执行。
- 就绪状态:进程已经准备好,等待操作系统将其调度到CPU执行。
- 运行状态:进程正在CPU上执行,操作系统正在处理它的指令。
- 阻塞状态:进程因为等待某些资源(如I/O操作)而暂停执行,直到事件完成或资源可用
- 结束状态:进程完成任务或被终止,操作系统回收进程的资源。
从新建到就绪,从就绪到运行,从运行到阻塞,从阻塞到就绪,从运行到结束。进程状态的转化依赖于操作系统调度、I/O事件和进程的执行状态。
⭐️什么是僵尸进程和孤儿进程?
僵尸进程:
- 是已经结束执行的进程,但它的父进程还没有调用 wait() 来回收它的退出状态。
- 僵尸进程虽然不再占用CPU资源,但仍然占用进程表中的一个条目,直到父进程处理它
- 特点:占用进程表条目,但不占用系统资源。
孤儿进程:
- 是父进程在它还没有结束时就提前终止了,导致这些进程没有父进程。
- 孤儿进程会被操作系统的 init 进程收养,init 进程会负责它们的资源回收。
- 特点:父进程提前终止,子进程没有父进程,最终由 init 收养。
⭐️⭐️⭐️进程有哪些调度算法?
常见的进程调度算法有以下几种:
先来先服务(FCFS, First-Come, First-Served):
- 按照进程到达的顺序调度。
- 缺点:可能导致“长进程”阻塞“短进程”,导致较大的平均等待时间。
最短作业优先(SJF, Shortest Job First):
- 优先调度执行时间最短的进程。
- 缺点:需要知道进程的执行时间,而且可能导致“饥饿”问题(长作业永远得不到执行)。
优先级调度(Priority Scheduling):
- 根据进程的优先级进行调度,优先级高的先执行。
- 缺点:低优先级的进程可能长期得不到执行,导致“饥饿”。
轮转调度(RR, Round-Robin):
- 每个进程分配固定时间片,时间片用完后切换到下一个进程。
- 优点:公平,不会有进程长时间被饿死。
- 缺点:时间片长度的选择影响效率,时间片太长像FCFS,太短会增加上下文切换开销。
多级反馈队列调度(Multilevel Feedback Queue):
- 结合了优先级调度和时间片轮转调度,进程会根据执行时间和行为在不同队列间移动。
- 优点:适应性强,能平衡响应时间和系统效率。
什么是死锁?死锁产生的四个必要条件?
死锁就是多个线程互相等待对方的资源,最后谁都动不了,就“锁死”了。
它发生的前提有四个条件,必须同时满足四个必要条件才会死锁:
- 互斥条件:至少一个资源是非共享的。
- 占有并等待:进程持有资源并等待其他资源。
- 不剥夺条件:资源不能被强制夺走,只有在进程自愿释放时才能释放资源。
- 循环等待:存在一个进程等待链,形成闭环。
⭐️⭐️避免死锁的方法?
所以要避免死锁问题,就是要破坏其中一个条件即可,所以可以:
- 保持统一的加锁顺序(最常用):所有线程加锁时,按照统一顺序获取多个锁,比如永远先锁 A,再锁 B,这样就不会形成循环等待。
- 尽量少用嵌套锁:嵌套加锁越多,死锁风险越高。能不嵌套就不嵌套。
- 给线程设置超时时间和中断机制:防止线程永远挂起。
4.内存管理
⭐️⭐️什么是虚拟内存?物理内存和虚拟内存有什么区别?页一般来说有多大?
- 虚拟内存(Virtual Memory)是一种内存管理技术,它允许操作系统使用硬盘空间来模拟更多的内存资源,从而让计算机的程序看起来拥有更多的内存空间,超出了物理内存的限制。虚拟内存使得每个程序都认为自己有独立的内存区域,而操作系统负责将这些虚拟内存地址映射到物理内存或者硬盘上的交换空间。
- 物理内存是计算机中的实际内存(RAM),它的大小和容量是有限的,直接影响计算机的性能。
- 虚拟内存是通过操作系统和硬件结合使用的技术,扩展了可用内存的容量,它使得应用程序可以使用更多的内存,而不受限于物理内存的大小。
- 默认页大小通常为4KB。

5.I/O
⭐️⭐️⭐️讲一讲I/O多路复用select、poll、epoll?
- I/O多路复用是一种在单个进程中同时处理多个I/O操作的方法,主要用于解决高并发的场景,避免每次都阻塞等待一个I/O操作完成。
- 常见的I/O多路复用技术包括
select、poll和 **epoll**。- epoll 相比于 poll 和 select ,能支持更大的并发连接数、性能更高
1. select
- 原理:
select是最早的 I/O 多路复用方式,允许一个进程监控多个文件描述符,并通知程序哪个文件描述符准备好进行I/O操作。- 优点:简单、跨平台。
- 缺点:
- 文件描述符上限:
select有文件描述符数量上限(1024),因此适用于小规模并发- 性能差:每次调用都要遍历所有文件描述符,即使部分文件描述符没有准备好,效率较低。
2. poll
- 原理:
poll与select类似,也通过监视多个文件描述符来检测哪些I/O操作可以执行,但没有select的文件描述符上限。- 优点:没有文件描述符上限,可以处理更多的连接。
- 缺点:
- 性能差:每次调用时仍需要遍历所有文件描述符列表,效率不高。
3. epoll
- 原理:
epoll是Linux特有的I/O多路复用技术,采用事件驱动机制,避免了select和poll的遍历性能瓶颈。- 优点:
- 高效:只有文件描述符就绪时才通知应用程序,避免了不必要的遍历。
- 无文件描述符上限:不再限制文件描述符的数量,适合大规模并发。
- 边缘触发与水平触发:支持两种触发模式,边缘触发(只在状态变化时通知)和水平触发(每次事件发生时都会通知)。
- 缺点:
- 仅支持Linux:
epoll是Linux专用的I/O多路复用方法,其他操作系统不支持。- 编程复杂度:需要处理事件通知机制,编程比
select和poll复杂。
当程序打开一个文件时,操作系统会为这个文件分配一个文件描述符。程序通过这个文件描述符来读取文件、写入文件等。文件描述符是一个整数值,操作系统内部使用它来标识文件的打开状态,并管理文件的读取和写入。
⭐️⭐️缓存淘汰策略?
- LRU (Least Recently Used): 最近最少使用策略。该策略会移除最近最少使用的数据,假设最近使用的数据在未来仍会被使用。
- LFU (Least Frequently Used): 最不经常使用策略。该策略会移除使用频率最低的数据,假设使用频率高的数据在未来仍会被使用。
- FIFO (First In First Out): 先进先出策略。该策略会移除最早进入缓存的数据,不考虑数据的使用频率或最近使用时间。
- MRU (Most Recently Used): 最近最多使用策略。与LRU相反,该策略会移除最近使用的数据,适用于某些特定场景。
- Random: 随机淘汰策略。随机选择缓存中的数据进行移除,简单但不一定高效。
⭐️操作系统中LRU算法如何实现
- LRU(Least Recently Used)算法是用来管理缓存的一种淘汰策略,确保最久没有使用的数据被淘汰。
实现步骤:
- 使用双向链表:
- 维护一个双向链表,链表的头部是最近使用的数据,尾部是最久没有使用的数据。
- 当数据被访问时,先在链表中查找该数据。
- 如果数据存在,就把它移到链表头部,表示它最近被访问。如果数据不在缓存中,且缓存未满,将数据添加到链表的头部。
- 当缓存满了,需要淘汰数据时,移除链表尾部的数据(最久没使用的)。
- 使用哈希表:
- 哈希表可以快速查找数据的位置。哈希表的键是数据的标识符,值是数据的引用。
- 每次访问数据时,先检查哈希表,找到数据并移动到链表头部。
6.Linux命令
6.0 常用命令
- cd xxx 进入某个目录、pwd 显示当前目录路径
- ll 或 ls 查看当前目录下内容
- mkdir 创建目录、rm 删除文件、cp 复制文件、mv 移动文件
- vim 或 vi 编辑文件
- find 查找文件、find 目录名 -name 文件名 根据文件名查找指定目录下的文件
- top 用来查看系统资源
- kill PID 终止进程
- ps -ef | grep java 查看 Java 进程、ps aux显示所有进程
- netstat 查看网络连接
- ping 测试网络连通性
- chmod 修改文件权限
- df 查看磁盘空间
- zip 压缩文件、unzip 解压文件等等这些。
6.1 文件操作的命令有哪些?
- ls:列出目录内容。ls -l显示详细信息,ls -a显示隐藏文件。
- cd:更改当前目录。cd ..回到上级目录,cd ~回到用户的主目录。
- pwd:显示当前工作目录的完整路径。
- cp:复制文件或目录。cp source_file target_file复制文件,cp -r source_directory target_directory复制目录
- mv:移动或重命名文件或目录。
- rm:删除文件或目录。rm -r递归删除目录及其内容。
- mkdir:创建新目录。
- cat:查看文件内容。cat file1 file2合并文件内容显示。
如何查看系统的日志文件?
在 Linux 中,可以通过 cat、more、less、tail、head 等命令查看系统日志文件。
也可以直接通过 vim 打开日志文件,然后按照关键字去搜查对应的日志信息。
⭐️怎么对比两个文件的差异
- 比较文件差异的话使用 diff 命令, diff 命令用于比较两个文件的内容差异,显示添加、删除和修改的部分
- 比较两个文件
diff file1.txt file2.txt- 忽略空格和制表符的变化,仅比较实际内容。简要比较
diff –brief filel.txt file2.txt
⭐️ linux里,如果我要统计一个日志文件的error数量用什么命令
- grep -i “error” your_log_file.log | wc -l
- -i选项表示忽略大小写
wc-l: wc 命令用于统计字数、行数等。(-1选项表示统计行数。- grep “Error” xx.log | grep “uid” 查找日志中带有 “Error”且带有 指定uid的内容
6.2 系统管理的命令有哪些?
- ps:显示当前运行的进程。ps aux显示所有进程。
- top:实时显示进程动态。
- kill:终止进程。kill -9 PID强制终止。
- df:查看磁盘空间使用情况。df -h以易读格式显示。
- du:显示目录或文件的磁盘使用情况。
- free:查看内存使用情况。
- chmod:更改文件或目录的权限。
- chown:更改文件或目录的所有者和所属组。
- find:在指定目录下查找文件。
- grep:在文件内容中查找匹配的字符串。
⭐️查看CPU使用情况
top
- 作用:可以动态地查看系统中正在运行的进程及其CPU、内存等资源消耗情况
- 使用场景:当线上服务器报警CPU占用率过高时,可以使用top命令查看具体哪些进程耗费CPU。
⭐️查看磁盘使用情况
df -h
- 作用:显示磁盘空间使用情况
- 使用场景:当线上服务器报警磁盘满的时候,需要查看磁盘占用情况
查看Linux进程或CPU使用?
- top 命令可以实时查看所有进程的 CPU 和内存使用情况。
- ps aux –sort=-%cpu | head -5可以查看 CPU 使用率最高的 5 个进程。


查看Linux内存使用?
- top命令
- 可以使用 watch 配合 free 命令实时监控内存使用情况。如 watch -n 1 free -m每秒刷新一次内存使用情况。
free命令可以显示Linux系统中空闲的、已用的物理内存及swap内存,及被内核使用的buffer。在Linux系统监控的工具中,free命令是最经常使用的命令之一。


查看系统负载?
- top 命令是实时查看系统性能的常用工具,系统负载信息通常显示在 top 命令输出的顶部。它还显示了系统运行的进程、内存使用情况等。

Load Average?
load average是一个反映系统负载的指标,表示在一段时间内系统正在处理的平均进程数量
通常,它包含三个数值,分别对应过去 1 分钟、5 分钟和 15 分钟的平均负载。
- 比如说上图中出现的 load average: 1.80, 1.74, 1.83 表示:
1.80:表示过去 1 分钟内,系统平均有 1.80 个进程在等待处理(包括 CPU 正在处理和等待被调度的进程)。
1.74:表示过去 5 分钟内的平均负载。
1.83:表示过去 15 分钟内的平均负载。- load average 的数值可以看作是系统的工作队列长度(等待处理的任务数量)。如果这个数值接近或等于 CPU 核心数,说明系统的负载是合理的。
- 如果 load average 大于 CPU 核心数,表示系统的进程比 CPU 能处理的多,系统可能处于过载状态。
- 在单核系统中,load average 数值超过 1 通常意味着系统繁忙(有任务在等待 CPU)。
- 在多核系统中,假设有 N 个 CPU 核心,load average 接近 N 时表示系统正处于高负载状态,但还在可接受范围内。如果 load average 超过 N,则意味着系统可能过载。
- macOS 上可以通过 sysctl -a | grep machdep.cpu.core_count 查看 CPU 核心数,我本机目前是 16 核。
chmod 的参数?
chmod 命令在 Linux 中用来改变文件或目录的访问权限。这个命令的使用可以基于符号模式或数字模式。
Linux 中的权限可以应用于三种类别的用户:
文件所有者(u)
与文件所有者同组的用户(g)
其他用户(o)
①、符号模式
符号模式使用字母来表示权限,如下:
读(r) 写(w) 执行(x) 所有(a)②、数字模式
数字模式使用三位八进制数来表示权限,每位数字代表不同的用户类别(所有者、组、其他用户),数字是其各自权限值的总和:
读(r)= 4 写(w)= 2 执行(x)= 1


kill -9 中的 9 是什么意思?
kill -9 PID 是一种强制终止进程的方式,其中的 9 表示信号编号,代表 SIGKILL 信号。
6.3 网络管理的命令有哪些?
- ping:测试网络连接。
- ifconfig:查看和配置网络接口。
- netstat:查看网络状态。
- wget:从网络上下载文件。
⭐️查看网络状态
netstat -nap
- 作用:将列出所有的网络连接(包括TCP和UDP连接)、监听的端口以及与之关联的进程信息。这对于诊断网络问题和监视系统上的网络活动非常有用
⭐️查看某个进程使用的端口?
netstat 命令 ss 命令 lsof 命令
如何查看8080端口的连接数?
- 可以通过 netstat 命令查看,如netstat -an | grep ‘:8080’ | grep ‘tcp’ | wc -l。
-a:显示所有网络连接和监听端口。
-n:以数字形式显示地址和端口。
grep ‘:8080’:过滤出 8080 端口的连接。
grep ‘tcp’:仅显示 TCP 连接。
wc -l:统计匹配到的行数,即连接数。- 也可以使用 ss 命令,它是 netstat 的替代工具;
- 还可以使用 lsof 命令,它可以列出当前系统打开的文件和套接字。

6.4 压缩和解压的命令有哪些?
- tar:打包或解包.tar文件。tar cvf archive.tar files打包,tar xvf archive.tar解包。
- gzip / gunzip:压缩或解压.gz文件。
- zip / unzip:压缩或解压.zip文件。
查找文件的命令有哪些?
find:在目录树中查找文件。find /directory/ -name filename。
Liunx 下查找一个文件?
在 Linux 环境下查找文件,有多种命令和方法可以使用。find 命令是最常用的文件查找工具之一,它可以在指定目录下递归查找符合条件的文件和目录。
