驱动开发基础工作

本文介绍了驱动开发的基础工作,包括必要的条件如开发板、内核源码和NFS根文件系统。详细阐述了驱动开发步骤,如编写和编译驱动源码、使用insmod和rmmod等命令进行模块安装和卸载。同时,分析了最小模块的makefile和源码,讲解了module_init和module_exit宏以及printk函数的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

驱动开发的必要条件:

  1. 正常运行linux系统的开发板
  2. 内核源码树
  3. nfs挂载的rootfs,虚拟机安装nfs服务器

驱动开发步骤:

  1. 驱动源码和makefile编写,编译
  2. insmod安装模块,测试,rmmod卸载模块

常用的模块操作命令:

  1. lsmod,打印当前内核已经安装的模块
  2. insmod xxx.ko 安装xxx.ko模块
  3. modinfo xxx.ko 打印xxx.ko模块信息,注意模块版本和内核版本必须一致,否则安装报错:Invalid module format
  4. rmmod xxx 卸载xxx.ko模块
  5. 其他

最小模块源码及makefiel分析

makefile :

#ubuntu的内核源码树,如果要编译在虚拟机中安装的模块就用这个
KERN_VER = $(shell uname -r)
KERN_DIR = /lib/modules/$(KERN_VER)/build	
		
# 开发板的linux内核的源码树目录,自定义
#KERN_DIR = /home/yt/drivers/kernel

#将module_test.c编译成一个模块
obj-m	+= module_test.o

#第一个命令
all:
	make -C $(KERN_DIR) M=`pwd` modules 

.PHONY: clean	
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
  • KERN_DIR,变量的值就是我们用来编译这个模块的内核源码树的目录
  • obj-m += module_test.o,这一行就表示我们要将module_test.c文件编译成一个模块
  • make -C $(KERN_DIR) M=pwd modules 这个命令用来实际编译模块,工作原理就是:利用make -C进入到我们指定的内核源码树目录下,然后在源码目录树下借用内核源码中定义的模块编译规则去编译这个模块,编译完成后把生成的文件还拷贝到当前目录下,完成编译

总结:模块的编译要借助内核源码的体系来完成

module.c

#include <linux/module.h>		// module_init  module_exith宏在这里定义
#include <linux/init.h>			// __init   __exit宏在这里定义

// 模块安装函数
static int __init chrdev_init(void)
{	
	printk(KERN_INFO "chrdev_init helloworld init\n");
	#设置打印级别为7
	//printk("<7>" "chrdev_init \n");
	return 0;
}

// 模块下载函数
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit \n");
}


module_init(chrdev_init);
module_exit(chrdev_exit);

// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("klyer");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("xxx");			// 描述模块的别名信息
  • 头文件,头文件路径是内核源码树的 /include/…,比如#include <linux/module.h>是在/include/linux/module.h
  • module_init宏和insmod命令绑定,即insmod----调用module_init宏----调用chrdev_init函数
  • module_exit宏和rmmod命令绑定,即rmmod----调用module_exit宏----调用chrdev_exit函数
  • __init,本质上是个宏定义,
#define __init		__section(.init.text) __cold notrace

这个__init的作用就是将被他修饰的函数放入.init.text段中去(本来默认情况下函数是被放入.text段中)。
__exit和它差不多:

#define __exit          __section(.exit.text) __exitused __cold
  • 模块中常用宏,代码中已经注释,一般模块许可证不能少
  • printk函数,和printf功能类似,区别是printf是应用层使用的C库函数,不能在内核中使用。printk函数是内核中使用的,并且多了打印级别设置的功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值