第三章--Linux内核及内核编程
第三章--Linux内核及内核编程
3.1 内核演变
--Unix、minix、GNU计划、POSIX标准、互联网
--具体版本变更参考网页https://kernelnewbies.org/Linux_5.8
--内核开发无计划,根据个人和企业的需要不断演变
https://www.linux.com/news/linux-weather-forecast/
https://kernelnewbies.org/Linux_5.8#Architectures
--嵌入式linux Montana Vista Linux Mentor Embedded Linux MeeGo、Tizen、Firefox OS等
--Android基于linux添加Binder、ashmem、wakelock、lowmemory killer、RAM_CONSOLE等
3.2 linux2.6以后的内核特点
--新调度器,早期采用O(1)算法、之后转CFS(完全公平调度)算法。3.14增加了新调度算法SCHED_DEADLINE实现EDF(Earliest Deadline First 最早截止期限优先)调度算法
--内核抢占:内核任务可以被抢占以提高系统实时性。极大增强系统用户交互行。但保留了部分不可抢占区间(中断上下文、软终端上下文和自旋锁锁住的区间、RTP补丁后中断和软中断线程化,自旋锁也被互斥体替换,linux内核变得支持硬实时)。
***************Linux24和26以后的内核在抢占上的区别.jpg*****************
--改进的线程模型,采用NPTL(Native POSIX Thread Library)模型,操作速度提高.更加遵循POSIX规范,未使用linuxthreads模型的线程管理,内核增加FUTEX(Fast Userspace Mutex)以减小多线程通信开销
--虚拟内存变化:融合r-map(反向映射)技术,改善虚拟内存在一定负载下的性能。2.4要回收页时,内核需遍历每个新城的PTE以判断该PTE是否与该页建立映射,是则取消。最后无PTE与该页关联才回收该页。2.6后r-map可通过页结构快速找到页面映射。
--文件系统: 增加日志文件系统支持,解决2.4的不足。
2.6后对扩展属性及POSIX标准访问控制的支持。可给指定文件在文件系统中嵌入元数据
ext2/ext3/ext4作为默认安装文件系统
Btrfs下一代linux文件系统。扩展性、数据一致性、多设备管理和针对SSD优化都优于ext4
--音频: ALSA取代OSS,ALSA支持USB音频和MIDI设备,支持全双工重放等功能
--总线、设备和驱动模型: 三者因存在联系实现对设备控制。总线是联系基础,通过一种总线类型将设备和驱动关联。总线类型中的match()函数用来匹配设备和驱动,当匹配操作完成后执行驱动的探针函数
--电源管理:支持高级配置和电源接口(ACPI),用于调整CPU在不同负载下工作于不同时钟频率以降低功耗。目前的PM有CPUFreq,CPUIdle、CPU热插拔、设备运行时PM、Linux系统挂起到内存和挂起到硬盘灯全套支持,在ARM上的支持也较完备。
--联网和IPSec:支持IPSec,删除内核内置的khttpd,支持NFSv4客户机/服务器,改进IPv6
--用户界面层: 重写帧缓冲/控制台层,人机界面层支持几乎所有接口设备(触摸屏到盲人设备、各种鼠标)。增加内存池、sysfs文件系统、内核模块.o变为.ko、驱动编译方式、模块使用计数、模块加载、卸载函数定义等
--3.0以后arm架构变更:FDT进入arm社区视野。时钟、DMA、pinmux、计时器刻度等优化改进,删除arch/arm/mach-xxx/include/mach头文件目录。3.7以后可支持多平台,即同一内核镜像运行于多家Soc公司多个芯片实现一个linux可适用于多个arm系统
3.3 linux组成
3.3.1 代码结构
driver和arch分开,驱动不包含板级信息,驱动跨平台,通用不分(fs,kernel,ipc,net等)与具体硬件(arch,drivers)剥离
3.3.2 linux 内核组成部分
**********************Linux内核的组成部分与关系*****
1.进程调度(SCHED)
使得访问CPU的多进程实现微观串行宏观并行,进程调度处于系统中心位置,内核中其他都依赖它,因为每个子系统都需要挂起或恢复进程
*********************Linux进程状态转换************
--睡眠分成可中断睡眠和不可中断睡眠,区别在于可中断睡眠收到信号会醒来
--完全处于Task_uniterrputible状态的进程甚至无法杀死,所以linux2.6.26之后内核也存在task_killable的状态,它就是task_wakekill|task_uninterrputible可以响应致命信号。
--内核使用task_struct结构体描述进程.包含进程内存资源、文件系统资源、文件资源、tty资源、信号处理等指针。linux的线程采用轻量级进程模型实现,用户空间通过pthread_create() 创建线程时,本质上内核只创建了一个task_struct,并将新task_struct的所有资源指针指向创建它的那个task_struct的指针
--多部分进城是用户扣减创建,当他们存在底层资源和硬件访问需求时,通过系统调用进入内核空间,有时,内核编程需要几个并发执行的人物,可以启动内核线程,这些线程没有用户空间,启动内核线程的函数为
kernel_thread(int (*fn)(void*), void* arg,unsigned long flags);
2.内存管理(MM)
--控制多个进程安全共享内存区域.
--CPU提供内存管理单元(MMU)时,内存管理对每个进程完成从虚拟内存到物理内存的转换。2.6引入对无MMU CPU的支持。
--32位linux处理器单个进程享有4GB内存,0-3是用户空间,3-4G内核空间.内核空间对常规内存、IO设备内存、高端内存处理方式不同.内核和用户空间界限可调整.在配置项kernel Features->Memory split下可以设置为2G或3G
************Linux进程地址空间*****************
--总体庞大,
---底层Buddy算法,管理每个页的占用情况,
---内核空间的slab以及用户空间的C库二次管理,
---提供页缓存支持,用内存来缓存磁盘
---per-BDI flusher线程用于刷回找那个的页缓存到磁盘
---Kswapd(交换进程)则是Linux中用于页面回收(file-backed的页和匿名页)的内核线程,采用最近最少用(LRU)算法回收内存
***************Linux内存管理***********
3.虚拟文件系统(VFS)
隐藏硬件细节,为所有设备提供统一接口,独立于各个具体文件系统,是文件系统的抽象,为上层的应用提供统一接口vfs_read(),vfs_write()等
4.网络接口(NET)
--网络协议负责实现所有可能的网络传输协议
--网络设备驱动负责与硬件通信,每种可能的硬件设备都有相应的驱动
--各种协议栈:Internet,unix can,nfc,bluetooth,wimax,irDA等,上层应用统一调用套接字接口
***************Linux网络体系结构.jpg***************
5.进程间通信(IPC)
通:信号量、共享内存、消息队列、管道、Unix域,实际应用趋向于使用Unix域套接字,而不是消息队列等消息机制,Android内核则使用Binder进程间通信
--进程调度与内存管理:相互依赖,多程序环境下,程序要运行,则必须为之创建进程,创建进程第一件事就是将程序和数据装入内存
--进程间通信与内存:进程间通信子系统要依赖内存管理支持共享内存通信机制,这种机制允许两个进程除了拥有自己的私有空间外,还能存取功能的内存区域.
--VFS和Net:VFS利用网络支持NFS,也利用内存管理支持RAMDISK设备
--内存管理与VFS:内存管理利用VFS支持交换,交换进程定期由调度程序调度,也是内存管理依赖与进程调度的原因.当进程存取的内存映射被换出时,内存管理想VFS系统发出请求,同事挂起当前正在运行的进程。
--所有子系统依赖部分共同资源,包括所有子系统API,分配&释放内存空间的函数,输出警告或错误或系统调用
3.3.3 内核空间&用户空间
-ARM7种模式。
--用户模式(usr)
--快速中断模式(fiq)-高速数据传输或通道处理
--外部中断模式(irq)-通用的中断处理
--管理模式(svc)--操作系统的保护模式
--数据访问中止模式(abt)-数据或指令预取中止时进入该模式,可用于虚拟存储及存储保护
--系统模式(sys)-运行具有特权的操作系统任务
--未定义指令中止模式(und)-当未定义的指令执行时进入该模式,可用支持硬件协处理器的软件仿真.
-ARM Linux系统调用实现原理采用swi软终端从用户模式陷入管理模式。
linux只能通过系统调用和硬件中U按完成用户控件到内核空间的控制转移
3.4 编译加载
3.4.1 编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make zImage
make dbts
make ARCH=arm modules
3.4.2 Kconfig&Makefile
增加内核需要完成以下三项工作
1.编写源码复制到相应目录
2.目录的Kconfig文件增加配置
3.目录的Makefile增加编译条目
实例 ttyprintk.c实例的配置 /drivers/char/ttyprintk.c引导
obj-$(CONFIG_ISDN) +=isdn.o --目标文件,
obj-$(CONFIG_EXT2_FS) +=ext2/ --目录文件夹
4.为drivers添加test驱动测试
3.4.3 linux内核引导
--SOC内嵌bootrom,上电时bootrom运行.
--对于CPU0而言,bootrom会去引导bootloader,其他CPU则会判断自己是否为CPU0,进入WFI状态等待CPU0唤醒。
--CPU0引导bootloader引导Linux内核,在内核启动阶段,CPU会发中断唤醒CPU1,之后CPU0和CPU1都投入运行。CPU0导致用户空间的init被调用。init再派生其他进程,派生出来的进程再派生其他进程。CPU0和CPU1共担这些负载,进行负载均衡。
--bootrom是各Soc自己定制,都具备SD、eMMC、NAND、USB等启动。
--bootrom内部代码具备读SD、NAND等能力.
--init(busybox init/SysVinit/systemd等)职责类似、启动系统最后进入一个进程树种例如ubuntu的pstree。
--bootloader需把dtb的地址放入r2寄存器中.当然armLinux也支持直接把dtb和zImage绑定在一起的模式(ARM_APPENDED_DTB选项"Use appeded device tree blob to zImage"),这样r2寄存器就不在需要填充dtb地址。
3.5 linux编程风格
1.代码缩进用TAB
2.{}使用原则
1)结构体、if/for/while/switch {不另起一行
2)如果if/for循环后只有一行,不要{}
3)if/else混用情况下,else不另起一行
4)函数另起一行
3.switch和case对齐
4.CodingStyle提供代码风格要求
5.scripts/checkpatch.pl可用于检查代码风格
6.工程阶段SCM软件的使能pre-commit hook自动检查代码风格 git pre-commithook也可运行检查本地代码
7.do{}while(0)主要用于宏定义
3.6 串口工具 CKermit、mincom、XModem MobaXterm等
3.7 结束