现代操作系统——Linux架构与学习
Posted ThXe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了现代操作系统——Linux架构与学习相关的知识,希望对你有一定的参考价值。
小白的疑惑
在我决定从事嵌入式(应用层)方面的工作时,我查询了大量资料该如何学习,几乎所有观点不约而同的都指向了学习好Linux,大部分工作都是在Linux环境下来进行工作的。于是我雄心勃勃的去下载Linux,可能大部分人的经历都与我类似,下载虚拟机、学习指令、学习文件操作等API。但是我在学习的过程中,总是觉得不得劲。不知道自己学Linux到底是在学什么?仿佛是盲人摸象,越学越迷糊。
初窥门径
前期花了十分多的精力学习了各种函数、线程进程的概念。总是晕晕乎乎,直到后面接触到一种学习方法,框架式学习法,使用框架式学习法后我犹如醍醐灌顶,瞬间有了学习的欲望自己也不茫然了。为了帮助更多的人,所以 我把这种学习方法来分享给大家,帮助更多不知道Linux该如何学习的人,能够踏入Linux的大门。
所谓框架式学习,就是自顶向下的学习,先从全局来把握Linux,下面给出一张图来简要说明
从上面的图中不难看出,Linux位于硬件上层与系统API下层。而我们常说的C\\C++开发屏蔽了硬件层,你无须认识各类硬件,也能自如的使用这些硬件。这是因为Linux为我们封装好了使用这些硬件的方法。而更上层的应用框架,也就是我们后续学习的高端编程,都是基于这之上来搭建的。学习框架可以帮我们快速的搭建一个可用的应用。但是缺点是我们很难知道底层的一些细节,也就是不断调用写好的函数,而不知所以然。值得注意的是,越下层的东西原理越固定,也就是迭代的速度越慢。而越上层的应用,则日新月异,我们时常会感受到,学习Linux做不出什么东西来,这是十分正常的。想要短时间实现应用,就该学习一些框架。
举个例子吧,想要以linux为操作系统做个人脸识别机器人,还能语音播报,可以用window控制,可以存储视频数据。
考虑一个最小子系统,我们需要用一个摄像头来当眼睛,需要一个语音模块来当嘴巴,需要一颗主控板上面跑着Linux操作系统来当作大脑(可以用树莓派)。我们可以用Opencv来做图像处理,只需要调用几个函数几百行代码就能实现一个简单的人脸识别,可以使用FFMPEG来做语音识别和音频处理,如果只是简单的语音播报功能学习起来也十分的快。有了这些功能,组织起来,你的下位机也就是机器人就已经制作完毕了。穿插着学习一下线程和进程的知识,简单的组装一下他就可以用几个Linux命实现相应的功能。针对性的去学习相应的函数,其它用不上的一概不学的情况下。这大概只需要花费十来个小时,
只有下位机显然是不够的,如果我们想要用个PC机来作为上位机控制这个机器人呢?那我们需要有个前端界面,可以是用Qt,Qt可以拖拽生成界面,假设不考虑美观性,只实现获取摄像头、开始识别、语音播报两个功能。那PC机需要和树莓派进行通信,我们需要学习Socket网络编程,如果需要存储数据可以学习Sqlite。同样的广度优先学习,只学一个皮毛调用相应的API即可。这不会花费特别多的时间,现代框架拥有的强大功能可以帮助你快速搭建起一个这样的体系。
让我们回头看看我们做了一个什么东西,是不是和我们现在用的产品已经十分类似了,完全可以当作一个毕设的级别的小Demo。然鹅做一个这样东西的时间,其实不需要花费太久,只要你知道有这个函数,知道环境怎么搭建,你不需要知道太多的底层知识,只需要知道个大概流程。长则一个月短则几周,完全可以独立的开发出一个这样的东西(照猫画虎)很多代码网络上都有了,跟着视频去做即可。这也是自顶向下学习的第一步,从应用层进行学习。
渐入佳境
完成这样的一个机器人,我们看似用了很多技术,那么这些技术究竟从何而来?我们调用的API函数究竟是怎么实现的?框架又是怎么搭建的?为什么短短几行代码就能实现如此强大的功能?如果你有强烈的求知欲,而不满足只是在巨人的肩膀上来实现这样一个应用。让我们接着往下走,这里假设你已经有了C语言的基础,看看Linux到底帮助我们完成了什么工作。
首先我们回忆一下我们开机时候的场景,第一步按下电源键,屏幕开始显示,恭喜你,已经成功开机。让我们停下来,看看具体发生了什么,为什么按下开机键就可以有如此大的威力?开机键按下,它会产生一个电流,一切的一切都可以从这开始。电流进入一个名叫bootloder(一个写在单片机里的引导程序)的身体,bootloder被电流唤醒,开始引导Linux内核(Kernel):喂喂喂!开始工作了,Kernel按照定义开机的步骤,点亮屏幕、输出一些信息、连接鼠标…挂载文件系统。启动成功,欢迎用户。这时候你可以自由的使用Linux系统,可以敲一些指令。
而那些屏幕、鼠标、键盘称之为IO设备,是人和机器沟通的工具。我们可以有一些输入,然后得到一些输出。Linux又是怎么来调用这些硬件的呢?这些硬件有不同的原理图,但是我们可以同一用一个USB接口(或者蓝牙之类的)来识别,然后使用,这又是怎么实现的呢?答案是驱动程序,比如一个鼠标,它的产家根据它独有的芯片来设计一个驱动程序,然后Linux加载这个驱动程序,用户就可以使用这个鼠标了。大部分时候用户都会被屏蔽这个过程,有时候操作系统缺少驱动时,会提醒你安装,或者你需要自己到官网来下载一些驱动程序…
这时候我们大致明白什么是 BootLoader 引导程序,什么是 Linux 操作系统内核 Kernel,什么是文件系统,不同硬件和Linux是怎么进行交互的,怎么使用这些硬件的。
让我们回到最初的问题,框架是怎么来的,框架你也可以认为是一种应用,而它调用的就是最基础的Linux提供的API,像是我们学习的fopen,fwrite的函数。驱动程序则赋予fopen真正的意义,因为外设也是一种文件。那么框架通过抽象出大部分的流程,封装好繁琐的步骤,留下一个薄薄的调用接口,可以帮助我们实现各种强大的功能。
总结
上文我简单的带大家去识别了究竟一个实际的产品的背后,涉及到的是什么东西。它到底和我们学习的Linux、C语言有什么关系。可能大部分使用单纯的用C或者Linux我们做不成什么有用的产品,这是因为我们没有接触一些现在流行的框架,我鼓励大家去接触到底该怎么开发一个产品,你大可以根据我上面描述的制作机器人的步骤去一步一步学习。当然你需要善于使用搜索引擎,好歹你现在知道该怎么去做了,你脑海里面有了清晰的计划,只要一个个问题去解决,终究是可以实现一个有用的产品。在这一步骤,大家可以不求甚解,面向需求编程,需求是什么,就去用什么,学习相应的内容,不要全学,用到什么学什么。可以复制黏贴的绝不自己手敲。大部分培训班干的就是这件事情。
但是完成了一个小项目后,我希望你能回过头来,静下心的去弄明白,这些东西到底是怎么实现的?它涉及到哪些我之前学习过的知识点?原理是什么?大师们是怎么解决这些难题的?其实所有的专业术语都是为了解决一些出现的难题,像TCP\\IP协议并非无中生有,网络的多层模型也是为了解决网络通信的难题。学校学习的知识,不会从应用出发,常常是自底向上,或者从中间往上走,让人云里雾里,稀里糊涂,好像学了又好像没学。实际不会用,理论学不懂,相信是绝大多数人迷茫的地方。所以在遇到一个新的知识时,不妨从另外一个角度来思考问题,这个知识,它能解决什么实际问题?这往往会为你打开一个新世界的大门,也可以帮助你将这个知识点领悟的更加深刻。我是一个爱编程的小白,今天的文章到这里就结束啦!期待和大家下次再见!
相关视频:https://www.bilibili.com/video/BV1HE411w7by?p=1&vd_source=d15a0ea5c86399d259f6febe12d6ea1a
Linux内核分析学习总结
一.Linux内核架构及概念模型
Linux操作系统是一种自由和开放源码的类UNIX操作系统。其符合POSIX,是一种支持多用户,多任务,多线程的现代操作系统。
GNU/Linux 层次结构如下图
其中Linux内核架构如图
可以看到,最下层是与体系结构及设备驱动相关的代码,中间层主要是进程管理,内存管理,文件系统模块及网络栈,最上层提供了为应用程序系统系统调用的接口。
前文说过,Linux支持多用户多任务。为了高效管理有效的计算机资源分配和防止可能的使用冲突及信息安全,Linux采用了对指令执行分级的机制,具体来说,CPU执行级别分为内核态和用户态。应用程序需要访问计算机资源等敏感操作时需要通过系统调用进入内核态实现相应功能。
二.中断
中断分类:
中断可分为如下几种:
硬件中断:
- 可屏蔽中断。硬件中断的一类,可通过在中断屏蔽寄存器中设定位掩码来关闭。
- 非可屏蔽中断。硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。典型例子是时钟中断。
软件中断:
- 陷入。是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态的子例程,它常被用作实现系统调用。
- 故障。通常来自当前指令内在缺陷,导致执行失败,可在修复后重新执行该指令。
中断处理过程:
1.CPU得到中断类型码后,进行保护断点,主要包括将状态寄存器压栈,保存当前代码段寄存器CS和程序计数器IP。
2.通过中断向量号查找中断向量表,找到中断处理程序地址,保存现场。执行中断处理程序
3.执行结束后恢复线场,恢复CS和IP。
三.进程管理
进程介绍:
进程是操作系统资源调度的单位,也是线程的容器。
Linux内核通过名为struct task_struct的结构体来描述进程,其包含了一个进程所需的所有信息。包括了进程状态,进程标识符,进程内核栈,线程描述符,进程标记进程优先级,进程地址空间,时间等信息。
进程调度及切换:
进程调度策略即从就绪队列中选择合适进程的策略方法。常用调度策略有SCHED_NORMAL、SCHED_FIFO、SCHED_RR、SCHED_BATCH。其中SCHED_NORMAL是用于普通进程的调度类,而SCHED_FIFO和SCHED_RR是用于实时进程的调度类,优先级高于SCHED_NORMAL。
进程切换:进程的切换即进程上下文的切换,包括用户地址空间,控制信息,和寄存器值。包括切换页全局目录和切换内核态堆栈和进程的CPU上下文两个步骤。切换成功的标志是寄存器从一个状态转换到另一个状态。
四.内存管理
Linux采用虚拟内存管理技术,进程初始化分配和操作都是基于虚拟地址,只有当进程需要实际访问内存资源的时候才会建立虚拟地址和物理地址的映射,调入物理内存页。
内核的内存管理单元实现虚拟地址和物理地址的转化。Linux进程可以划分为 5 个不同的内存区域,分别是:代码段、数据段、BSS
、堆、栈,内核管理这些区域的方式是,将这些内存区域抽象成vm_area_struct
的内存管理对象。
五.文件管理
虚拟文件系统是Linux内核的子系统之一,它为用户程序提供文件和文件系统操作的统一接口,屏蔽不同文件系统的差异和操作细节。借助VFS可以直接使用open()
、read()
、write()
这样的系统调用操作文件,而无须考虑具体的文件系统和实际的存储介质。
Linux为了实现这种VFS系统,采用面向对象的设计思路,主要抽象了四种对象类型:
- 超级块对象:代表一个已安装的文件系统。
- 索引节点对象:代表具体的文件。
- 目录项对象:代表一个目录项,是文件路径的一个组成部分。
- 文件对象:代表进程打开的文件。
每个对象都包含一组操作方法,用于操作相应的文件系统。
六.总结
感谢孟老师和李老师的教学与付出, 让我对linux操作系统的设计与实现理论有了初步的了解。通过学习《Linux操作系统分析》理论课及多次实验,我对linux的兴趣更深入了一步,受益匪浅。
以上是关于现代操作系统——Linux架构与学习的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核Linux 内核体系架构 ( 硬件层面 | 内核空间 | 用户空间 | 内核态与用户态切换 | 系统调用 | 体系结构抽象层 )