`

Linux系统调用及其实验(一)——内核态、用户态

 
阅读更多

简单来讲一个进程由于执行系统调用而开始执行内核代码,我们称该进程处于内核态中. 一个进程执行应用程序自身代码则称该进程处于用户态。
    intel x86 架构的 CPU 分为好几个运行级别,从 0--3 , 0 为最高级别, 3 为最低级别
    针对不同的级别,有很多的限制,比如说传统的 in ,out 指令,就是端口的输入输出指令,在 0 级下是可以用的,但在 3 级下就不能用,你用就产生陷阱,告诉你出错了,当然限制还有很多了,不只是这一点
    操作系统下是利用这个特点,当操作系统自己的代码运行时, CPU 就切成 0 级,当用户的程序运行是就只让它在 3 级运行,这样如果用户的程序想做什么破坏系统的事情的话,也没办法做到
    当然,低级别的程序是没法把自己升到高级别的,也就是说 用户程序运行在 3 级,他想把自己变成 0 级自己是做不到的,除非是操作系统帮忙,利用这个特性,操作系统就可以控制所有的程序的运行,确保系统的安全了. 平时把操作系统运行时的级别就叫内核态(因为是操作系统内核运行时的状态),而且普通用户程序运行时的那个级别叫用户态...
    当操作系统刚引导时, CPU 处于实模式,这时就相当于是 0 级,于是操作系统就自动得到最高权限,然后切到保护模式时就是 0 级,这时操作系统就占了先机,成为了最高级别的运行者,由于你的程序都是由操作系统来加载的,所以当它把你加载上来后,就把你的运行状态设为 3 级,即最低级,然后才让你运行,所以没办法,你只能在最低级运行了,因为没办法把自己从低级上升到高级, 这就是操作系统在 内核 态可以管理用户程序,杀死用户程序的原因.
 
 
 
1. 用户态和内核态的概念区别
    究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子:
1)例子
   void testfork(){
       if(0 = = fork()){
           printf(“create new process success!\n”);
       }
       printf(“testfork ok\n”);
   }
    这段代码很简单,从功能的角度来看,就是实际执行了一个fork(),生成一个新的进程,从逻辑的角度看,就是判断了如果fork()返回的是0则打印相关语句,然后函数最后再打印一句表示执行完整个testfork()函数。代码的执行逻辑和功能上看就是如此简单,一共四行代码,从上到下一句一句执行而已,完全看不出来哪里有体现出用户态和进程态的概念。
如果说前面两种是静态观察的角度看的话,我们还可以从动态的角度来看这段代码,即它被转换成CPU执行的指令后加载执行的过程,这时这段程序就是一个动态执行的指令序列。而究竟加载了哪些代码,如何加载就是和操作系统密切相关了。

内核态和用户态区别
    当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。
    A、用系统调用时进入核心态。Linux对硬件的操作只能在核心态,这可以通过写驱动程序来控制。在用户态操作硬件会造成core    dump.  
    B、要注意区分系统调用和一般的函数。系统调用由内核提供,如read()、write()、open()等。而一般的函数由软件包中的函数库提供,如sin()、cos()等。在语法上两者没有区别。  
    C、一般情况:系统调用运行在核心态,函数运行在用户态。但也有一些函数在内部使用了系统调用(如fopen),这样的函数在调用系统调用是进入核心态,其他时候运行在用户态。
大概是    当用户程序调用系统的API时,就产生中断,进入内核态的API,处理完成后,用中断再退出,返回用户态的调用函数。  
    user    api    -->    interrupt    -->    kernel    api    -->    interrupt
 
2)特权级
    熟悉Unix/Linux系统的人都知道,fork的工作实际上是以系统调用的方式完成相应功能的,具体的工作是由sys_fork负责实施。其实无论是不是Unix或者Linux,对于任何操作系统来说,创建一个新的进程都是属于核心功能,因为它要做很多底层细致地工作,消耗系统的物理资源,比如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录页表等等,这些显然不能随便让哪个程序就能去做,于是就自然引出特权级别的概念,显然,最关键性的权力必须由高特权级的程序来执行,这样才可以做到集中管理,减少有限资源的访问和使用冲突。
    特权级显然是非常有效的管理和控制程序执行的手段,因此在硬件上对特权级做了很多支持,就Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有CPL、DPL和RPL,这里不再过多阐述。硬件已经提供了一套特权级使用的相关机制,软件自然就是好好利用的问题,这属于操作系统要做的事情,对于Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在0级特权级的指令具有了CPU能提供的最高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。
 
3)用户态和内核态
    现在我们从特权级的调度来理解用户态和内核态就比较好理解了,当程序运行在3级特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运行在0级特权级上时,就可以称之为运行在内核态。
    虽然用户态下和内核态下工作的程序有很多差别,但最重要的差别就在于特权级的不同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序,比如上面例子中的testfork()就不能直接调用sys_fork(),因为前者是工作在用户态,属于用户态程序,而sys_fork()是工作在内核态,属于内核态程序。
    当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,比如testfork()最初运行在用户态进程下,当它调用fork()最终触发sys_fork()的执行时,就切换到了内核态。
 
2. 用户态和内核态的转换
    1)用户态切换到内核态的3种方式
        a. 系统调用
    这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
        b. 异常
    当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
        c. 外围设备的中断
    当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
 
    这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

 

 

参考文档:

http://hi.baidu.com/zjsxycli/item/93e92a11a569214a3a176ea5

分享到:
评论

相关推荐

    操作系统实验指导——基于Linux内核(第2版)

    操作系统实验指导——基于Linux内核(第2版) 在深入探讨操作系统实验之前,我们首先要理解操作系统的基本概念。操作系统是计算机系统的核心,它管理硬件资源,为应用程序提供服务,并协调计算机的各项活动。Linux...

    操作系统实验一熟悉实验环境——Linux

    操作系统实验一的主要目标是熟悉Linux操作系统环境,包括安装配置、基本操作、文件系统管理以及文本编辑。这个实验将涵盖以下几个核心知识点: 1. **Linux操作系统安装与配置**:实验要求参与者掌握Linux操作系统的...

    linux系统调用可视化 操作系统课程设计 实验报告

    【操作系统课程设计——Linux系统调用可视化实验报告】 在操作系统的学习过程中,系统调用是连接用户空间和内核空间的重要桥梁。本实验旨在通过可视化Linux系统调用的过程,加深对系统调用的理解,同时锻炼动手实践...

    Linux内核实验报告——实验4.docx

    在本篇Linux内核实验报告——实验4中,主要涵盖了两个关键知识点:动态模块设计和proc文件系统。实验目的是让学生理解和掌握Linux内核模块的编写,以及如何通过proc文件系统来与用户空间交互。 首先,实验A部分涉及...

    疯狂内核之——内核初始化

    - **内核引导程序**: 引导程序是计算机启动过程中的第一步,负责加载操作系统内核到内存中并执行。对于Linux来说,常见的引导程序有GRUB和LILO等。 #### 2. 内核映像的形成 - **MakeFile预备知识**: - **Makefile...

    Linux原理与应用——专题3:中断与系统调用.ppt

    1. 用户态到内核态的切换:用户程序执行系统调用指令后,CPU进入陷阱模式,由用户态转换为内核态。 2. 系统调用号解析:处理器将系统调用号放入特定寄存器,内核根据这个号码调用相应的处理函数。 3. 执行服务:内核...

    操作系统实验作业——linux系统调用学习,重定向、管道、多进程、多线程编程技术实现.zip

    Linux系统调用是用户程序与操作系统内核交互的主要途径。它们提供了访问操作系统功能的接口,如创建进程、打开文件、读写文件等。通过系统调用,程序员可以实现高级的程序功能。常见的系统调用包括`fork()`用于创建...

    南大linux课件——Linux内核

    6. **系统调用接口**:内核通过系统调用接口提供服务,允许用户空间的程序请求内核执行特定操作,如读写文件、创建进程等。 学习“Linux内核”时,你需要掌握以下几个关键知识点: 1. **内核编译与配置**:了解...

    Linux 系统调用学习笔记

    Linux系统调用是操作系统提供给用户空间程序与内核交互的一种机制,它是操作系统核心功能的直接接口。在Linux中,当用户程序需要执行如文件操作、进程管理、网络通信等低级任务时,就需要通过系统调用来实现。这是...

    Linux内核系统调用开发指南

    Linux® 系统调用 —— ...不过您清楚系统调用是如何在用户空间和内核之间执行的吗?本文将探究 Linux 系统调用接口(SCI),学习如何添加新的系统调用(以及实现这种功能的其他方法),并介绍与 SCI 有关的一些工具。

    疯狂内核之——Linux预备知识.pdf

    在Linux系统中,当程序从用户态切换到内核态时,会发生堆栈切换。这是由于用户态和内核态拥有不同的权限级别,因此它们各自的堆栈也必须分开,以确保安全性。具体来说,当发生系统调用或异常时,处理器会自动保存...

    Linux驱动初级——内核中断

    ### Linux内核中断详解 #### 一、中断基础 ...通过深入了解Linux内核中断和异常处理的原理及其实现细节,开发者可以更好地理解Linux操作系统是如何管理和响应各种硬件事件的,这对于编写高效的驱动程序至关重要。

    深度探索Linux操作系统——系统构建和原理解析

    《深度探索Linux操作系统——系统构建和原理解析》是一本专为那些希望深入了解Linux操作系统内核和系统构建的读者量身打造的专业书籍。它详细阐述了Linux操作系统的内部工作机制,涵盖了从内核设计到系统服务的...

    边干边学——LINUX内核指导

    在IT领域,Linux内核是操作系统的核心部分,它负责管理硬件资源、提供系统调用接口以及维护系统的稳定性与安全性。"边干边学——LINUX内核指导"这个标题暗示了这是一份实用型的学习资料,旨在帮助读者通过实践来理解...

    19——Linux的系统调用与文件IO(二)

    本主题将深入探讨这两个重要领域,特别是针对"19——Linux的系统调用与文件IO(二)"这一视频教程内容进行详细阐述。 首先,让我们理解什么是系统调用。系统调用是用户程序与操作系统内核进行通信的唯一合法方式,它...

    Linux下系统调用的设计及其局限性.pdf

    Linux下的系统调用是操作系统与用户程序之间的重要接口,它允许用户空间的应用程序请求操作系统内核执行特定的任务,如管理文件、创建进程、网络通信等。本文将详细探讨Linux系统调用的设计、实现方法以及其局限性。...

    西南交通大学2020届操作系统实验1——7

    通过本实验,了解Linux系统的组织和行为,观察各种存储系统状态信息的内核变量;熟悉这些结构与信息。 实验2 软中断通信实验 ①本实验要求学生了解什么是信号,掌握软中断的基本原理;掌握中断信号的使用、进程的创建...

Global site tag (gtag.js) - Google Analytics