Linux内核学习(十三)—— 设备与模块(基于Linux 2.6内核)

目录

一、设备类型

二、模块

构建模块

安装模块

载入模块


一、设备类型

在 Linux 以及 Unix 系统中,设备被分为以下三种类型:

  • 块设备(blkdev):以块为寻址单位,块的大小随设备的不同而变化;块设备通常支持重定位(seeking)操作,也就是对数据的随机访问。如硬盘、蓝光光碟和 Flash 这样的存储设备都是块设备。块设备是通过称为 "块设备节点" 的特殊文件来访问的,并且通常被挂载为文件系统。
  • 字符设备(cdev):不可寻址,只提供数据的流式访问,即一个一个字符或字节地访问。如键盘、鼠标和打印机等都是字符设备。字符设备是通过称为 "字符设备节点" 的特殊文件来访问的,与块设备不同,应用程序通过直接访问设备节点与字符设备交互。
  • 网络设备:有时也被称为以太网设备(ethernet devices),提供了对网络的访问,这是通过一个物理适配器和一种特定的协议进行的。它不是通过设备节点来访问,而是通过套接字 API 这样的特殊接口来访问。

并不是所有设备驱动都表示物理设备。有些设备驱动是虚拟的,仅仅提供访问内核功能而已。这种设备被称为 "伪设备" (pseudo device),如内核随机数发生器(/dev/random)、空设备(/dev/null)等。

二、模块

尽管 Linux 是 "单块内核"(monolithic)的操作系统,但 Linux 内核时模块化组成的,它允许内核在运行时动态地向其中安装或卸载一个模块。

下面编写一个 Hello,World!的模块程序:

objectivec 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

/* 初始化函数,当模块装载时被调用 */
static int hello_init(void)
{
    printk(KERN_ALERT "Module installed!\n");
    return 0;
}

/* 退出函数,当模块卸载时调用 */
static void hello_exit(void)
{
    printk(KERN_ALERT "Module removed!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

这是一个非常非常简单的内核模块程序,hello_init() 是模块的入口点,它通过 module_init() 例程注册到系统中,在内核装载时调用。这个 init 函数仅仅打印了一行简单的信息,但在实际的模块中,该函数还会注册资源、初始化硬件、分配数据结构等。而 hello_exit() 函数负责对 init 函数以及在模块生命周期过程中所作的一切事情进行撤销与清理工作。

构建模块

下面开始构建模块。有两种方法来构建模块:

第一种是放在内核源代码树中。这样构建的模块会正式成为 Linux 内核中的一部分,设备驱动程序存放在内核源码树根目录下的 /drivers 的子目录下,根据不同的设备类型,字符设备存放于 /drivers/char,块设备存放于 /drivers/block 等。

假如我们编写的模块类型是字符设备,那就把模块文件移动到 /drivers/char 目录下,然后往 /drivers/char 目录下的 Makefile 文件中添加一行:

objectivec 复制代码
obj-m += hello.o

然后编译内核,重新装载内核即可。

第二种是放在内核代码外。将 hello.c 放到 /drivers/char 目录下后,在内核代码外创建一个 Makefile 文件,内容如下:

objectivec 复制代码
# -C 后为你的内核源码树所在位置
#  make -C /root/linux_kernel_learning/linux-2.6 modules

obj-m += hello.o

然后执行如下指令来构建模块:

objectivec 复制代码
make -C /root/linux_kernel_learning/linux-2.6 SUBDIRS=$PWD modules

安装模块

编译后模块将被装入到目录 /lib/modules/<version>/kernel/drivers/char 下:

下面的构建命令用来安装编译的模块(在内核源码树目录下执行):

复制代码
make modules_install

载入模块

载入一个模块:

复制代码
insmod hello.ko

卸载一个模块:

复制代码
rmmod hello.ko
相关推荐
ao-weilai11 分钟前
Linux网络编程:网络知识基础
linux·网络·php
David猪大卫24 分钟前
【C++修炼】哈希表的实现
数据结构·c++·笔记·学习·算法·哈希算法·散列表
辣知28 分钟前
辣知·化智53 榆林石峁遗址的石城文明
学习
GeW31 分钟前
RHCE10一次过!提高通过率+快速拿证的7个核心技巧
linux
JavaPub-rodert39 分钟前
Docker 多阶段构建:为什么生产环境镜像可以小 90%
运维·docker·容器
浅念-40 分钟前
C++ Protobuf 入门实战:基于通讯录项目吃透proto3语法与序列化
linux·服务器·网络·c++·protobuf·proto·proto3
m4Rk_1 小时前
【论文阅读】Agent 记忆机制(68):Memp——把历史轨迹沉淀为可检索、可纠错的程序性记忆
论文阅读·人工智能·学习·开源·github
知识分享小能手1 小时前
深度学习学习教程,从入门到精通,自编码器 — 完整知识点与代码案例(14)
人工智能·深度学习·学习
我命由我123451 小时前
人脸识别 - 去重时间窗口
java·开发语言·python·学习·java-ee·学习方法·python3.11
不怕犯错,就怕不做1 小时前
RK linux在buildroot中如何添加linux命令
linux·驱动开发·嵌入式硬件