1)示例

void testfork()
{  if(0 = = fork()){  printf(“create new process success!\n”);  }printf(“testfork ok\n”);
}  

这段代码很简单,从功能的角度来看,就是实际执行了一个fork(),生成一个新的进程,从逻辑的角度看,就是判断了如果fork()返回的是则打印相关语句,然后函数最后再打印一句表示执行完整个testfork()函数。代码的行逻辑和功能上看就是如此简单,一共四行代码,从上到下一句一句执行而已。

2)特权级

如果说前面两种是静态观察的角度看的话,我们还可以从动态的角度来看这段代码,即它被转换成CPU执行的指令后加载执行的过程,这时这段程序就是一个动态执行的指令序列。而究竟加载了哪些代码,如何加载就是和操作系统密切相关了。

熟悉Unix/Linux系统的人都知道,fork的工作实际上是以系统调用的方式完成相应功能的,具体的工作是由sys_fork负责实施。其实无论是不是Unix或者Linux,对于任何操作系统来说,创建一个新的进程都是属于核心功能,因为它要做很多底层细致地工作,消耗系统的物理资源,比如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录页表等等,这些显然不能随便让哪个程序就能去做,于是就自然引出特权级别的概念,显然,最关键性的权力必须由高特权级的程序来执行,这样才可以做到集中管理,减少有限资源的访问和使用冲突。

特权级显然是非常有效的管理和控制程序执行的手段,因此在硬件上对特权级做了很多支持,就Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有 CPL、DPL和RPL。硬件已经提供了一套特权级使用的相关机制,软件自然就是好好利用的问题,这属于操作系统要做的事情,对于 Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在级特权级的指令具有了CPU能提供的最高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。

3)用户态和内核态

为什么用户态到内核态切换消耗大?
内核态和用户态有自己的内存映射,即自己的地址空间。
用户空间的应用程序,通过系统调用,进入内核空间。由内核代表该进程运行于内核空间,这就涉及到上下文的切换,用户空间和内核空间具有不同的地址映射,通用或专用的寄存器组,而用户空间的进程要传递很多变量、参数给内核,内核也要保存用户进程的一些寄存器、变量等,以便系统调用结束后回到用户空间继续执行。

所谓的“进程上下文”,就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈上的内容,当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。

现在我们从特权级的调度来理解用户态和内核态就比较好理解了,当程序运行在3级特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运行在级特权级上时,就可以称之为运行在内核态。

虽然用户态下和内核态下工作的程序有很多差别,但最重要的差别就在于特权级的不同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序,比如上面例子中的testfork()就不能直接调用 sys_fork(),因为前者是工作在用户态,属于用户态程序,而sys_fork()是工作在内核态,属于内核态程序。

当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,比如testfork()最初运行在用户态进程下,当它调用fork()最终触发 sys_fork()的执行时,就切换到了内核态。

4)用户态和内核态的转换

1.用户态切换到内核态的3种方式

a. 系统调用

这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。

b. 异常

当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。

c. 外围设备的中断

当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

2.具体的切换操作

从触发方式上看,可以认为存在前述3种不同的类型,但是从最终实际完成由用户态到内核态的切换操作上来说,涉及的关键步骤是完全一致的,没有任何区别,都相当于执行了一个中断响应的过程,因为系统调用实际上最终是中断机制实现的,而异常和中断的处理机制基本上也是一致的,关于它们的具体区别这里不再赘述。关于中断处理机制的细节和步骤这里也不做过多分析,涉及到由用户态切换到内核态的步骤主要包括:

[1] 从当前进程的描述符中提取其内核栈的ss0及esp0信息。

[2] 使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个 过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一 条指令。

[3] 将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始 执行中断处理程序,这时就转到了内核态的程序执行了。

