操作系统概述
操作系统概述
什么是操作系统?
操作系统可以说是硬件上的第一层软件,屏蔽了硬件层的复杂性,管理计算机硬件与软件资源的程序。操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的进程线程管理、内存管理、文件管理、设备管理。 内核是连接应用程序和硬件的桥梁,决定着系统的性能和稳定性。
操作系统主要有哪些功能?
从资源管理的角度来看,操作系统有 6 大功能:
- 进程和线程的管理:进程的创建、撤销、阻塞、唤醒,进程间的通信等。
- 存储管理:内存的分配和管理、外存(磁盘等)的分配和管理等。
- 文件管理:文件的读、写、创建及删除等。
- 设备管理:完成设备(输入输出设备和外部存储设备等)的请求或释放,以及设备启动等功能。
- 网络管理:操作系统负责管理计算机网络的使用。网络是计算机系统中连接不同计算机的方式,操作系统需要管理计算机网络的配置、连接、通信和安全等,以提供高效可靠的网络服务。
- 安全管理:用户的身份认证、访问控制、文件加密等,以防止非法用户对系统资源的访问和操作。
二、用户态和内核态
什么是用户态和内核态?
根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:
- 用户态(User Mode) : 用户态运行的进程可以直接读取用户程序的数据,拥有较低的权限。当应用程序需要执行某些需要特殊权限的操作,例如读写磁盘、网络通信等,就需要向操作系统发起系统调用请求,进入内核态。【应用程序、库函数、系统调用接口】
- 内核态(Kernel Mode):内核态运行的进程几乎可以访问计算机的任何资源包括系统的内存空间、设备等,不受限制,拥有非常高的权限。

内核态相比用户态拥有更高的权限,因此能够执行更底层、更敏感的操作。不过,由于进入内核态需要付出较高的开销(需要进行一系列的上下文切换和权限检查),应该尽量减少进入内核态的次数,以提高系统的性能和稳定性。
为什么要有用户态和内核态?
在 CPU 的所有指令中,有一些指令是比较危险的,比如内存分配、设置时钟、IO 处理等,如果所有的程序都能使用这些指令的话,不能保证系统的安全性。所以我们需要限制这些指令只能在更高权限状态,也就是内核态运行。这些只能由操作系统内核态执行的指令也被叫做 特权指令 。
只有一个内核态不行么?
如果计算机系统中只有一个内核态,那么所有程序或进程具有相同的特权级别和访问权限,都必须共享系统资源,例如内存、CPU、硬盘等,这将导致系统资源的竞争和冲突,从而影响系统性能和效率。让系统的安全性降低。
new一个对象会跑到内核态吗?
- 通常情况下,
new
一个对象是在用户态完成的,不会跑到内核态。 - 在内存不足需要操作系统介入时,可能会触发内核态的操作。
- 不同编程语言和环境中的实现可能有所不同,但大多数情况都是在用户态完成内存分配。
用户态和内核态是如何切换的?
用户态切换到内核态的 3 种方式:
- 系统调用(Trap):用户态进程 主动 要求切换到内核态的一种方式,主要是为了使用内核态才能做的事情比如读取磁盘资源。
- 中断(Interrupt):现在执行的是用户态程序,当外部设备完成用户请求的操作后,会向 CPU 发出相应的中断信号,这时 CPU 会暂停当前的用户态程序,转而去执行设备中断信号对应的处理程序。那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
- 异常(Exception):当 CPU 在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时切换到处理异常的内核相关程序中,也就转到了内核态,比如缺页异常。
系统调用
什么是系统调用?
也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。
这些系统调用按功能大致可分为如下几类:
- 设备管理:完成设备(输入输出设备和外部存储设备等)的请求或释放,以及设备启动等功能。
- 文件管理:完成文件的读、写、创建及删除等功能。
- 进程管理:进程的创建、撤销、阻塞、唤醒,进程间的通信等功能。
- 内存管理:完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。
总结:系统调用是应用程序与操作系统之间进行交互的一种方式,通过系统调用,应用程序可以访问操作系统底层资源例如文件、设备、网络等。
系统调用的过程了解吗?
系统调用的过程可以简单分为以下几个步骤:
- 用户态的程序发起系统调用,因为系统调用中涉及一些特权指令(只能由操作系统内核态执行的指令),用户态程序权限不足,因此会中断执行,也就是 Trap(Trap 是一种中断)。
- 发生中断后,当前 CPU 执行的程序会中断,跳转到中断处理程序。内核程序开始执行,也就是开始处理系统调用。
- 内核处理完成后,主动触发 Trap,这样会再次发生中断,切换回用户态工作。

