01、Linux内核模块

01、Linux内核模块

一、Linux内核模块简介

1、 模块的特点

  • 模块本身不被编译到内核镜像中,从而控制了内核的大小
  • 模块一旦被加载,就能和内核中的其他部分一样被调用

2、模块操作的命令

命令说明
insmod xxx.ko加载模块
modprobe xxx.ko加载模块,并同时加载该模块所依赖的其他模块
rmmod xxx.ko卸载模块
moprobe -r xxx.ko卸载模块,并同时卸载该模块所依赖的其他模块
lsmod查看已经加载的模块及模块间的依赖关系
modinfo xxx.ko获取模块的信息

模块加载完成后将在/sys/module目录下生成对应名称的目录

二、内核模块程序结构

结构说明
模块加载函数通过模块加载命令加载时,函数自动被内核执行,完成模块相关的初始化工作
模块卸载函数通过模块卸载命令卸载时,函数自动被内核执行,完成和加载相反的工作
模块许可证说明声明模块的许可权限,不声明将会产生内核被污染的警告
模块参数(可选)模块加载时可以传递给模块的值,该值也是模块内部的全局变量
模块导出符号(可选)模块可以导出的符号(包含函数或变量),符号导出后可被其他模块使用
模块作者信息(可选)

三、模块加载函数

  模块加载函数一般以__init标识声明,该标识告诉内核在初始化调用后可以将函数占用的空间释放留作他用。

#include <linux/init.h>
#include <linux/module.h>

/**
* @brief 模块加载函数
* 
* @return int              --0表示初始化成功,负值表示初始化失败
*/
static int __init xxx_init(void)
{
	/* 初始化代码 */
	
	return 0;
}
module_init(xxx_init);

四、模块卸载函数

  模块加载函数一般以__exit标识声明,该标志告诉内核如果模块直接编译进内核,则模块卸载函数不链接到最后的镜像中。

#include <linux/init.h>
#include <linux/module.h>

/**
* @brief 模块卸载函数
*/
static void __exit xxx_exit(void)
{
   /* 释放资源代码 */
}
module_exit(xxx_exit);

五、模块参数

  使用module_param宏可以为模块定义一个参数,使用module_param_array宏可以为模块定义一个参数数组。


/**
 * @brief 定义一个模块参数
 * 
 * @param  name             --参数名
 * @param  type             --参数类型
 * @param  perm             --参数读写权限
 */
module_param(name, type, perm);


/**
 * @brief 定义一个模块参数数组
 * 
 * @param  name             --参数数组名
 * @param  type             --参数数组类型
 * @param  nump             --参数数组长度
 * @param  perm             --参数读写权限
 */
module_param_array(name, type, nump, perm);

   在加载模块时调用命令后边加上参数及对应的值即可对参数进行赋值,即insmod xxx.ko param=valuemodprobe xxx.ko param=value。如果不传递,参数将使用模块内定义的缺省值。
  参数类型可以为byte(单字节类型)、shortushort(有无符号短整型)、intuint(有无符号整型)、longulong(有无符号长整型)、charp(字符串指针)、boolinvbool(正反布尔类型)。
  模块加载完成后,会在/sys/module/xxx/parameters/(xxx表示模块名称)目录下生成声明的参数对应的文件,该文件拥有声明时的操作权限。

六、导出符号

  使用EXPORT_SYMBOL(sys)宏声明导出符号到内核符号表中/proc/kallsyms

七、模块声明与描述

说明
MODULE_AUTHOR模块作者
MODULE_DESCRIPTION模块描述信息
MODULE_VERSION模块版本信息
MODULE_DEVICE_TABLE模块设备表,对于USB、PCI设备驱动通常会创建设备表
MODULE_ALIAS模块别名

八、模块的使用计数

九、模块的编译

  模块的编译需要在linux内核路径下编译,因此需要定义KERNAL_PATHCUR_PATH变量来告诉make执行的路径。该Makefile文件应该驱动源代码在同一目录下。

KERNAL_PATH := #内核存储的绝对路径
CURRENT_PATH := $(shell pwd)
MODULE_NAME := #编译模块的名称

obj-m := $(MODULE_NAME).o
#如果模块包含多个.c文件组成,则需要使用下一行命令
modulename-objs := file1.o file2.o


all:
	clear #清空终端内容
	$(MAKE) -C $(KERNAL_PATH) M=$(CURRENT_PATH) modules

clean:
	$(MAKE) -C $(KERNAL_PATH) M=$(CURRENT_PATH) clean
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值