Linux内核入门(一)——小白学ARM
前言
小白之前一直跟着正点原子的教程学Linux嵌入式驱动开发,但总觉得少了点什么,现在回头来看,发现是对LINUX内核的一些基础知识缺乏了解。
例如说,教程里教你移植内核,教你写驱动,教你并发与竞争,但是,缺少一个整体框架,就容易学的云里雾里,所以小白觉得,学之前,还是得学一下LINUX的一些知识。
LINUX的前世今生
“众所周知的,Linux 的核心原型是 1991 年由托瓦兹(Linus Torvalds)写出来的,但是托瓦兹为何可以写出 Linux 这个操作系统? 为什么他要选择 386的计算机来开发?为什举 Linux 的发展可以这举迅速?又为什么 Linux 是免费的? 以及目前为何有这举多的 Linux 版本(distributions)呢?”——《鸟哥的Linux私房菜》
在《鸟哥的Linux私房菜》这本书的第1章就详细介绍了Linux的发展由来,务必要看这本书,知道的Linux的历史,对以后学习会有很大帮助。
这本书的作者——鸟哥,原名蔡德明,台湾省人,其实国内最早兴起研究Linux就是在台湾那边。
LINUX系统整体结构
Linux作为一个操作系统,其内部结构是怎么样的?
虽然我们不会去设计Linux系统,但了解其内部结构,对今后学习文件系统、进程管理、驱动开发等都有很大帮助。
如上图所示,Linux这套系统是怎样工作的呢?
内核提供一系列具备预定功能的多内核函数,通过一组称为系统调用(system call)的接口呈现给用户。最上层就是用户的应用软件,用户运行该软件,系统调用就会把应用程序的请求传给内核,内核调用相应的的内核函数完成所需的处理,将处理结果返回给应用程序。
上述过程,又可以描述为——从用户态切换至内核态,内核处理完成后,又回到用户态。
LINUX内核中的各模块功能
1.文件系统
在linux操作系统中,我们经常听到“一切皆文件”,事实上也确实如此——我们要操作开发板上的LED灯,写驱动时就需要像操作文件一样:open、write、close。
linux与其他操作系统不同,几乎所有的操作都基于文件系统接口的处理,
这里就不得不提到 “/proc” ,在专业笔试或面试时,经常会出现这个概念。
Linux系统上的/proc目录是一种文件系统,即proc文件系统。与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统(VFS virtual File System)),存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。
通过/proc文件系统可以访问linux内核的数据和参数,这两个功能在调试时非常有效
直白点说:/proc目录就是内核文件系统的实体,我们可以通过访问该目录下相应的文件,来窥探系统的运行状态,所以该目录对开发人员十分有用,后期需要深入学习。
详细讲解链接: /proc详解.
2.内存管理模块
内存管理是一个复杂的东西,涉及到内存分配、回收等知识,很是庞杂,这里只做粗浅了解。
由于从物理内存读写数据比从硬盘快的多,我们自然希望内存越大越好,内存越大,能运行的程序就越多,越复杂。这就引出了物理内存与虚拟内存的概念。
物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space)。
linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。
通俗一点讲:Linux怕自己的物理内存不够,跑去硬盘那边划一块空间,充当内存使用,因为磁盘嘛,读写很慢,当然不会像读写物理内存那样去读写这块逻辑内存。而是——不时地将物理内存中不常用的数据存放到这块逻辑内存(swap space)中,等需要用的时候,再取回到物理内存中。
那么,这个内存里,它存什么呢?
在内存里游荡的是一条条活生生的进程(进程:系统中正在运行的一个应用程序),它们可以被创建、阻塞、运行、杀死。进程占用的内存,又被分为:
- 栈区:存放函数的参数,局部变量
- 堆区:提供程序员动态申请的内存空间
- 全局(静态)区:
.data段:初始化不为0的全局变量和静态变量,const常量
.bss段:初始化为0的全局变量,静态变量 - 程序代码区:存放函数体的二进制代码和字符串常量
我们可以在Linux中使用命令:
free
来查看内存的使用状况,如图所示:
上面的数据不怎么直观,我写到了EXCEL里,可以看到:
total = used + free + buff/cache
available = free + buffer/cache
实际算下来,available 理论值比实际显示的值要偏大,不清楚为什么,有资料说会有偏差
- total:物理内存的总大小。
- used:已经使用的物理内存多小。
- free:空闲的物理内存值。
- shared:多个进程共享的内存值。
- buffers/cached:磁盘缓存的大小。
前面几个都很好理解,这个buffers/cached是做什么的呢?
历史上,buffer和cached是两独立的磁盘缓存,linux 内核 2.4 中才将它们统一。
buffer:中文一般翻译为 “缓冲区”,每个缓冲区与一个磁盘上的块对应,它相当于是磁盘块在内存中的表示。
cached:中文一般翻译为 “页高速缓存”,是通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。
available 就比较有意思了,它是从应用程序的角度看到的可用内存数量。Linux 内核为了提升磁盘操作的性能,会消耗一部分内存去缓存磁盘数据,就是我们介绍的 buffer 和 cache。所以对于内核来说,buffer 和 cache 都属于已经被使用的内存。当应用程序需要内存时,如果没有足够的 free 内存可以用,内核就会从 buffer 和 cache 中回收内存来满足应用程序的请求。
3.进程管理模块&进程间通信模块
为了方便内核管理各个进程,每个进程都由一个进程描述符(process descriptor)表示,这个描述符包含了有关进程的当前状态信息。详见链接: 进程与进程描述符(process descriptor).
说是一个“描述符”,其实是个很复杂的结构体——task_struct
这个结构体里,有很多成员,感兴趣可以去深入了解
这里说几个常见的成员:
state字段:
用来表示当前进程状态,考点:linux进程有几种基本状态?
答:5种,即R、S、D、T、Z
PID字段:
是进程的身份证号,也是我们常看到的一个进程信息。
进程间通信又是一大考点:
几种进程间通信方式:
- 管道 pipe
- 消息队列 MessageQueue
- 共享内存 SharedMemory
- 信号量 Semaphore
- 信号 sinal
- 套接字 Socket
此外还涉及到:进程间的并发与竞争,后面会写一些专门讲进程的内容,这里不做展开。
4.驱动管理模块
Linux 内核中有大量代码都在设备驱动程序中,它们能够运转特定的硬件设备。Linux 源码树提供了一个驱动程序子目录,这个目录又进一步划分为各种支持设备,例如 Bluetooth、I2C、serial 等。设备驱动程序的代码可以在 ./linux/drivers 中找到。