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
相关推荐
薛先生_09919 分钟前
js学习语法第一天
开发语言·javascript·学习
杨云龙UP26 分钟前
mysqldump逻辑备份文件恢复总结:全库恢复、单库恢复,一篇讲明白
linux·运维·服务器·数据库·mysql·adb
舰长11529 分钟前
linux系统服务器加固1、中风险 未设置登录失败处理功能和登录连接超时处理功能。2、中风险 未限制默认账户的访问权限。3、中风险 未实现管理用户的权限分离。
linux·运维·服务器
mounter6251 小时前
Linux 7.0 重磅更新:详解 nullfs 如何重塑根文件系统挂载与内核线程隔离
linux·运维·服务器·kernel
色空大师1 小时前
【网站搭建实操(一)环境部署】
java·linux·数据库·mysql·网站搭建
-Da-2 小时前
Unix哲学:一切皆文件与网络通信的统一抽象
服务器·unix
江南风月2 小时前
日志审计系统WGLOG支持syslog吗
运维·网络·日志审计
A.A呐3 小时前
【Linux第十三章】缓冲区
linux·服务器
寒秋花开曾相惜3 小时前
(学习笔记)3.8 指针运算(3.8.3 嵌套的数组& 3.8.4 定长数组)
java·开发语言·笔记·学习·算法
想唱rap3 小时前
Linux线程
java·linux·运维·服务器·开发语言·mysql