linux c程序中内核态与用户态内存存储问题

 Unix/Linux的体系架构

  如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核)。内核从本质上看是一种软件——控制计算机的硬件资源,并提供上层应用程序运行的环境。用户态即上层应用程序的活动空间,应用程序的执行必须依托于内核提供的资源,包括CPU资源、存储资源、I/O资源等。为了使上层应用能够访问到这些资源,内核必须为上层应用提供访问的接口:即系统调用。

  系统调用是操作系统的最小功能单位,这些系统调用根据不同的应用场景可以进行扩展和裁剪,现在各种版本的Unix实现都提供了不同数量的系统调用,如Linux的不同版本提供了240-260个系统调用,FreeBSD大约提供了320个(reference:UNIX环境高级编程)。我们可以把系统调用看成是一种不能再化简的操作(类似于原子操作,但是不同概念),有人把它比作一个汉字的一个“笔画”,而一个“汉字”就代表一个上层应用,我觉得这个比喻非常贴切。因此,有时候如果要实现一个完整的汉字(给某个变量分配内存空间),就必须调用很多的系统调用。如果从实现者(程序员)的角度来看,这势必会加重程序员的负担,良好的程序设计方法是:重视上层的业务逻辑操作,而尽可能避免底层复杂的实现细节。库函数正是为了将程序员从复杂的细节中解脱出来而提出的一种有效方法。它实现对系统调用的封装,将简单的业务逻辑接口呈现给用户,方便用户调用,从这个角度上看,库函数就像是组成汉字的“偏旁”。这样的一种组成方式极大增强了程序设计的灵活性,对于简单的操作,我们可以直接调用系统调用来访问资源,如“人”,对于复杂操作,我们借助于库函数来实现,如“仁”。显然,这样的库函数依据不同的标准也可以有不同的实现版本,如ISO C 标准库,POSIX标准库等。

  Shell是一个特殊的应用程序,俗称命令行,本质上是一个命令解释器,它下通系统调用,上通各种应用,通常充当着一种“胶水”的角色,来连接各个小功能程序,让不同程序能够以一个清晰的接口协同工作,从而增强各个程序的功能。同时,Shell是可编程的,它可以执行符合Shell语法的文本,这样的文本称为Shell脚本,通常短短的几行Shell脚本就可以实现一个非常大的功能,原因就是这些Shell语句通常都对系统调用做了一层封装。为了方便用户和系统交互,一般,一个Shell对应一个终端,终端是一个硬件设备,呈现给用户的是一个图形化窗口。我们可以通过这个窗口输入或者输出文本。这个文本直接传递给shell进行分析解释,然后执行。

  总结一下,用户态的应用程序可以通过三种方式来访问内核态的资源:

1)系统调用

2)库函数

3)Shell脚本

  下图是对上图的一个细分结构,从这个图上可以更进一步对内核所做的事有一个“全景式”的印象。主要表现为:向下控制硬件资源,向内管理操作系统资源:包括进程的调度和管理、内存的管理、文件系统的管理、设备驱动程序的管理以及网络资源的管理,向上则向应用程序提供系统调用的接口。从整体上来看,整个操作系统分为两层:用户态和内核态,这种分层的架构极大地提高了资源管理的可扩展性和灵活性,而且方便用户对资源的调用和集中式的管理,带来一定的安全性。

二、用户态和内核态的切换

  因为操作系统的资源是有限的,如果访问资源的操作过多,必然会消耗过多的资源,而且如果不对这些操作加以区分,很可能造成资源访问的冲突。所以,为了减少有限资源的访问和使用冲突,Unix/Linux的设计哲学之一就是:对不同的操作赋予不同的执行等级,就是所谓特权的概念。简单说就是有多大能力做多大的事,与系统相关的一些特别关键的操作必须由最高特权的程序来完成。Intel的X86架构的CPU提供了0到3四个特权级,数字越小,特权越高,Linux操作系统中主要采用了0和3两个特权级,分别对应的就是内核态和用户态。运行于用户态的进程可以执行的操作和访问的资源都会受到极大的限制,而运行在内核态的进程则可以执行任何操作并且在资源的使用上没有限制。很多程序开始时运行于用户态,但在执行的过程中,一些操作需要在内核权限下才能执行,这就涉及到一个从用户态切换到内核态的过程。比如C函数库中的内存分配函数malloc(),它具体是使用sbrk()系统调用来分配内存,当malloc调用sbrk()的时候就涉及一次从用户态到内核态的切换,类似的函数还有printf(),调用的是wirte()系统调用来输出字符串,等等。

  到底在什么情况下会发生从用户态到内核态的切换,一般存在以下三种情况:

