在操作系统的架构中,内核(Kernel)处于核心枢纽位置,它宛如一位掌控全局的管理者,精心掌管着内存、硬件设备、文件系统以及应用程序,就像桥梁一样连接着应用程序和硬件,决定着系统稳不稳定、快不快,CPU有用户态和内核态两种状态。
一、用户态与内核态:权限世界的两极
1、用户态(User Mode):有限权限的 “居民区”
在用户态运行的程序,就像是普通居民,能访问自己家里的东西(用户程序数据),但权限有限。当应用程序执行一些诸如读写磁盘、网络通信等需特殊权限的操作时,就好比居民要动用超出其居住区域权限的资源,此时必须向操作系统发出系统调用请求,进入内核态。
2、内核态(Kernel Mode):特权掌控的 “指挥中心”
内核态就像管理员,几乎能访问计算机所有资源,比如内存空间、硬件设备、驱动程序等,权限超高。当操作系统收到用户态程序的系统调用请求,就会从用户态切换到内核态,帮程序完成操作,再把结果返回,最后又切回用户态。
3、为何单一内核态不可行:混乱与无序的潜在风险
CPU的指令里,有些像内存分配、设置时钟、IO处理这些,特别危险。要是所有程序都能用这些指令,那系统就乱套了,就像谁都能当管理员乱动东西,肯定出问题。所以,这些危险指令只能在内核态运行,叫特权指令。要是系统只有内核态,所有程序都共享资源,就会抢来抢去,影响性能,而且安全性也就没了。
二、系统调用:用户态与内核态的沟通纽带
平常我们运行的程序大多在用户态,要是程序想对系统级别的资源,一旦涉及与系统态级别资源相关的操作,诸如文件管理、进程控制、内存管理等,就得通过系统调用,向操作系统发出服务请求,进而由操作系统代为完成这些操作,系统调用是操作系统内核提供的,运行在内核态。
三、进程、线程、协程:并发编程的三剑客
1、进程:资源分配的独立王国
进程是操作系统分配资源的最小单位,每个进程都有自己独立的内存空间、数据和资源,每一个进程都犹如一座独立的城堡,不同进程之间彼此隔绝,各自独立运行,互不干扰。
2、线程:进程中的轻量级 “执行者”
线程则是操作系统中调度的最小单位,可将其看作是进程这座城堡中的不同 “生产线”。一个进程能够容纳多个线程,相较于进程,线程更为轻量级,创建与切换所耗费的资源和时间都相对较少。同一进程内的线程如同同一条生产线上的工人,共享内存和文件句柄等资源,这使得线程之间的数据共享与通信变得更为便捷。多个线程共同享有进程的堆和方法区(JDK1.8 之后为元空间)资源,每个线程都配备有自己独立的程序计数器、虚拟机栈和本地方法栈。线程在需要共享资源且高并发执行的场景中表现卓越,例如在繁忙的 Web 服务器处理海量并发请求,或是进行复杂的并发计算任务。
由操作系统内核调度,属于内核态调度。线程切换涉及上下文保存和恢复(如寄存器、程序计数器等),相对协程开销较大
3、协程:轻量级
协程比线程还轻量级,它自己就能调度,不怎么依赖操作系统内核。创建和切换协程几乎不花什么代价,因为不用经过系统调用,在用户态就能完成。协程适合做轻量级、异步的任务,像网络请求、IO 操作。
GO的高并发得益于协程,并由此广被高并发场景应用,由Go语言的运行时(runtime)调度,属于用户态调度,不依赖操作系统内核。协程的切换由Go的调度器(GPM模型)控制,避免了内核态和用户态的切换开销
四、多线程:释放系统潜能的密钥
1、单核时代:提升单进程资源利用率的利器
在单核时代,多线程能提高单进程利用 CPU 和 IO 系统的效率。比如说只有一个 Java 进程,如果只有一个线程,这个线程要是被 IO 操作堵住了,整个进程就动不了,CPU 和 IO 设备只有一个能工作,效率低。但有多线程的话,一个线程被堵,其他线程还能用 CPU,这样进程就能更好地利用系统资源。
2、多核时代:发挥多核优势
进入多核时代,多线程能让进程更好地利用多核 CPU。比如要算一个复杂任务,只用一个线程,不管有几个 CPU 核心,只有一个核心在干活。要是创建多个线程,这些线程能分到不同 CPU 核心上运行,在不抢资源的情况下,任务就能快很多,差不多是单核运行时间除以 CPU 核心数(单核时执行时间 / CPU 核心数)。
操作系统的这些底层概念是构建高效、稳定软件系统的基石,深入理解它们对于每一位开发者而言都至关重要。