`

linux驱动入门——模块参数和导出符号

阅读更多
驱动程序中lsmod命令实际读取的是/proc/modules文件
即与lsmod命令对应的结果是cat /proc/modules

内核中已经加载的模块的信息存在于/sys/module目录下

modprobe命令比insmod命令要强大,它在加载某模块时会同时加载该模块所依赖的其他模块
使用modprobe -r filename的方式卸载将同时其依赖的模块
modinfo 模块名命令可以获得模块的信息
modinfo hello.ko

filename:       hello.ko
alias:          a simplest module
description:    A simple Hello World Module
author:         Jimmy
license:        Dual BSD/GPL
srcversion:     FC20E540C350C6F733C7546
depends:       
vermagic:       2.6.28-15-generic SMP mod_unload modversions 586


驱动模块参数,MODULE_PARM_DESC可以注解参数
如:
        static int num = 4000;
        module_param(num, int, S_IRUGO);
        MODULE_PARM_DESC(myshort, "A integer");

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

MODULE_LICENSE("Dual BSD/GPL");

static char *book_name = "dissecting Linux Device Driver";
static int num = 4000;
static int param[8] = {1, 2, 3, 4, 5, 6, 7, 8};
static int param_len = 8;

static int book_init(void)
{
        int i;
        printk(KERN_ALERT " book name: %s\n", book_name);
        printk(KERN_ALERT " book num: %d\n", num);
        for(i = 0; i < 8; i++)
        {
                printk(KERN_ALERT "param[%d] =  %d \n", i, param[i]);
        }

        return 0;
}

static void book_exit(void)
{
        printk(KERN_ALERT " Book module exit\n");
}

module_init(book_init);
module_exit(book_exit);
module_param(num, int, S_IRUGO);
module_param(book_name, charp, S_IRUGO);
module_param_array(param, int, &param_len, S_IRUGO);

MODULE_AUTHOR("Jimmy, fightingjimmy@gmail.com");
MODULE_DESCRIPTION("A simple Module for testing module params");
MODULE_VERSION("v1.0");

sudo insmod book.ko
dmesg |tail -10
[14047.901352]  book name: dissecting Linux Device Driver
[14047.901366]  book num: 4000
[14047.901377] param[0] =  1
[14047.901386] param[1] =  2
[14047.901388] param[2] =  3
[14047.901389] param[3] =  4
[14047.901390] param[4] =  5
[14047.901391] param[5] =  6
[14047.901392] param[6] =  7
[14047.901393] param[7] =  8

sudo rmmod book.ko
sudo insmod book.ko book_name='Hello' num=1000 param=8,7,6,5
[14298.942521]  book name: Hello
[14298.942535]  book num: 1000
[14298.942547] param[0] =  8
[14298.942558] param[1] =  7
[14298.942559] param[2] =  6
[14298.942560] param[3] =  5
[14298.942561] param[4] =  5
[14298.942562] param[5] =  6
[14298.942564] param[6] =  7
[14298.942565] param[7] =  8

sudo rmmod book.ko
sudo insmod book.ko book_name="Hello World" num=1000 param=8,7,6,5
insmod: error inserting 'book.ko': -1 Unknown symbol in module

dmesg |tail -10
[15097.587159] book: Unknown parameter `world'
猜想:可能是因为传入的字符串参数带有空格的原因(有遇到类似情况的请不吝赐教)

linux2.6的/proc/kallsyms文件对应着内核符号表,它记录了以及符号所在的内存地址。
EXPORT_SYMBOL(符号名);
EXPROT_SYMBOL_GPL(符号名);

module/
        include/
                print.h
        print/
                print.c
                Makefile
        symbol/
                test.c
                Makefile

/****************************************
* print.h                               *
*****************************************/
#ifndef PRINT_H
#define PRINT_H

void add_integer(int a, int b);
void sub_integer(int a, int b);

#endif


/****************************************
* print.c                               *
*****************************************/
#include <linux/init.h>
#include <linux/module.h>

#include "print.h"

MODULE_LICENSE("Dual BSD/GPL");

void add_integer(int a, int b)
{
        printk(KERN_ALERT " sum: %d\n", a + b);
}

void sub_integer(int a, int b)
{
        printk(KERN_ALERT " sub: %d\n", a - b);
}

EXPORT_SYMBOL(add_integer);
EXPORT_SYMBOL(sub_integer);


/****************************************
* test.c                                *
*****************************************/
#include <linux/init.h>
#include <linux/module.h> 
 
#include "print.h" 

MODULE_LICENSE("GPL");  
 
static int symbol_init(void) 
{
        printk(KERN_ALERT " Symbol test init\n"); 
        add_integer(10, 6);
        sub_integer(10, 6); 
        return 0; 

  
static void symbol_exit(void) 

        printk(KERN_ALERT " Symbol test exit\n"); 

  
module_init(symbol_init); 
module_exit(symbol_exit); 

print目录下的Makefile:
obj-m := print.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
PRINT_INC = $(obj)/../include           #包含print.h头文件
EXTRA_CFLAGS += -I $(PRINT_INC)

modules:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
        rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean


symbol目录下的Makefile:
obj-m := test.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
SYMBOL_INC = $(obj)/../include
EXTRA_CFLAGS += -I $(SYMBOL_INC)
KBUILD_EXTRA_SYMBOLS=$(obj)/../print/Module.symvers

modules:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
        rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

注意:若是Makefile文件中没有KBUILD_EXTRA_SYMBOLS=$(obj)/../print/Module.symvers
则需要将print目录下的Module.symvers拷贝到symbol目录下,这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi?id=12446)


分别编译insmod即可
分享到:
评论

