精华内容
下载资源
问答
  • 用户空间和内核空间的区别
    千次阅读
    2021-01-12 03:09:38

    用户空间和内核空间

    最近在重新梳理Java 并发的知识,这篇文章是为了后面讲ReentrantLock做准备的,先热个身,随着研究的深入,就来到了这里,要把一件事情讲清楚,可以无限下钻,就像物体->原子->分子->夸克,直到超出自己能理解的知识范畴。

    前言

    我们知道操作系统采用的是虚拟地址空间,以32位操作系统举例,它的寻址空间为4G(2的32次方),这里解释二个概念:

    1. 寻址: 是指操作系统能找到的地址范围,32位指的是地址总线的位数,你就想象32位的二进制数,每一位可以是0,可以是1,是不是有2的32次方种可能,2^32次方就是可以访问到的最大内存空间,也就是4G。
    2. 虚拟地址空间:为什么叫虚拟,因为我们内存一共就4G,但操作系统为每一个进程都分配了4G的内存空间,这个内存空间实际是虚拟的,虚拟内存到真实内存有个映射关系。例如X86 cpu采用的段页式地址映射模型。

    操作系统将这4G可访问的内存空间分为二部分,一部分是内核空间,一部分是用户空间。

    内核空间是操作系统内核访问的区域,独立于普通的应用程序,是受保护的内存空间。

    用户空间是普通应用程序可访问的内存区域。

    以linux操作系统为例,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空间,而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF),供各个进程使用,称为用户空间。空间分配如下图所示:

    在这里插入图片描述

    每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。

    区分内核空间和用户空间原因

    其实早期操作系统是不区分内核空间和用户空间的,但是应用程序能访问任意内存空间,如果程序不稳定常常把系统搞崩溃,比如清除操作系统的内存数据。后来觉得让应用程序随便访问内存太危险了,就按照CPU 指令的重要程度对指令进行了分级,指令分为四个级别:Ring0~Ring3 (和电影分级有点像),linux 只使用了 Ring0 和 Ring3 两个运行级别,进程运行在 Ring3 级别时运行在用户态,指令只访问用户空间,而运行在 Ring0 级别时被称为运行在内核态,可以访问任意内存空间。

    用户态的程序不能随意操作内核地址空间,这样对操作系统具有一定的安全保护作用。

    说说内核态和用户态

    其实很清晰:当进程/线程运行在内核空间时就处于内核态,而进程/线程运行在用户空间时则处于用户态。

    在内核态下,进程运行在内核地址空间中,此时 CPU 可以执行任何指令。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。

    在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的很多检查,比如:进程只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址。

    我们来看下linux系统的整体结构:

    在这里插入图片描述

    用户态到内核态的切换

    如上图所示,所有系统资源的管理都是在内存空间进行的,也就是在内核态去做的,那我们应用程序需要访问磁盘,读取网卡的数据,新建一个线程都需要通过系统调用接口,完成从用户态到内存态的切换。

    比如我们 Java 中需要新建一个线程,new Thread( Runnable ...) 之后调用 start() 方法时, 看Hotspot Linux 的JVM 源码实现,最终是调pthread_create 系统方法来创建的线程,这里会从用户态切换到内核态完成系统资源的分配,线程的创建。

    当一个任务(进程)执行系统调用而陷入内核代码中执行时,称进程处于内核运行态(内核态)

    除了系统调用可以实现用户态到内核态的切换,还有别的方式吗? 有,软中断和硬中断。

    软中断是指进程发生了异常事件;硬中断就有很多种,例如时钟周期、IO等。涉及的操作系统知识比较多,这里不展开讲。

    后面会细讲Java线程和ReentrantLock再结合内核态、用户态讲上下文切换。

    更多相关内容
  • Linux 系统内核空间与用户空间通信的实现与分析 Linux 内核模块的运行环境与传统进程间通信 在一台运行 Linux 的计算机中,CPU 在任何时候只会有如下四种状态: 【1】 在处理一个硬中断。 【2】 在处理一个软中断,...
  • Linux 内核空间与用户空间

    千次阅读 2020-08-31 22:28:24
    目录内核空间和用户空间为什么需要区分内核空间与用户空间内核态与用户态如何从用户空间进入内核空间整体结构总结另一种说法一、4G地址空间解析二、虚拟地址空间分配及其与物理内存对应图三、物理内存分配图 内核...

    内核空间和用户空间

     对 32 位操作系统而言,它的寻址空间(虚拟地址空间,或叫线性地址空间)为 4G(2的32次方)。也就是说一个进程的最大地址空间为 4G。操作系统的核心是内核(kernel),它独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证内核的安全,现在的操作系统一般都强制用户进程不能直接操作内核。具体的实现方式基本都是由操作系统将虚拟地址空间划分为两部分,一部分为内核空间,另一部分为用户空间。针对 Linux 操作系统而言,最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间。
    对上面这段内容我们可以这样理解:
    每个进程的 4G 地址空间中,最高 1G 都是一样的,即内核空间。只有剩余的 3G 才归进程自己使用。
    换句话说就是, 最高 1G 的内核空间是被所有进程共享的!
    下图描述了每个进程 4G 地址空间的分配情况:
    在这里插入图片描述

    为什么需要区分内核空间与用户空间

     在 CPU 的所有指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。
     所以,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。比如 Intel 的 CPU 将特权等级分为 4 个级别:Ring0~Ring3。
     其实 Linux 系统只使用了 Ring0 和 Ring3 两个运行级别(Windows 系统也是一样的)。当进程运行在 Ring3 级别时被称为运行在用户态,而运行在 Ring0 级别时被称为运行在内核态。

    内核态与用户态

     好了我们现在需要再解释一下什么是内核态、用户态:

    当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。

     在内核态下,进程运行在内核地址空间中,此时 CPU 可以执行任何指令。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。

     在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/O 许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。

     对于以前的 DOS 操作系统来说,是没有内核空间、用户空间以及内核态、用户态这些概念的。可以认为所有的代码都是运行在内核态的,因而用户编写的应用程序代码可以很容易的让操作系统崩溃掉。

     对于 Linux 来说,通过区分内核空间和用户空间的设计,隔离了操作系统代码(操作系统的代码要比应用程序的代码健壮很多)与应用程序代码。即便是单个应用程序出现错误也不会影响到操作系统的稳定性,这样其它的程序还可以正常的运行(Linux 可是个多任务系统啊!)。

     所以,区分内核空间和用户空间本质上是要提高操作系统的稳定性及可用性。

    如何从用户空间进入内核空间

     其实所有的系统资源管理都是在内核空间中完成的。比如读写磁盘文件,分配回收内存,从网络接口读写数据等等。我们的应用程序是无法直接进行这样的操作的。但是我们可以通过内核提供的接口来完成这样的任务。

     比如应用程序要读取磁盘上的一个文件,它可以向内核发起一个 “系统调用” 告诉内核:“我要读取磁盘上的某某文件”。其实就是通过一个特殊的指令让进程从用户态进入到内核态(到了内核空间),在内核空间中,CPU 可以执行任何的指令,当然也包括从磁盘上读取数据。具体过程是先把数据读取到内核空间中,然后再把数据拷贝到用户空间并从内核态切换到用户态。此时应用程序已经从系统调用中返回并且拿到了想要的数据,可以开开心心的往下执行了。

     简单说就是应用程序把高科技的事情(从磁盘读取文件)外包给了系统内核,系统内核做这些事情既专业又高效。

     对于一个进程来讲,从用户空间进入内核空间并最终返回到用户空间,这个过程是十分复杂的。举个例子,比如我们经常接触的概念 “堆栈”,其实进程在内核态和用户态各有一个堆栈。运行在用户空间时进程使用的是用户空间中的堆栈,而运行在内核空间时,进程使用的是内核空间中的堆栈。所以说,Linux 中每个进程有两个栈,分别用于用户态和内核态。

    下图简明的描述了用户态与内核态之间的转换:

    在这里插入图片描述

     既然用户态的进程必须切换成内核态才能使用系统的资源,那么我们接下来就看看进程一共有多少种方式可以从用户态进入到内核态。概括的说,有三种方式:系统调用、软中断和硬件中断。这三种方式每一种都涉及到大量的操作系统知识,所以这里不做展开。

    整体结构

     接下来我们从内核空间和用户空间的角度看一看整个 Linux 系统的结构。它大体可以分为三个部分,从下往上依次为:硬件 -> 内核空间 -> 用户空间。如下图所示(此图来自互联网):
    在这里插入图片描述

     在硬件之上,内核空间中的代码控制了硬件资源的使用权,用户空间中的代码只有通过内核暴露的系统调用接口(System Call Interface)才能使用到系统中的硬件资源。其实,不光是 Linux,Windows 操作系统的设计也是大同小异。

    总结

     现代的操作系统大都通过内核空间和用户空间的设计来保护操作系统自身的安全性和稳定性。所以在我们阅读有关操作系统的资料时经常遇到内核空间、用户空间和内核态、用户态等概念,希望本文能够帮助您理解这些基本的概念。


    另一种说法

    关于虚拟内存有三点需要注意:

    • 4G的进程地址空间被人为的分为两个部分–用户空间与内核空间。用户空间从0到3G(0xc0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间的虚拟地址。例外情况只有用户进程进行系统调用(代表用户进程在内核态执行)等时刻可以访问到内核空间。
    • 用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程变化,是固定的。内核空间地址有自己对应的页表,用户进程各自有不同的页表。
    • 每个进程的用户空间都是完全独立、互不相干的。

    一、4G地址空间解析

    在这里插入图片描述
     上图展示了整个进程地址空间的分布,其中4G的地址空间分为两部分,在用户空间内,对应了内存分布的五个段:数据段、代码段、BSS段、堆、栈。在上篇文章中有详细的介绍。

    二、虚拟地址空间分配及其与物理内存对应图

    在这里插入图片描述

     这个图示内核用户空间的划分,图中最重要的就是高端内存的映射其中kmalloc和vmalloc函数申请的空间对应着不同的区域,同时又不同的含义。

    三、物理内存分配图

    在这里插入图片描述

    这张图中页解释了三者的不同关系,和上篇文章中的内容有相似之处。

    伙伴算法

     一种物理内存分配和回收的方法,物理内存所有空闲页都记录在BUDDY链表中。首选,系统建立一个链表,链表中的每个元素代表一类大小的物理内存,分别为2的0次方、1次方、2次方,个页大小,对应4K、8K、16K的内存,没一类大小的内存又有一个链表,表示目前可以分配的物理内存。例如现在仅存需要分配8K的物理内存,系统首先从8K那个链表中查询有无可分配的内存,若有直接分配;否则查找16K大小的链表,若有,首先将16K一分为二,将其中一个分配给进程,另一个插入8K的链表中,若无,继续查找32K,若有,首先把32K一分为二,其中一个16K大小的内存插入16K链表中,然后另一个16K继续一分为二,将其中一个插入8K的链表中,另一个分配给进程…以此类推。当内存释放时,查看相邻内存有无空闲,若存在两个联系的8K的空闲内存,直接合并成一个16K的内存,插入16K链表中。(伙伴算法用于物理内存分配方案)

    SLAB算法:

     是一种对伙伴算的一种补充,对于用户进程的内存分配,伙伴算法已经够好了,但对于内核进程,还需要存在一类很小的数据(字节大小,比如进程描述符、虚拟内存描述符等),若每次给几个字节的数据分配一个4KB的页,实在太浪费,于是就有了SLBA算法,SLAB算法其实就是把一个页用力劈成一小块一小块,然后再分配。

    展开全文
  • Linux用户空间与内核空间、内核的功能与作用 在讲述内核的功能及其作用以前,先简单介绍一下内核空间和用户空间 用户空间和内核空间 概念简介 内核空间(User Space):用户程序的运行空间。为了安全,它们是隔离的...

    Linux用户空间与内核空间、内核的功能与作用

    在讲述内核的功能及其作用以前,先简单介绍一下内核空间和用户空间

    用户空间和内核空间

    概念简介

    • 内核空间(User Space):用户程序的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃,内核也不会受到影响。只能执行简单的运算,不能直接调用系统资源,必须通过系统接口(system call),才能向内核发出指令。
    • 内核空间(Kernel Space):这是Linux内核的运行空间,可以执行任意命令,调用系统的一切资源。

    对 32 位操作系统而言,它的寻址空间(虚拟地址空间,或叫线性地址空间)为 4G(2的32次方)。也就是说一个进程的最大地址空间为 4G。
    操作系统的核心是内核(kernel),它独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证内核的安全,现在的操作系统一般都强制用户进程不能直接操作内核。
    具体的实现方式基本都是由操作系统将虚拟地址空间划分为两部分,一部分为内核空间,另一部分为用户空间。针对 Linux 操作系统而言,最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间。
    对上面这段内容我们可以这样理解:

    • 每个进程的 4G 地址空间中,最高 1G 都是一样的,即内核空间。只有剩余的 3G 才归进程自己使用。换句话说就是, 最高 1G 的内核空间是被所有进程共享的。

    下图描述了每个进程 4G 地址空间的分配情况:
    内存空间和用户空间的占用地址

    为什么需要区分内核空间和用户空间

    在 CPU 的所有指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。
    所以,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。

    比如 Intel 的 CPU 将特权等级分为 4 个级别:Ring0~Ring3。其实 Linux 系统只使用了 Ring0 和 Ring3 两个运行级别(Windows 系统也是一样的)。当进程运行在 Ring3 级别时被称为运行在用户态,而运行在 Ring0 级别时被称为运行在内核态。
    在这里插入图片描述

    内核态和用户态

    当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。

    • 在内核态下,进程运行在内核地址空间中,此时 CPU 可以执行任何指令。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。
    • 在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/O 许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。

    对于以前的 DOS 操作系统来说,是没有内核空间、用户空间以及内核态、用户态这些概念的。可以认为所有的代码都是运行在内核态的,因而用户编写的应用程序代码可以很容易的让操作系统崩溃掉。
    但是对于 Linux 来说,通过区分内核空间和用户空间的设计,隔离了操作系统代码(操作系统的代码要比应用程序的代码健壮很多)与应用程序代码。即便是单个应用程序出现错误也不会影响到操作系统的稳定性,这样其它的程序还可以正常的运行(Linux本质上是一个多任务系统)。

    所以,区分内核空间和用户空间本质上是要提高操作系统的稳定性及可用性。

    如何从用户空间进入内核空间

    其实所有的系统资源管理都是在内核空间中完成的。比如读写磁盘文件,分配回收内存,从网络接口读写数据等等。我们的应用程序是无法直接进行这样的操作的。但是我们可以通过内核提供的接口来完成这样的任务。
    比如应用程序要读取磁盘上的一个文件,它可以向内核发起一个 “系统调用” 告诉内核:“我要读取磁盘上的某某文件”。其实就是通过一个特殊的指令让进程从用户态进入到内核态(到了内核空间),在内核空间中,CPU 可以执行任何的指令,当然也包括从磁盘上读取数据。具体过程是先把数据读取到内核空间中,然后再把数据拷贝到用户空间并从内核态切换到用户态。此时应用程序已经从系统调用中返回并且拿到了想要的数据,可以开开心心的往下执行了。
    简单说就是应用程序把高科技的事情(从磁盘读取文件)外包给了系统内核,系统内核做这些事情既专业又高效。

    对于一个进程来讲,从用户空间进入内核空间并最终返回到用户空间,这个过程是十分复杂的。举个例子,比如我们经常接触的概念 “堆栈”,其实进程在内核态和用户态各有一个堆栈。运行在用户空间时进程使用的是用户空间中的堆栈,而运行在内核空间时,进程使用的是内核空间中的堆栈。所以说,Linux 中每个进程有两个栈,分别用于用户态和内核态。

    下图简明的描述了用户态与内核态之间的转换:
    在这里插入图片描述
    既然用户态的进程必须切换成内核态才能使用系统的资源,那么我们接下来就看看进程一共有多少种方式可以从用户态进入到内核态。概括的说,有三种方式:系统调用、软中断和硬件中断。这三种方式每一种都涉及到大量的操作系统知识,所以这里不做展开。

    整体结构

    我们从内核空间和用户空间的角度看一看整个 Linux 系统的结构。它大体可以分为三个部分,从下往上依次为:硬件 -> 内核空间 -> 用户空间。如下图所示:
    用户空间、内核空间和底层硬件的关系图
    在硬件之上,内核空间中的代码控制了硬件资源的使用权,用户空间中的代码只有通过内核暴露的系统调用接口(System Call Interface)才能使用到系统中的硬件资源。其实,不光是 Linux,Windows 操作系统的设计也是大同小异。

    实际上我们可以将每个处理器在任何指定时间点上的活动概括为下列三者之一:

    • 运行于用户空间,执行用户进程。
    • 运行于内核空间,处于进程上下文,代表某个特定的进程执行。
    • 运行于内核空间,处于中断上下文,与任何进程无关,处理某个特定的中断。

    以上三点几乎包括所有的情况,比如当 CPU 空闲时,内核就运行一个空进程,处于进程上下文,但运行在内核空间。

    说明:Linux 系统的中断服务程序不在进程的上下文中执行,它们在一个与所有进程都无关的、专门的中断上下文中执行。之所以存在一个专门的执行环境,就是为了保证中断服务程序能够在第一时间响应和处理中断请求,然后快速地退出。

    所以,现代的操作系统大都通过内核空间和用户空间的设计来保护操作系统自身的安全性和稳定性。所以在我们阅读有关操作系统的资料时经常遇到内核空间、用户空间和内核态、用户态等概念,希望本文能够帮助您理解这些基本的概念。

    实例讲解

    str= “www.magedu.com"     #用户空间
    x = x + 100               #用户空间
    file.write(str)           #切换到内核空间
    y = x + 200               #切换回用户空间
    

    说明:第一行和第二行都是简单的赋值运算,在User Space 执行。第三行需要写入文件,就要切换到Kernel Space,因为用户不能直接写文件,必须通过内核安排。第四行又是赋值运算,就切换回User Space。

    内核的概念和作用

    内核的概念

    内核指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。内核是一个操作系统的核心,是操作系统最基本的部分。它负责管理系统的进程、内存、设备驱动程序、文件和网络系统等,决定着系统的性能和稳定性。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件,这种访问是有限的,并且内核决定一个程序在什么时候对某部分硬件操作多长时间。直接对硬件操作是非常复杂的,所以内核通常提供一种硬件抽象的方法来完成这些操作。硬件抽象隐藏了复杂性,为应用软件和硬件提供了一套简洁,统一的接口,使程序设计更为简单。
    一个内核不是一套完整的操作系统。比如一套基于Linux内核的完整操作系统叫作Linux操作系统,或是GNU/Linux。

    内核的作用

    • 进程管理:内核负责创建和销毁进程, 并处理它们与外部世界的联系(输入和输出),不同进程间通讯(通过信号,管道,或者进程间通讯原语)对整个系统功能来说是基本的,也由内核处理。 另外, 调度器, 控制进程如何共享CPU,是进程管理的一部分。更通常地,内核的进程管理活动实现了多个进程在一个单个或者几个CPU 之上的抽象。
    • 内存管理:计算机的内存是主要的资源, 处理它所用的策略对系统性能是至关重要的。内核为所有进程的每一个都在有限的可用资源上建立了一个虚拟地址空间。内核的不同部分与内存管理子系统通过一套函数调用交互,从简单的malloc/free对到更多更复杂的功能。
    • 文件管理:Linux 在很大程度上基于文件系统的概念;几乎Linux中的任何东西都可看作一个文件。内核在非结构化的硬件之上建立了一个结构化的文件系统,结果是文件的抽象非常多地在整个系统中应用。另外,Linux 支持多个文件系统类型,就是说,物理介质上不同的数据组织方式。例如,磁盘可被格式化成标准Linux的ext3文件系统,普遍使用的FAT文件系统,或者其他几个文件系统。
    • 驱动管理:几乎每个系统操作终都映射到一个物理设备上,除了处理器,内存和非常少的别的实体之外,全部中的任何设备控制操作都由特定于要寻址的设备相关的代码来进行。这些代码称为设备驱动。内核中必须嵌入系统中出现的每个外设的驱动,从硬盘驱动到键盘和磁带驱动器。
    • 网络管理:网络必须由操作系统来管理,因为大部分网络操作不是特定于某一个进程: 进入系统的报文是异步事件。报文在某一个进程接手之前必须被收集,识别,分发,系统负责在程序和网络接口之间递送数据报文,它必须根据程序的网络活动来控制程序的执行。另外,所有的路由和地址解析问题都在内核中实现。

    参考链接:https://www.cnblogs.com/sparkdev/p/8410350.html
    参考链接:https://www.jianshu.com/p/fb744f37e364

    展开全文
  • 1、内核空间和用户空间的概念简介 在Linux中,操作系统和驱动程序运行在内核空间,应用程序运行在用户空间。 两者不能简单的使用指针传递数据,因为Linux使用的虚拟内核机制,当内核空间使用用户空间指针时,对应的...

    1、内核空间和用户空间的概念简介

    在Linux中,操作系统和驱动程序运行在内核空间,应用程序运行在用户空间
    两者不能简单的使用指针传递数据,因为Linux使用的虚拟内核机制,当内核空间使用用户空间指针时,对应的数据可能不在内存中(数据已被换出)。用户空间的内存采用段页式,内核空间也有自己的规则。

    32位的Linux内核虚拟地址空间,一般低3G的地址(0-3G)划分为用户空间,高1G的地址(3~4G)划为内核空间,也就是说内核空间可以使用的线性地址只有1G。

    另外也可以自行配置内核空间和用户空间的界限(大小),感兴趣自行搜索学习。
    在这里插入图片描述
    为什么要这样划分呢?

    • 处理器模式不同,权限不同
    对于X86体系的cpu,用户空间代码运行在Ring3横式,内核空间代码运行Ring0模式;
    对于arm体系的cpu,用户空间代码运行在usr横式,内核空间代码运行在svc模式;
    • 安全考虑
    整个系统中有各种资源,比如计箅资源、内存资源和外设资源,而linux是多用户、多进程系统,所以,这些资源必须在受限的、被管理的状态下使用,要不然就陷入了混乱,空间隔离可以保证即便是单个应用程序出现错误也不会影响到操作系统的稳定性
    • 从软件设计思想来看,解除了核心代码和业务逻辑代码的耦合
    内核代码偏重于系统管理;而用户空间代码(也即应用程序)偏重于业务逻辑代码的实现,
    两者分工不同,隔离也是解耦合

    2、内核空间和用户空间的数据传递

    在这里插入图片描述
    用户空间的应用程序,在业务实现时,
    1、如果很简单,比如你只实现个printf("hello world");,并没有和内核进行交互,那么就不会存在两个空间的数据拷贝。
    2、但是实际上,很多的业务实现都要与内核进行交互,各种上网,操作一些字符、块设备,调用open()、write()、read()、ioctl()等等函数,就要用到系统调用。这些都会触发一个中断,并通过中断的方式陷入到内核去执行,但用到的还是用户态进程,然后将进程需要的数据返回到用户空间。
    更加细节的可自行再去学习。

    下面我们就用代码来展示下内核空间和用户空间之间的数据拷贝。
    helloworld.c

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/cdev.h>
    #include <linux/fs.h>
    #include <linux/wait.h>
    #include <linux/poll.h>
    #include <linux/sched.h>
    #include <linux/slab.h>
    
    #define BUFFER_MAX (64)
    #define OK (0)
    #define ERROR (-1)
    
    struct cdev *gDev;
    struct file_operations *gFile;
    
    dev_t devNum;
    
    unsigned int subDevNum = 1;
    int reg_major = 813;
    int reg_minor = 0;
    char *buffer;
    
    int hello_open(struct inode *p, struct file *f)
    {
    	 printk(KERN_INFO "hello_open\r\n");
    	 return 0;
    }
    ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l)//*f为file的结构体指针,__user为编译器汇编扩展,用来说明*u为用户空间的地址,s是长度,*l为返回的offset
    {
    	 printk(KERN_INFO "hello_write\r\n");
    	 int writelen = 0;
    	 writelen = BUFFER_MAX>s ? s : BUFFER_MAX;
    	 if(copy_from_user(buffer,u,writelen)){
    		 return EFAULT;
    	 }
    	 return writelen;
    }
    ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l)
    {
    	 printk(KERN_INFO "hello_read\r\n");
    	 int readlen = 0;
    	 readlen = BUFFER_MAX > s ? s : BUFFER_MAX;
    	 if(copy_to_user(u,buffer,readlen)){
    		 return EFAULT;
    	 }	
    	 return readlen;
    }
    int hello_init(void)
    {
    	 devNum = MKDEV(reg_major, reg_minor);
    	 if(OK == register_chrdev_region(devNum, subDevNum, "helloworld")){
    		   printk(KERN_INFO "register_chrdev_region ok \n");
    	 }
    	 else {
    		 printk(KERN_INFO "register_chrdev_region error n");
    		 return ERROR;
    	 }
    	 printk(KERN_INFO " hello driver init \n");
    	 gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
    	 gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
       
    	 gFile->open = hello_open;
       
    	 gFile->read = hello_read;
    	 gFile->write = hello_write;
    	
    	 gFile->owner = THIS_MODULE;
    	  
    	 cdev_init(gDev, gFile);
    	   
    	 cdev_add(gDev, devNum, 1);
    		
    	 return 0;
    
    }
    void __exit hello_exit(void)
    {
    	 printk(KERN_INFO " hello driver exit \n");
    	 
    	 cdev_del(gDev);
    	  
    	 kfree(gFile);
    	   
    	 kfree(gDev);
    	
    	 unregister_chrdev_region(devNum, subDevNum);
    		
    	 return;
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    MODULE_LICENSE("GPL");
    

    在加载完成内核驱动后,下面就是写用户空间的程序并调用这个驱动了。
    废话不多说直接上代码:
    write.c

    #include <fcntl.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/select.h>
    
    #define DATA_NUM 64
    
    int main(int argc,char *argv[]){
    	int fd,i;
    	int r_len,w_len;
    	fd_set fdset;
    	char buf[DATA_NUM] = "hello world";
    	memset(buf,0,sizeof(buf));
    	fd = open("/dev/hello",O_RDWR);
    	//printf("%d\n",fd);
    
    	if(-1 == fd){
    		perror("open file error\n");
    		return -1;
    	}
    	else{
    		printf("open successe\n");
    	}
    	w_len = write(fd,buf,DATA_NUM);
    	if(-1 == w_len){
    		perror("write_error\n");
    		return -1;
    	}
    	printf("write_length = %d \n",w_len);
    	close(fd);
    	return 0;
    }
    

    read.c

    #include <fcntl.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/select.h>
    
    #define DATA_NUM 64
    
    int main(int argc,char *argv[]){
    	int fd,i;
    	int r_len,w_len;
    	fd_set fdset;
    	char buf[DATA_NUM];
    	memset(buf,0,sizeof(buf));
    	fd = open("/dev/hello",O_RDWR);
    	if(-1 == fd){
    		perror("open file error\n");
    		return -1;
    	}
    	else{
    		printf("open successe\n");
    	}
    	r_len = read(fd,buf,DATA_NUM);
    	if(-1 == r_len){
    		perror("read_error");
    		return -1;
    	}
    	printf("read_length = %d\n", r_len);
    	printf("%s\n",buf);
    	close(fd);
    	return 0;
    }
    

    解释下:write.c是将用户态的字符数组buf[DATA_NUM],写入到内核空间。之后使用read.c将内核空间的字符数组读出来。

    这里自行编译执行下吧。

    参考:

    https://blog.csdn.net/tommy_wxie/article/details/17122923/

    展开全文
  • 【Linux】Linux的内核空间(低端内存、高端内存)

    万次阅读 多人点赞 2018-07-20 16:50:01
    内核也是程序,也应该具有自己的虚存空间,但是作为一种为用户程序服务的程序,内核空间有它自己的特点。   内核空间与用户空间的关系 在一个32位系统中,一个程序的虚拟空间最大可以是4GB,那么最直接的做法...
  • 对于进程来说,它既有内核空间(与其他进程共享),也有用户空间(进程私有私有)。不 管是内核空间还是用户空间,它们都处于虚拟地址空间。 内核空间和用户空间交换数据的方式有很多。用户空间发起的有系统调用、...
  • linux进程用户内存空间和内核空间

    千次阅读 2020-06-15 20:02:52
    vmalloc和kmalloc区别 kmalloc对应于kfree,分配的内存处于3GB~high_memory之间,这段内核空间与物理内存的映射一一对应,可以分配连续的物理内存; vmalloc对应于vfree,分配的内存在VMALLOC_START~4GB之间,...
  • 操作系统中的用户空间和内核空间

    千次阅读 2020-11-27 09:41:54
    内核程序运行的空间就内核空间,即 kernel space。这两个空间是隔离的,即使用户程序崩溃了,内核也不受影响。 如图: 用户空间只能执行简单的运算,很多时候,还需要调用内核空间。如应用程序要读取某个...
  • linux驱动程序一般工作在内核空间,但也可以工作在用户空间。下面我们将详细解析,什么是内核空间,什么是用户空间,以及如何判断他们。 Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟...
  • Linux的用户空间与内核空间

    万次阅读 多人点赞 2018-09-03 10:51:23
    两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据可能不在内存中。用户空间的内存映射采用段页式,而内核空间有自己的规则;...
  • 笔记-操作系统-内存-内核空间与用户空间 1. 内核空间与用户空间 用户空间就是用户进程所在的内存区域,相对的,系统空间就是操作系统占据的内存区域。用户进程和系统进程的所有数据都在内存中。 上面的话叫做...
  • linux内核空间和用户空间认识和区别

    千次阅读 2017-03-04 20:44:16
    linux驱动程序一般工作在内核空间,但也可以工作在用户空间。下面我们将详细解析,什么是内核空间,什么是用户空间,以及如何判断他们。  Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的...
  • 内核空间与用户空间的通信方式

    千次阅读 2019-05-05 18:19:44
    下面总结了7种方式,主要对以前不是很熟悉的方式做了编程实现,以便加深印象。...B.put_user(x,ptr):在内核中被调用,将内核空间的变量x的数值保存到到用户空间指定地址处。 C.Copy_from_user()/copy_to_use...
  • Linux用户空间与内核空间内存映射

    千次阅读 2017-05-25 15:42:06
    Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据可能不在...
  • 用户空间地址和内核空间地址说明

    千次阅读 2018-03-02 15:01:33
     ● 内核编译后地址空间在什么范围内? ● 要对外设进行访问,I/O的地址空间又是什么样的?于是就有了这篇文章,从大概上把内存相关知识点介绍一下,减少同学们在驱动课时对内存的困惑先回答第一个问题。Linux最...
  • 内核空间和用户空间  现代操作系统采用虚拟存储器,对于32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问...
  • 摘要:Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据...
  • 用户空间和内核空间是什么?

    千次阅读 2019-03-30 09:00:00
    学习 Linux 时,经常可以看到两个词:User space(用户空间)和 Kernel space(内核空间)。 简单说,Kernel space 是 Linux 内核的运行空间,User space 是用户程序的运行空间。为了安全,它们是隔离的,即使用户的...
  • 关于linux内核空间与用户空间的理解

    万次阅读 多人点赞 2017-10-19 09:20:41
    简介现代计算机都有两种以上的运行模式(普通模式、特权模式),...应用程序不能直接操控硬件或者调用内核函数,需借助一系列接口函数申请让系统调用相关代码在内核空间运行,获取代码运行权限。Created with Raphaël
  • 要了解什么是用户态,什么是内核态,我们需要先了解什么是进程的用户空间和内核空间:Linux虚拟内存的大小为2^32(在32位的x86机器上),内核将这4G字节的空间分为两部分。最高的1G字节(从虚地址0xC0000000到0...
  • linux 用户空间和内核空间区别

    千次阅读 2018-01-05 18:33:12
    linux驱动程序一般工作在内核空间,但也可以工作在用户空间。下面我们将详细解析,什么是内核空间,什么是用户空间,以及如何判断他们。 Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟...
  • 如上图所说,**物理内存全部与内核空间相映射(物理内存是不是全被映射完了),那么用户空间映射到哪?** ![图片说明](https://img-ask.csdn.net/upload/201611/08/1478568677_50512.png) 比如上图中的text、data段...
  • 摘要:Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据...
  • 用户空间就是用户进程所在的内存区域,相对的,系统空间就是操作系统占据的内存区域。用户进程和系统进程的所有数据都在内存中。  是谁来划分内存空间的呢?在电脑开机之前,内存就是一块原始的物理内存。什么也...
  • 文章很长,建议收藏起来慢慢读!疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 经典图书:《Java高并发核心编程(卷1)》 面试必备 + 大厂必备 +涨薪必备 加尼恩...
  • 4.9 Linux64位内核地址空间分布图,各个关键宏的分布位置。
  • [Linux]理解用户空间与内核空间

    千次阅读 2017-10-25 14:33:34
    源文: ...这里的用户空间及内核空间对应于虚拟地址空间. 每个linux中的进程占用独立的虚拟空间. 在32位架构linux系统中, 用户空间至少对应3GB虚拟空间, 而内核空间
  • linux内存管理--用户空间和内核空间

    千次阅读 2018-08-09 10:29:24
    4G的进程地址空间被人为的分为两个部分--用户空间与内核空间。用户空间从0到3G(0xc0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间的虚拟地址。例外情况只有用户...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 500,493
精华内容 200,197
关键字:

内核空间

友情链接: epoch_user-4.17.rar