1)当然就是系统调用:原因如上的分析。

2)异常事件: 当CPU正在执行运行在用户态的程序时,突然发生某些预先不可知的异常事件,这个时候就会触发从当前用户态执行的进程转向内核态执行相关的异常事件,典型的如缺页异常。

3)外围设备的中断:当外围设备完成用户的请求操作后,会像CPU发出中断信号,此时,CPU就会暂停执行下一条即将要执行的指令,转而去执行中断信号对应的处理程序,如果先前执行的指令是在用户态下,则自然就发生从用户态到内核态的转换。

  注意:系统调用的本质其实也是中断,相对于外围设备的硬中断,这种中断称为软中断,这是操作系统为用户特别开放的一种中断,如Linux int 80h中断。所以,从触发方式和效果上来看,这三种切换方式是完全一样的,都相当于是执行了一个中断响应的过程。但是从触发的对象来看,系统调用是进程主动请求切换的,而异常和硬中断则是被动的。

三、总结

  本文仅是从宏观的角度去理解Linux用户态和内核态的设计,并没有去深究它们的具体实现方式。从实现上来看,必须要考虑到的一点我想就是性能问题,因为用户态和内核态之间的切换也会消耗大量资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457845.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程自动退出_C++基础 多线程笔记(一)

join & detachjoin和detach为最基本的用法,join可以使主线程(main函数)等待子线程(自定义的function_1函数)完成后再退出程序,而detach可以使子线程与主线程毫无关联的独立运行,当主线程执行…

WEB在线预览PDF

