嵌入式内核及驱动开发-02驱动模块开发(编写驱动ko,内核编译,设备树文件的编译,网卡移植,简单驱动代码的编写,驱动Makefile编写,insmod加载ko模块,模块ko参数传递)

驱动模块开发

驱动代码需要有四个部分
	1.头文件
	2.驱动模块装载和卸载函数入口声明
	3.实现模块装载和卸载函数入口
	4.GPL声明

编译驱动代码hello.c

在Ubuntu下Samba共享文件夹中组织自己的目录结构

linux@linux:/home/zzw/share/linux-3.14.79/mydirvers/hello_drv$ ls
hello.c      hello.mod.o  modules.order   mymath.h      mymath.mod.o
hello.ko     hello.o      Module.symvers  mymath.ko     mymath.o
hello.mod.c  Makefile     mymath.c        mymath.mod.c

linux@linux:/home/zzw/share/linux-3.14.79/mydirvers/hello_drv$ pwd 
/home/zzw/share/linux-3.14.79/mydirvers/hello_drv

驱动代码hello.c

/*
驱动代码需要有四个部分
		1.头文件
		2.驱动模块装载和卸载函数入口声明
		3.实现模块装载和卸载函数入口
		4.GPL声明
*/

//头文件
#include <linux/init.h>
#include <linux/module.h>

//实现模块装载和卸载函数入口
static int __init hello_drv_init(void)   
{
	//向系统申请资源
	printk("-----------%s-------------\n",__FUNCTION__);

	return 0;
}

static void __exit hello_drv_exit(void)
{
	//释放资源
	printk("-----------%s-------------\n",__FUNCTION__);

}

//驱动模块装载和卸载函数入口声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);

//GPL声明
MODULE_LICENSE("GPL");

编写Makefile

  • Mkaefile会被读两次
  • 第一次是make的时候,这时候主要读取的路径
  • 第二次是内核源码变异的时候,这时候,内核源码要知道要- 把该路径下哪个文件编译成ko

例—Makefile

ROOTFS_DIR = /nfs/rootfs / #根文件系统路径

ifeq ($(KERNELRELEASE),)
        
KERNEL_DIR = /home/zzw/share/linux-3.14.79 	#编译过的内核源码的路径

CPU_DIR = $(shell pwd) 

all:

	make -C $(KERNEL_DIR) M=$(CPU_DIR) modules  #把当前路径编成modules

clean:

	make -C $(KERNEL_DIR) M=$(CPU_DIR) clean
install:
	sudo cp -raf *.ko $(ROOTFS_DIR)/drv_module 	#把当前的所有.ko文件考到根文件系统的drv_module目录

else

obj-m += hello.o   #指定内核要把哪个文件编译成ko

obj-m += mymath.o   

endif

insmod 加载ko模块

在这里插入图片描述

lsmod 查看系统中装载了哪些模块

在这里插入图片描述

rmmod 卸载ko模块

注意:卸载时是驱动名,不加后缀.ko
在这里插入图片描述

  • 注意:卸载时是驱动名,不加后缀.ko

模块ko参数传递

  1. 加载模块时insmod hello.ko myname=“zhuzhongwei” myvalue=88参数会传递给模块内部

  2. 用途

     wifi驱动:   wifi硬件中内部也运行内部代码,原厂开发,这些代码叫做固件--firmware.bin
     装载wifi驱动,必须告诉固件文件在哪里
      insmod  rtxxx.ko path=/lib/modules/firmware/xxx.bin
    
  3. 在代码如何处理参数:

     module_param(name, type, perm)
     参数1:表示参数到名字,比如myname, myvalue
     参数2:参数到类型, charp, int
     参数3: /sys/modules/表示文件到权限: 0666
    
  4. 用法:

     module_param(myvalue, int, 0666);
     module_param(myname, charp, S_IRUGO|S_IWUGO|S_IXUGO);
    
  5. 传参(当驱动内部已经定义了参数后,优先使用外部传入的参数)
    在这里插入图片描述

ko模块的符号导出

新建mymath.c

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

//不需要模块加载和卸载的入口申明,直接定义好一些封装的函数

int my_add(int a,int b)
{
	return a+b;
}
EXPORT_SYMBOL(my_add);

int my_sub(int a,int b)
{
	return a-b;
}
EXPORT_SYMBOL(my_sub);

MODULE_LICENSE("GPL");

新建mymath.h

#ifndef __MATH_H__
#define __MATH_H__

int my_add(int a,int b);
int my_sub(int a,int b);

#endif

hello.c

/*
驱动代码需要有四个部分
		1.头文件
		2.驱动模块装载和卸载函数入口声明
		3.实现模块装载和卸载函数入口
		4.GPL声明
*/

//头文件
#include <linux/init.h>
#include <linux/module.h>
#include "math.h"

static int myvalue = 56;
static char *myname = "xinyuan";

//实现模块装载和卸载函数入口
static int __init hello_drv_init(void)   
{
	//向系统申请资源
	printk("-----------%s-------------\n",__FUNCTION__);
	printk("name = %s, value = %d\n",myname,myvalue);


	printk("a+b = %d, a-b = %d\n",my_add(33,22),my_sub(44,12));

	return 0;
}

static void __exit hello_drv_exit(void)
{
	//释放资源
	printk("-----------%s-------------\n",__FUNCTION__);

}


//驱动模块装载和卸载函数入口声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);

//GPL声明
MODULE_LICENSE("GPL");

//传参(当驱动内部已经定义了参数后,优先使用外部传入的参数)
module_param(myvalue,int,0644);
module_param(myname,charp,S_IRUGO|S_IWUSR);

调用模块符号

  • hello.ko里面调用了math.ko中的符号,所以要先加载mymath.ko
    在这里插入图片描述

#参考
https://blog.csdn.net/m0_37542524/article/details/86522912

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值