相关推荐

    易模块——超级列表框导出EXECL

    易模块——超级列表框导出EXECL 易模块——超级列表框导出EXECL

    公众号一口Linux驱动部分源码汇总.rar

    代码是公众号一口Linux 文章驱动部分所有势力代码,文章如下: 《玩转内核链表list_head,如何管理不同类型节点的实现...《手把手教Linux驱动2-模块参数param和符号导出export用法》 《手把手教Linux驱动1-模块化编程》

    linux驱动开发实例

    Hello World 模块程序设计是 Linux 驱动开发的入门级实验,旨在帮助初学者掌握 Linux 内核模块的编写、编译、加载和卸载的过程。这个实验包括编写 Hello World 模块的源代码、编译 Makefile、加载模块到目标板上、...

    ABPLC编程软件RSLOGIX5000入门8——程序导入导出.pdf

    ABPLC编程软件RSLOGIX5000入门8——程序导入导出 本文将介绍使用部分导入/导出工具来帮助加速程序开发。关于梯形图部分导入/导出工具大多数时候,应用开发时都会有许多代码段重复许多次。例如, 在传送带系统中具有...

    exfat-linux驱动支持exfat文件系统NFS导出

    总的来说,"exfat-linux驱动支持exfat文件系统NFS导出"是一个涉及到Linux内核驱动编程、文件系统理论以及网络文件系统协议的复杂工程,需要开发者对这些领域有深入的理解和实践经验。这样的工作有助于提升Linux对...

    小程序模块化开发——模块.zip

    3. **导入与导出**:在JavaScript中,我们使用`import`和`export`关键字来实现模块间的依赖关系。小程序虽然基于JS,但其API略有不同,采用`require`和`module.exports`或`exports`进行模块的加载和暴露。 4. **...

    ABPLC编程软件RSLOGIX5000入门8——程序导入导出.docx

    本文将详细介绍RSLogix5000中的一个非常实用的功能——程序导入导出,特别是梯形图部分导入/导出工具的使用方法。 #### 梯形图部分导入/导出工具简介 梯形图部分导入/导出工具是RSLogix5000自版本13起新增的一个...

    深入linux设备驱动程序内核机制

    《深入Linux设备驱动程序内核机制》一书探讨了Linux内核与设备驱动程序的紧密关系,旨在帮助读者深入理解如何有效地编写和优化Linux设备驱动。书中不仅关注内核模块的构建,还涉及驱动程序与内核交互的关键技术,如...

    TS TOOLS.rar ——3dmax插件 导出fbx ue4必用插件

    1. **高级FBX导出设置**:TS Tools允许用户自定义FBX导出的详细参数,包括选择导出的几何体类型(如多边形、NURBS等)、是否包含UV坐标、骨架结构和动画关键帧等。这些高级设置对于保持模型在UE4中的完整性至关重要...

    安卓Android源码——安卓Android导入导出txt通讯录工具.rar

    这个压缩包文件“安卓Android源码——安卓Android导入导出txt通讯录工具.rar”显然提供了一个实用工具,它能够帮助用户将他们的通讯录数据在Android设备和纯文本(txt)文件之间进行转换。以下是对这一技术实现的...

    如何正确的导出符号表-PLC学习笔记

    要正确导出符号表,首先需要了解PLC和其编程软件支持的导出文件格式。常用的格式包括CSV(逗号分隔值)、TXT(文本文件)、XML(可扩展标记语言)等。CSV格式由于其简单易用且广泛支持,经常被选用。正确选择导出...

    AB PLC编程软件RSLOGIX5000入门8 ——程序导入导出.docx

    本文将深入讲解如何利用RSLOGIX5000的程序导入导出功能,以提高程序开发效率和代码复用性。 1. **梯形图部分导入/导出工具的背景** 在传统的编程方法中,当需要在多个地方重复使用相同或相似的代码段时,通常会...

    AB-PLC编程软件RSLOGIX5000入门8-——程序导入导出.pdf

    AB-PLC编程软件RSLOGIX5000入门8-——程序导入导出.pdf

    AB-PLC编程软件RSLOGIX5000入门8-——程序导入导出.doc

    AB-PLC编程软件RSLOGIX5000入门8-——程序导入导出.doc

    Linux内核可装载模块对设备驱动的影响

    Linux内核可装载模块对设备驱动的影响主要体现在2.4到2.6内核的升级过程中,这涉及到多个方面的变化,包括模块编译、版本检查、初始化与退出、模块使用计数、内核符号输出、命令行参数处理以及许可证声明等。...

    Linux驱动学习总结

    **1.6 内核和模块的编译** 内核编译过程通常包括以下几个步骤: 1. **配置**:使用`make menuconfig`或其他工具来配置内核选项。 2. **编译**:运行`make`命令进行编译。 3. **安装**:使用`make modules_install`...

    Linux2.6内核驱动移植

    Linux2.6内核驱动移植需要遵守新的编程规范和接口标准,需要注意入口函数、许可证声明、模块参数、模块别名、模块计数、符号导出、内核版本检查、设备号、内存分配头文件变更、结构体的初始化、用户模式帮助器和...

    宋宝华老师的Linux驱动最佳实践

    Linux内核模块主要由几个关键部分组成,包括模块加载函数、模块卸载函数、模块许可证声明、模块参数、模块导出符号以及模块作者等信息声明。其中,模块加载函数和卸载函数分别在模块加载和卸载时被内核调用执行相关...

    linux 内核模块

    Linux内核模块是Linux操作系统内核可动态加载和卸载的部分...理解模块编写、导出符号的使用以及如何管理模块,是Linux系统管理和开发的基础。通过实践,你可以创建自己的内核模块,从而更好地理解和控制你的Linux系统。

Global site tag (gtag.js) - Google Analytics