helloworld驱动程序
七、helloworld驱动程序
7.1 概述
嵌入式linux系统设计关键概念是将用户应用与底层硬件隔离,不允许上层应用直接操作底层硬件,防止硬件设备处于未知状态。内核态和用户态的隔离,提供给开发者较强的可移植性。内核模块一般存放于
/lib/modules
Linux内核使用GNU GPLv2许可证。更多开源软件许可证可访问http://opensource.org/license查看。
7.2 helloworld驱动(1)不带参数
helloworld驱动文件包括:
Makefile //编译文件
helloworld.c //源代码文件 <module name>.c
针对SAMA5D2写的helloworld驱动程序,即
helloworld.c代码:
#include <linux/module.h>
static int __init hello_init(void)
{
pr_info("hello world init\n");
return 0;
}
static int __init hello_exit(void)
{
pr_info("hello world exit\n");
return 0;
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(" ");
MODULE_DESCRIPTION("This is print out hello world module");
Makefile:
obj-m += helloworld.o
KERNEL_DIR ?= $(home)/my-linux-imx
all:
make -C $(KERNEL_DIR ) \
ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- \
SUBDIR=$(PWD) modules
clean:
make -C $(KERNEL_DIR ) \
ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- \
SUBDIR=$(PWD) clean
deploy:
scp *.ko root@10.0.0.10:
简单的把<module name>.c
编译成<module name>.o
,随后到Makefile变量obj-m
打印备注:
printk() //内核态下打印使用
测试调试
insmod helloworld.ko //加载模块
modinfo helloworld.ko //查看模块介绍
cat /proc/sys/kernel/tainted //打印 4096 = GPL, oot
rmmod helloworld.ko //卸载模块
cat /proc/modules
find /sys -name "*helloworld*" //在sysfs中查找你的模块
7.2 helloworld驱动(2)带输入参数
在helloworld驱动(1)基础上增加参数传递,通过命令行提供模块加载时设置参数。你也可以通过sysfs文件系统读取参数,下面介绍sysfs(虚拟文件系统)。
sysfs是Linux内核提供的一个虚拟文件系统,内核通过虚拟文件系统将内核模型中的各种内核子系统、硬件设备以及关联的设备驱动信息导出到用户态。除了提供各种关于设备以及子系统的信息,导出的虚拟文件也被用于对它们进行配置。
模块参数的宏定义:
module_param(name, perm);
helloworld_with_param.c代码:
#include <linux/module.h>
static int num = 5;
module_param(num, int, S_IRUGO);
static int __init hello_init(void)
{
pr_info("parameter num = %d\n", num);
return 0;
}
static void __exit hello_exit(void)
{
pr_info("Hello world with parameter exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(" ");
MODULE_DESCRIPTION("This is a module that accepts parameters");
Makefile:
obj-m += helloworld_with_param.o
KERNEL_DIR ?= $(HOME)/my-linux-imx
all:
make -C $(KERNEL_DIR) \
ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- \
SUBDIRS=$(PWD) modules
clean:
make -C $(KERNEL_DIR) \
ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- \
SUBDIRS=$(PWD) clean
deploy:
scp *.ko root@10.0.0.10:
测试调试
insmod helloworld_with_param.ko num=10
7.2 helloworld驱动(3)带计时功能
功能描述:
在内核卸载时候,打印驱动从加载到卸载所经历的时间长度。
获取时间c函数:
kernel/time/keeping.c
timeval数据结构定义:
#incldue <linux/time.h>
struct timeval {
_kernel_time_t tv_sec; //秒
_kernel_suseconds_t tv_usec; //微秒
};
helloworld_with_timing.c代码:
#include <linux/module.h>
#include <linux/time.h>
static int num = 10;
static struct timeval start_time;
module_param(num, int, S_IRUGO);
static void say_hello(void)
{
int i;
for (i = 1; i <= num; i++)
pr_info("[%d/%d] Hello!\n",i,num);
}
static int __init first_init(void)
{
do_gettimeofday(&start_time);
pr_info("Loading first!\n");
say_hello();
return 0;
}
static void __exit first_exit(void)
{
struct timeval end_time;
do_gettimeofday(&end_time);
pr_info("Unloading module after %ld seconds\n",
end_time.tv_sec - start_time.tv_sec);
say_hello();
}
module_init(first_init);
module_exit(first_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(" ");
MODULE_DESCRIPTION("This is a module that will print the time since it was loaded");
Makefile:
obj-m += helloworld_with_timing.o
KERNEL_DIR ?= $(HOME)/my-linux-imx
all:
make -C $(KERNEL_DIR) \
ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- \
SUBDIRS=$(PWD) modules
clean:
make -C $(KERNEL_DIR) \
ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- \
SUBDIRS=$(PWD) clean
deploy:
scp *.ko root@10.0.0.10:
测试调试:
insmod helloworld_timing.ko num=10
cat /sys/module/helloworld_with_timing/parameters/num
rmmod helloworld_timing.ko
感谢阅读,祝君成功!
-by aiziyou