LINUX
http://www.kernel.org/(Linux内核源代码官方网站)
驱动
裸机驱动 系统驱动
设备驱动在Linux操作系统中的层次
Linux系统驱动类型
字符设备
块设备
网络设备
Linux内核模块的三要素
入口
出口
许可证
#include <linux/init.h>
#include <linux/module.h>//内核模块入口函数
static int __init mycdev_init(void)
{//static声明当前函数只能在当前文件中使用//int 声明返回值类型为int// mycdev_init是函数名,可以更换//内核模块中的参数如果无,一定要写一个void//#define __init __section(".init.text")//__init的作用是指定入口函数存放在.init.text段中return 0; //一定要返回一个int类型的值,不然编译报错
}
//内核模块出口函数
static void __exit mycdev_exit(void)
{//__exit声明当前的出口函数在.exit.text段}
//用于向内核声明当前内核模块的入口函数地址
module_init(mycdev_init);
//用于向内核声明当前内核模块的出口函数地址
module_exit(mycdev_exit);
//声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");
makefile
arch?=arm #存储编译架构的变量
modname?=demo #存储模块文件名的变量
#指定内核顶层目录的路径
ifeq ($(arch),arm)
KERNELDIR:=/home/ubuntu/linux-5.10.61/ #编译为ARM架构的内核路径
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build #编译生成x86架构文件的内核路径
endif
#指定当前源码所在的路径
PWD:=$(shell pwd) #将shell命令pwd的执行结果赋值给变量PWD
all:
#make modules表示进行模块化编译
#make -C $(KERNELDIR)先切换路径到KERNELDIR下,按照这个路径下Makefile的规则进行make
#M=$(PWD)指定模块化编译的路径make -C $(KERNELDIR) M=$(PWD) modules
clean:
#编译清除make -C $(KERNELDIR) M=$(PWD) clean
#将指定的.o文件独立链接为模块文件
obj-m:=$(modname).o
insmod
rmmod
lsmod
modinfo
printk
#define KERN_EMERG KERN_SOH "0" /* system is unusable */
#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */
#define KERN_CRIT KERN_SOH "2" /* critical conditions */
#define KERN_ERR KERN_SOH "3" /* error conditions */
#define KERN_WARNING KERN_SOH "4" /* warning conditions */
#define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */
#define KERN_INFO KERN_SOH "6" /* informational */
#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
#include <linux/init.h>
#include <linux/module.h>// 内核模块入口函数
static int __init mycdev_init(void)
{printk(KERN_ERR "模块安装,执行入口函数\n");return 0;
}
// 内核模块出口函数
static void __exit mycdev_exit(void)
{printk(KERN_ERR "模块卸载,执行出口函数\n");
}module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
dmesg
传参
module_param(name, type, perm)
#include <linux/init.h>
#include <linux/module.h>int a=10;
module_param(a,int,0664);//声明当前变量可以进行命令行传参
MODULE_PARM_DESC(a,"value is a int");
// 内核模块入口函数
static int __init mycdev_init(void)
{printk(KERN_ERR "模块安装,执行入口函数\n");printk("a=%d\n",a);return 0;
}
// 内核模块出口函数
static void __exit mycdev_exit(void)
{printk(KERN_ERR "模块卸载,执行出口函数\n");
}module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <linux/module.h>int a=10;
char b='c';
char *p="hello world";
module_param(a,int,0664);//声明当前变量可以进行命令行传参
MODULE_PARM_DESC(a,"value is a int");
module_param(b,byte,0664);
MODULE_PARM_DESC(b,"value is a char");
module_param(p,charp,0664);
MODULE_PARM_DESC(p,"value is a charp");
// 内核模块入口函数
static int __init mycdev_init(void)
{printk(KERN_ERR "模块安装,执行入口函数\n");printk("a=%d\n",a);printk("b=%c\n",b);printk("p=%s\n",p);return 0;
}
// 内核模块出口函数
static void __exit mycdev_exit(void)
{printk(KERN_ERR "模块卸载,执行出口函数\n");
}module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");