Linux内核开发学习笔记(一)
内核交互图及前言
感谢 MakeLinux 制作的Linux内核交互图,在内核的学习过程中需要反复的温习内核交互图,才能够对整体的框架有充足的认识。
大佬推荐的书籍:
- 入门
鸟哥的Linux私房菜、Linux系统管理技术手册 - 初阶
UNIX环境高级编程 - 中阶
深入理解LINUX内核 - 高阶
深入理解Linux内核第三版
1.Linux系统概述
1.内核:进程间通信、进程调度、内存管理、文件系统、网络等内容;
2.交互方式:应用软件<- - - ->系统调用(隔离机制:隔离内核和应用软件间的变化)<- - - ->内核<- - - ->硬件;
3.设计理念:机制与策略分离。机制->提供了什么具体的功能;策略->如何使用该功能;
4.单内核和微内核:微内核主要作为消息转发站,以消息传递的方式进行通讯,可维护性高,设计灵活性强,但性能和效率上有损失(Minix3,QNX,L4 Fuchsia等);单内核(Linux借鉴了微内核的有点,采用模块化设计,抢占式内核,支持内核线程和动态加载内核模块等功能);
5.内核模块:不是可执行文件,而是运行时目标文件链接到内核中。加载和卸载模块需要超级用户权限。
2.内核编程
(1)内核编程和C编程的简要区别
图片来源于Linux内核分析与应用课程
(2)内核源码目录结构
存放位置:/usr/src/linux-****/
- arch 包含了内核源代码所支持的硬件体系结构相关的核心代码。
- include 包括了编译核心的大多数头文件。
- init 包含了内核的初始化代码。
- mm 包含了内存管理代码;
- drivers 包含了设备驱动相关代码;
- ipc 包含了进程间通信相关代码;
- modules 包含了可动态加载的模块;
- fs 包含了Linux支持的文件系统相关代码;
- kernel 包含了内核管理的核心代码;
- net 包含了内核的网络部分代码;
- lib 包含了内核的库代码;
- scripts 包含了内核配置的脚本文件;
- Documentation 包含了各目录的文档说明。
(3)宏定义获得结构体的起始地址
根据结构体成员变量获取结构体的起始地址
#define struct_entry(ptr,type,member) ((type*)((char*)(ptr)-(size_t)(&((type*)0)->member)))
原理:
- (char*)(ptr):成员变量的绝对地址;
- (type*)0:将0强转成type*指针;
- &((type*)0)->member):成员变量相对于0的偏移量;
(3)内核编程实践:hello world
- 内核代码文件夹:
- helloworld代码:
//kernel init func
#include <linux/init.h>
//kernel func
#include<linux/kernel.h>
//linux_kernel_module
#include <linux/module.h>
//linux kernel module entry function
static int __init lkm_init(void)
{
printk("Hello World\n");
return 0;
}
//linux kernel module exit function
static int __exit lkm_exit(void)
{
printk("Exit!\n");
}
//entry point && exit point
module_init(lkm_init);
module_exit(lkm_exit);
MODULE_LICENSE("GPL");
-
Makefile文件:
存在的问题:
真实原因:Makefile中LINUX_KERNEL_PATH中“-”写成了"_" (有些许无奈,全当学习一遍Linux替换内核了。)($ _ $)
原因没有安装内核安装包
(1) 下载内核安装包
(2)解压压缩包并解压
(3)make 相关配置文件以及必要库
命令:sudo make menuconfig
命令:sudo apt-get install libncurses-dev
命令:sudo apt-get install flex
命令:sudo apt-get install bison essential
(4)图形化界面
(5)查看配置文件
(6)make编译
根据提示有缺库的情况就安装库
命令:sudo apt-get install libssl-dev
-
内核helloWorld编译结果:
-
通过proc目录,访问有关内核的状态信息和进程信息:
其中kmsg保存所有的日志信息,利用dmesg查看其中的日志信息
-
插入helloWorld内核模块:
命令:sudo insmod helloWorld.ko
lsmod查看当前已插入的模块,helloWorld模块已经插入
通过dmesg查看日志信息,可以发现Hello World正常打印
-
删除helloWorld内核模块:
-
命令:sudo rmmod helloWorld
lsmod查看当前已插入的模块,helloWorld模块已经插入
通过dmesg查看日志信息,可以发现Hello World正常打印