Linux预备知识(三):系统调用-用户态/内核态相关推荐

  1. 42.Linux应用调试-初步制作系统调用(用户态-内核态)

    1首先来讲讲应用程序如何实现系统调用(用户态->内核态)? 我们以应用程序的write()函数为例: 1)首先用户态的write()函数会进入glibc库,里面会将write()转换为swi(S ...

  2. 5分钟搞懂用户态,内核态

    5分钟搞懂用户态,内核态 1. 什么是用户态,内核态 用户态就是提供应用程序运行的空间,为了使应用程序访问到内核管理的资源例如CPU,内存,I/O.内核必须提供一组通用的访问接口,这些接口就叫系统调用 ...

  3. 用户态/内核态、用户栈/内核栈

    一.用户态和内核态 内核态和用户态是操作系统的两种运行级别,用于区分不同程序的不同权利. 内核态就是拥有资源多的状态,或者说访问资源多的状态,也称为特权态.相对来说,用户态就是非特权态,访问的而资源将 ...

  4. 操作系统用户态内核态线程同步

    1.计算机系统中有两类程序:系统程序和应用程序.为了保证系统程序不被应用程序破坏,为计算机设置了两种状态:内核态和用户态. 内核态运行的程序可以访问计算机的任何资源不受限制. 用户态运行的程序可以直接 ...

  5. 【Linux 内核】Linux 内核体系架构 ( 硬件层面 | 内核空间 | 用户空间 | 内核态与用户态切换 | 系统调用 | 体系结构抽象层 )

    文章目录 一.Linux 内核体系架构 二.内核态与用户态切换 ( 系统调用层 ) 三.体系结构抽象层 一.Linux 内核体系架构 Linux 内核最初的源码不足一万行 , 当前的 Linux 内核 ...

  6. Linux预备知识(二):进程空间地划分-用户空间/内核空间

    查看机器上栈大小命令 ulimit -a 或者 ulimit -s 大小不固定,可以用 ulimit -s 进行调整,默认一般为 8M ** 栈区(stack sagment)**:由操作系统自动分配 ...

  7. linux 用户态 内核态 通信,procfs(从0开始,内核态和用户态通信charpter2)

    这篇博文将针对linux内核态与用户态通信方式中的procfs进行详细的学习. /proc主要存放内核的一些控制信息,所以这些信息大部分的逻辑位置位于内核控制的内存,在/proc下使用ls -l你会发 ...

  8. netlink实现与使用方法详解(用户态/内核态)

    一.什么是netlink Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口. 在Linux 内核中,使用netlink ...

  9. 理解用户态切换到内核态——内核态下有一个特殊的进程

    现在想想,从用户态进入到内核态,相当于一次进程切换--这就好像内核态下有一个特殊的进程. 我就把进入内核态后,理解为进入了一个特殊的进程,一切都忽然合理了,恍然大悟--所以所有用户态的task(称之为 ...

最新文章

  1. 高效程序员的 7 个共同特征
  2. SpringBoot-异常处理
  3. IDEA 中生成 MyBatis 逆向工程实践
  4. 要想挣大钱,就要懂一个基本
  5. python 从入门到实践_Python编程从入门到实践日记Day36
  6. 【CC评网】2013.第44周 把握每天的第一个小时
  7. 儿童python编程入门软件_一款儿童编程入门的理想工具——PythonTurtle
  8. 阿里云短信通道被人恶意刷了几万条短信,怎么办?(短信接口被盗刷系列3)
  9. JavaScript对象 、堆与栈
  10. python程序实现微信定时发送消息
  11. 产品读书《极简生活法则》
  12. 异常:Mapper method 'com.***.delByNumber' has an unsupported return type: class java.lang.String
  13. 学习AlphaGo理论知识-----part two
  14. 手机通讯录联系人怎么恢复 快速恢复的方法
  15. 如何在优麒麟操作系统安装QQ、微信
  16. oracle 雪峰,讨论 - 廖雪峰的官方网站
  17. 个税起征点升高----节省了多少?
  18. 红旗linux系统服务器,红旗linux11系统
  19. python只会基础能做什么?---你可以做一个文字游戏!
  20. 怎么从图片中提取文字?

热门文章

  1. influxdb tsm文件_利用InfluxDB+Grafana搭建Flink on YARN作业监控大屏
  2. python输出多个随机数_怎么用python输出随机数
  3. 如何将文件从安卓设备中拷贝到PC中
  4. 1.QT元对象系统、信号槽概述、宏Q_OBJECT
  5. Python知识点8——文件与异常
  6. HALCON双目重建
  7. java搜索文件夹中文件是否存在_java中判断文件文件夹是否存在的方法(附代码)...
  8. 制备pdms膜的方法_四川大学杨伟团队JMCC:实现柔性压阻式压力传感器的规模化制备...
  9. 在Heroku上扩展ipify服务
  10. 会话管理隐患与防御 总结