系统调用的执行过程
- 用户程序调用系统函数,将系统调用的参数传递给系统函数。
- 系统函数将系统调用的参数存储到寄存器中,并将系统调用号(syscall number)存储到寄存器eax中。
- 系统函数执行中断指令int 0x80,触发CPU从用户态切换到内核态,将控制权交给操作系统内核。
- 操作系统内核根据系统调用号和参数,执行相应的特权操作,如创建进程、打开文件、读写设备等。
- 操作系统内核将特权操作的结果返回给用户程序,将控制权重新切换到用户态,继续执行用户程序。
内核是怎么知道处理不同的系统调用的?
内核维护一张系统调用表,每个系统调用都有相应的系统调用号作为唯一的标识,就是系统调用在调用表的偏移量。在进行系统调用是只要指定对应的系统调用号,就可以明确的要调用哪个系统调用。
具体的系统中断指令有哪些?
下面一些函数已经过时,被新的更好的函数所代替了(gcc在链接这些函数时会发出警告),由于兼容的原因还保留着,这些函数将在前面标上“*”号以示区别。
进程控制
- fork 创建一个新进程
- clone 按指定条件创建子进程
- execve 运行可执行文件
- exit 中止进程
- getpid 获取进程标识号
- getpriority 获取调度优先级
- setpriority 设置调度优先级
- wait 等待子进程终止
- waitpid 等待指定子进程终止
文件读写操作
- fcntl 文件控制
- open 打开文件
- creat 创建新文件
- close 关闭文件描述字
- read 读文件
- write 写文件
- fsync 把文件在内存中的部分写回磁盘
文件系统操作
- chmod 改变文件方式
- stat 取文件状态信息
- mkdir 创建目录
- rename 文件改名
- link 创建链接
- symlink 创建符号链接
- unlink 删除链接
- readlink 读符号链接的值
- mount 安装文件系统
- umount 卸下文件系统
系统控制
- sysinfo 取得系统信息
- adjtimex 调整系统时钟
- alarm 设置进程的闹钟
- time 取得系统时间
- times 取进程运行时间
- uname 获取当前UNIX系统的名称、版本和主机等信息
内存管理
- mlock 内存页面加锁
- munlock 内存页面解锁
- mlockall 调用进程所有内存页面加锁
- munlockall 调用进程所有内存页面解锁
- mmap 映射虚拟内存页
- munmap 去除内存页映射
- mremap 重新映射虚拟内存地址
- msync 将映射内存中的数据写回磁盘
- mprotect 设置内存映像保护
- getpagesize 获取页面大小
- sync 将内存缓冲区数据写回硬盘
- cacheflush 将指定缓冲区中的内容写回磁盘
网络管理
- getdomainname 取域名
- setdomainname 设置域名
- gethostid 获取主机标识号
- sethostid 设置主机标识号
- gethostname 获取本主机名称
- sethostname 设置主机名称
Socket控制
- socket 建立socket
- bind 绑定socket到端口
- connect 连接远程主机
- accept 响应socket连接请求
- send 通过socket发送信息
- recv 通过socket接收信息
- recvfrom 接收UDP信息
- listen 监听socket端口
- select 对多路同步I/O进行轮询
- shutdown 关闭socket上的连接
- getsockname 取得本地socket名字
用户管理
- getuid 获取用户标识号
- setuid 设置用户标志号
进程间通信
- ipc 进程间通信总控制调用
- 信号
- sigaction 设置对指定信号的处理方法
- sigprocmask 根据参数对信号集中的信号执行阻塞/解除阻塞等操作
- sigpending 为指定的被阻塞信号设置队列
- sigsuspend 挂起进程等待特定信号
- signal 参见signal
- 消息
- msgctl 消息控制操作
- msgget 获取消息队列
- msgsnd 发消息
- msgrcv 取消息
- 管道
- pipe 创建管道
- 信号量
- semctl 信号量控制
- semget 获取一组信号量
- semop 信号量操作
- 共享内存
- shmctl 控制共享内存
- shmget 获取共享内存
- shmat 连接共享内存
- shmdt 拆卸共享内存
中断是什么,为什么需要中断?
中断其实就是在CPU正在做某件事的时候,收到了通知告诉CPU你要放下手头现在做的事,去处理这个中断。 【CPU在收到中断信号以后,并不立即执行响应,而是在执行每条指令周期的最后一个时钟周期,一旦检测到中断信号有效,并且中断允许位置1的时候,CPU才在当前指令执行完以后转入中断响应周期。】
**操作系统是中断驱动的,**中断可以提高操作系统运行的效率,有了中断系统才能并发运行。
外部中断
外部中断是指来自CPU外部的中断,外部的中断源必须是硬件,因此外部中断又称为硬件中断。
CPU如何收到来自外部的 中断呢?
外部中断是通过两根信号线通知CPU的,这两根信号线是INTR和NMI,通过INTR总线进来的是可屏蔽中断,NMI总线进来的是不可屏蔽中断。

可屏蔽中断和不可屏蔽中断的区别是什么?
可屏蔽中断是通过INTR信号线进入CPU,外部硬件设备产生的中断CPU可以理会,可以不理会,因为此类中断不会让操作系统宕机。
不可中断是指通过NMI信号线进入CPU,表示系统中出现了致命的错误,此类错误会导致操作系统宕机,因此不可以屏蔽,必须进行响应的处理。
内部中断
内部中断可以说是来自CPU执行过程中产生的中断,分为软中断和异常。
- 什么是软中断?
Linux 系统为了解决中断处理程序执行过长和中断丢失的问题,将中断过程分成了两个阶段,分别是「上半部和下半部分」。
- 上半部用来快速处理中断,一般会暂时关闭中断请求,主要负责处理跟硬件紧密相关或者时间敏感的事情。这部分直接处理硬件请求,是硬中断。特点是快速执行。
- 下半部分,内核会触发一个软中断,用来延迟处理上半部未完成的工作,把一些处理比较耗时且复杂的事情,交给「软中断处理程序」去做。
- 什么是异常?
CPU在执行指令期间发生错误导致的中断成为异常。比如除以0。
异常的种类有哪些?
异常根据严重程度分为以下三种:
- Fault:故障,当发生此类异常时,CPU将机器状态恢复到异常之前的状态,之后调用中断处理程序。时,CPU将返回地址依然指向导致fault异常的那条指令,给他一次改过自新的机会让其重新执行。
- Trap:陷阱,程序在运行时掉进了CPU设置的陷阱从而停止运行,通常用于调试中,比如int3指令【3号中断】便可引发该异常,CPU将中断处理程序的返回地址指向导致异常指令的下一个指令地址
- Abort:终止,一旦出现,错误无法修复,操作系统为了自保,会将此程序从进程表中去掉。