1.Linux内核框架:
linux内核框架有五个子系统:进程管理、内存管理、虚拟文件系统(vfs)、网络接口、进程间通信。这里重点介绍:内存管理和虚拟文件系统。
1.1内存管理(mm)
允许多个进程安全的共享主内存区域。linux 的内存管理支持虚拟内存,即在计算机中运行的程序, 其代码,数据,堆栈的总量可以超过实际内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑上分为硬 件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。
1.2虚拟文件系统(vfs)
隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,vfs 提供了多达数十种不同 的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指 linux 所支持的文件系统,如ext2,fat 等,设备驱动程序指为每一 种硬件控制器所编写的设备驱动程序模块。
2.应用程序如何调用驱动
2.1驱动框架
Linux下字符设备驱动框架_linux字符设备驱动框架-CSDN博客
重点是图中这几个没有用到的参数"inode"和"file"
框架写好后用3条命令:添加了inode结点
insmod mymod.ko
mknod /dev/mydev c 300 0
./a.out
扩展问题:ioremap的作用是什么?
由于linux内核的内存管理用到的是虚拟内存,不能直接操作寄存器,故ioremap可以将实际的物理内存地址映射到虚拟地址空间中,让程序员可以直接通过指针访问硬件寄存器。
2.2应用程序调用
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "cmd.h" // 假设你有一个头文件定义了 ioctl 命令
#define DEVICE_NAME "/dev/mydev"
int main() {
int fd;
int ret;
// 打开设备文件
fd = open(DEVICE_NAME, O_RDWR);
if (fd < 0) {
perror("Failed to open device file");
exit(EXIT_FAILURE);
}
// 控制 LED 开启
ret = ioctl(fd, LED5_ON, 0);
if (ret < 0) {
perror("Failed to turn on LED");
close(fd);
exit(EXIT_FAILURE);
}
printf("LED turned on\n");
// 等待一段时间
sleep(2);
// 控制 LED 关闭
ret = ioctl(fd, LED5_OFF, 0);
if (ret < 0) {
perror("Failed to turn off LED");
close(fd);
exit(EXIT_FAILURE);
}
printf("LED turned off\n");
// 关闭设备文件
close(fd);
return 0;
}
可以归纳出应用程序调用驱动的程序的步骤:
操作文件之前都需要 系统调用 open。1.open 通过字符设备文件(/dev/mydev)找到 inode2.根据 inode 的信息创建 file (fd)3.根据 inode 中成员 i_mode 确定设备类型 c(mknod 创建 inode,并将 c 主次设备号,文件名等信息存入到 inode 中)4.根据 inode 中成员 i_rdev 确定设备号,根据设备号可以找到 cdev 结构体(内核中好多字符设备,每个字符设备对应一个 cdev 结构体)5.将找到的 cdev 结构体指针存入 inode 成员 i_cdev 中6.将找到的 cdev 中 成员 ops(file_operation) 地址给 file 中成员 f_ops7.open 根据 file 中的 f_ops 找到驱动中的 file_opertions,这样就可以调用其中对应的 open。
这里利用sourceinsight可以查看inode结构体。更好的理解虚拟文件系统和Linux一切皆文件。