这是我在博客园发表的第一篇文章。以后会陆续把在线预览其他格式文档的解决方案发表出来。 解决思路:把pdf转换成html显示。 在线预览pdf我暂时了解3种解决方案,欢迎大家补充。 方案一: 利用pdf2html软件将PDF转换成HTML。 用法: PDF2HTML [选…

[算法]判断一个数是不是2的N次方

如果一个数是2^n,说明这个二进制里面只有一个1。除了1. a (10000)b a-1 (01111)b a&(a-1) 0。 如果一个数不是2^n, 说明它的二进制里含有多一个1。 a (1xxx100)b a-1(1xxx011)b 那么 a&(a-1)就是 (1xxx000)b, 而不会为0。 所以可…

VMware Ubuntu 全屏问题解决

在终端中输入: sudo apt install open-vm* 回车 自动解决

数组拼接时中间怎么加入空格_【题解二维数组】1123:图像相似度

1123:图像相似度时间限制: 1000 ms 内存限制: 65536 KB【题目描述】给出两幅相同大小的黑白图像(用0-1矩阵)表示,求它们的相似度。说明:若两幅图像在相同位置上的像素点颜色相同,则称它们在该位置具有相同的像素点。两幅图像的…

(旧)子数涵数·C语言——条件语句

首先,我们讲一下理论知识,在编程中有三种结构,分别是顺序结构、条件结构、循环结构,如果用流程图来表示的话就是: 那么在C语言中,如何灵活运用这三种结构呢?这就需要用到控制语句了。 而条件语句…

apache.commons.lang.StringUtils 使用心得

apache.commons.lang.StringUtils 使用心得 转载于:https://www.cnblogs.com/qinglizlp/p/5549687.html

python哪个版本支持xp_windows支持哪个版本的python

Windows操作系统支持Python的Python2版本和Python3版本,下载安装时要根据windows的操作系统来选择对应的Python安装包,否则将不能安装成功。 Python是跨平台的,免费开源的一门计算机编程语言。是一种面向对象的动态类型语言,最初被…

Ubuntu 键盘错位解决 更改键盘布局

原因是键盘布局不能适应键盘 解绝方法:更改键盘布局 一般改为标准104键盘就行 在终端输入 sudo dpkg-reconfigure keyboard-configuration 选择 标准104键盘 然后一直回车就行

【No.1 Ionic】基础环境配置

Node 安装git clone https://github.com/nodejs/node cd node ./configure make sudo make install node -v npm -vnpm设置淘宝镜像npm config set registry https://registry.npm.taobao.org npm config set disturl https://npm.taobao.org/distIOS Simulatorsudo npm instal…

识别操作系统

使用p0f进行操作系统探测 p0f是一款被动探测工具,通过分析网络数据包来判断操作系统类型。目前最新版本为3.06b。同时p0f在网络分析方面功能强大,可以用它来分析NAT、负载均衡、应用代理等。 p0f的命令参数很简单,基本说明如下: l…

常用RGB颜色表

转载于:https://www.cnblogs.com/Itwonderful/p/5550800.html

python中seek函数的用法_在Python中操作文件之seek()方法的使用教程

seek()方法在偏移设定该文件的当前位置。参数是可选的,默认为0,这意味着绝对的文件定位,它的值如果是1,这意味着寻求相对于当前位置,2表示相对于文件的末尾。 没有返回值。需要注意的是,如果该文件被打开或…

WPF中Grid实现网格,表格样式通用类(转)

/// <summary> /// 给Grid添加边框线 /// </summary> /// <param name"grid"></param> public static void InsertFrameForGrid(Grid grid) { var rowcon grid.RowDefinitions.Count; var clcon grid.ColumnDefinitions.Count; for (var i…

VS2017 安装 QT5.9

VS2017专业版使用最新版Qt5.9.2教程&#xff08;最新教材&#xff09; 目录 VS2017专业版使用最新版Qt5.9.2教程&#xff08;最新教材&#xff09; 运行环境&#xff1a; 1.安装Qt5.9.2 2.安装Qt5.9与VS2017之间的插件: 3.配置Qt VS Tool的环境. 4.设置创建的Qt的项目的属…

异步与并行~ReaderWriterLockSlim实现的共享锁和互斥锁

返回目录 在System.Threading.Tasks命名空间下&#xff0c;使用ReaderWriterLockSlim对象来实现多线程并发时的锁管理&#xff0c;它比lock来说&#xff0c;性能更好&#xff0c;也并合理&#xff0c;我们都知道lock可以对代码块进行锁定&#xff0c;当多线程共同访问代码时&am…

linux ssh yum升级_Linux 运维必备的 13 款实用工具,拿好了

作者丨Erstickthttp://blog.51cto.com/13740508/2114819本文介绍几款 Linux 运维比较实用的工具&#xff0c;希望对 Linux 运维人员有所帮助。1. 查看进程占用带宽情况 - NethogsNethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽。下载&#xff1a;htt…

iOS应用如何支持IPV6

本文转自 http://www.code4app.com/forum.php?modviewthread&tid8427&highlightipv6 果然是苹果打个哈欠&#xff0c;iOS行业内就得起一次风暴呀。自从5月初Apple明文规定所有开发者在6月1号以后提交新版本需要支持IPV6-Only的网络&#xff0c;大家便开始热火朝天的研…

SQL Server -- SQLserver 存储过程执行错误记录到表

SQLserver 存储过程执行错误记录到表 From: http://blog.csdn.net/leshami/article/details/51333650 对于在执行存储过程中碰到的一些错误&#xff0c;如果未及时捕获或者说传递给前端应用程序来&#xff0c;在这样的情形下&#xff0c;故障的排查显得尤为困难。基于此&…

opencv python教程简书_OpenCV-Python系列二:常用的图像属性

对于图像&#xff0c;我们经常需要知道关于图像的特殊属性&#xff0c;比如宽度&#xff0c;高度&#xff0c;面积&#xff0c;像素点数目等等&#xff0c;那么在opencv-python中&#xff0c;这些信息如何获取呢&#xff1f; 本文结构&#xff1a; 1.基本图像属性 2. 对于openc…