当前位置: 首页 > 科技观察

浅谈用户空间和内核空间

时间:2023-03-17 10:02:27 科技观察

本文转载自微信公众号“Angela的博客”,作者Angela。转载本文请联系Angela博客公众号。最近在整理Java并发方面的知识。这篇文章是为后面的ReentrantLock做准备。先热身。随着研究的深入,我来到了这里。为了弄清楚一件事,你可以无限地向下钻取。就像物体->分子->原子->夸克,直到超出我所能理解的知识范围。前言我们知道操作系统使用虚拟地址空间。以32位操作系统为例,其寻址空间为4G(2的32次方)。这里解释两个概念:寻址:指的是操作系统能找到的地址范围,32位指的是地址总线的位数,你可以想象一个32位的二进制数,每一位都可以为0,它可以是1,有没有可能是2的32次方,2^32次方就是最大可以访问的内存空间,也就是4G。虚拟地址空间:为什么叫虚拟,因为我们的总内存是4G,但是操作系统给每个进程分配了4G的内存空间。这个内存空间其实是虚拟的,虚拟内存和实内存之间存在映射关系。比如X86cpu采用的段页地址映射模型。操作系统将4G可访问内存空间分为两部分,一部分是内核空间,一部分是用户空间。内核空间是操作系统内核访问的区域,独立于普通应用程序,是受保护的内存空间。用户空间是普通应用程序可以访问的内存区域。以linux操作系统为例,最高1G字节(从虚拟地址0xC0000000到0xFFFFFFFF)被内核使用,称为内核空间,低3G字节(从虚拟地址0x00000000到0xBFFFFFFF)分别被内核使用进程使用,称为用户空间。空间分配如下图所示:每个进程都可以通过系统调用进入内核,因此Linux内核是系统中所有进程共享的。因此,从具体的进程来看,每个进程可以拥有4G字节的虚拟空间。之所以区分内核空间和用户空间,是因为早期的操作系统没有区分内核空间和用户空间,但是应用程序可以访问任何内存空间。如果程序不稳定,往往会导致系统崩溃,比如清除操作系统的内存数据。后来觉得应用程序随便访问内存太危险了,就按照CPU指令的重要程度对指令进行了分类。指令分为四个级别:Ring0~Ring3(类似于电影分级)。Linux只使用Ring0和Ring3两个级别的操作。当进程运行在Ring3级别时,它运行在用户态,指令只访问用户空间。当它运行在Ring0级别时,称为运行在内核态,可以访问任意内存空间。处于用户态的程序不能随意操作内核地址空间,对操作系统有一定的安全保护作用。说起内核态和用户态其实很清楚:进程/线程运行在内核空间就是内核态,进程/线程运行在用户态就是用户态。在内核模式下,进程运行在内核地址空间,此时CPU可以执行任意指令。运行代码不受任何限制,可以自由访问任意有效地址,也可以直接访问端口。在用户态下,进程运行在用户地址空间,执行的代码要经过CPU的很多检查,例如:进程只能访问页表中指定的用户态下可以访问的虚拟页映射其地址空间的条目。地址。我们先看一下Linux系统的整体结构:下面是从内核空间(写成内存空间)到内核态的切换要做的,我们的应用程序需要访问磁盘,读取网络的数据card,并通过系统调用接口新建一个线程,完成从用户态到内存态的切换。例如,我们需要在Java中创建一个新的线程。newThread(Runnable...)后调用start()方法时,参见HotspotLinux的JVM源码实现。最后调用pthread_create系统方法创建的线程会在这里从用户态切换。进入内核态完成系统资源的分配和线程的创建。当一个任务(进程)执行系统调用,进入内核代码的执行时,称该进程处于内核运行态(kernelstate)。除了系统调用可以实现从用户态到内核态的切换,还有没有别的办法呢?是的,软件中断和硬中断。软中断是指进程中发生的异常事件;硬中断有很多种,比如时钟周期,IO等,涉及到很多操作系统知识,这里就不展开了。