linux内核与驱动-驱动程序范例
来源:互联网 发布:lvm安装linux 编辑:程序博客网 时间:2024/05/17 08:03
范例中以一个经典的hello驱动程序为例
$vim hello.c创建源码文件
程序有几个重要的部分
a. 引用两个基本的头文件linux/init.h、linux/module.h;
b. MODULE_LICENSE("Dual BSD/GPL")
此申明是告诉内核,该模块采用自由许可证,没此申明则内核在装载该模块时会产生抱怨,就好像内核在说,你(此模块)遵循GNU GPL规定,有问题的话后果自负;
c. module_init(func_init),insmod加载内核时,会调用func_init初始化函数
module_exit(func_exit),rmmod卸载内核时,会调用func_exit退出函数
程序代码如下
///////////////////////////////////////////////START/////////////////////////////////////////////
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
//定义模块的版本
#define MODULEVERSION "1:1.0"
MODULE_LICENSE("Dual BSD/GPL");//申明此模块遵循GPL规定
MODULE_AUTHOR("jayson_jang");//申明此模块的作者
MODULE_DESCRIPTION("hello test");//申明对此模块的描述
MODULE_VERSION(MODULEVERSION);//申明此模块的版本
MODULE_ALIAS("hello_test.ko");//申明此模块的别名
//MODULE_DEVICE_TABLE("ALL", "bycle");
/*
模块支持一下数据类型
bool invbool charp int long short uint ulong ushort
*/
//变量申明
static char *whom = "world";
static int howmany = 1;
static bool boolflag=1;
static char name[2][16]={"name1", "name2"};
static int num = 2;
static int major=0, minor=0;
//static invbool invboolflag=1;
//将申明的变量传入到此模块,S_IRUGO代表所有人可读此变量
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);//charp代表是char指针类型
module_param(boolflag, bool, S_IRUGO);
module_param_array(name, charp, &num, S_IRUGO);
module_param(major, int, S_IRUGO);
module_param(minor, int, S_IRUGO);
void func1(void)
{
printk("func1\r\n");
}
EXPORT_SYMBOL_GPL(func1);//导出func1,遵循GPL的其他模块可调用此函数
//模块初始化函数,__init代表此模块初始化完后,此函数将被简单的丢弃
static int __init hello_init(void)
{
int err=0, i=0;
dev_t devid=0;
//printk打印字符,KERN_ALERT代表将打印输出到控制台和日志文件中
printk(KERN_ALERT "Hello,world\n");
//current->comm代表此进程名,current->pid代表此进行id号
//current定义在linux/sched.h头文件中,可直接使用
printk(KERN_ALERT "The process is \"%s\", pid is %d\n", current->comm, current->pid);
//根据输入的howmany变量打印howmany次whom
for(i=0; i<howmany; i++)
printk(KERN_ALERT "are you ok,%s\n", whom);
printk(KERN_ALERT "boolflag = %d\n", boolflag);
//printk(KERN_ALERT "invboolflag = %d\n", invbool(boolflag));
//打印输入的二维字符数组
for(i=0; i<2; i++)
printk(KERN_ALERT "age[%d]:%s\n", i, name[i]);
if(err)
goto err_exit;
if(major) //如果定义了主设备号
{
devid = MKDEV(major, minor); //MKDEV生成设备号
register_chrdev_region(devid, 1, "hello");//注册设备号,并命名为hello
}
else
{
alloc_chrdev_region(&devid, minor, 1, "hello");//动态分配设备号
printk(KERN_ALERT "minor:%d\r\n", minor);
major = MAJOR(devid);//MAJOR获取主设备号,MINOR获取次设备号
printk(KERN_ALERT "major:%d\r\n", major);
}
return 0;
err_exit:
return EBADTYPE;
}
//模块卸载函数,__exit代表此函数仅仅用于模块卸载,如此模块不允许卸载则丢弃
static void __exit hello_exit(void)
{
dev_t devid=0;
printk(KERN_ALERT "Goodbye,cruel world\n");
printk(KERN_ALERT "The process is \"%s\", pid is %d\n", current->comm, current->pid);
//printk(KERN_ALERT "UTS_RELEASE: %s \n", UTS_RELEASE);
printk("printk1\n");//没有KERN_ALERT则为默认级别,结尾有加\n,则会打印
printk("printk2");//没有KERN_ALERT则为默认级别,结尾没有加\n,则不会打印
devid = MKDEV(major, minor);
unregister_chrdev_region(devid, 1);//释放设备号
}
module_init(hello_init); //模块初始化函数入口
module_exit(hello_exit);//模块卸载函数入口
///////////////////////////////////////////////END/////////////////////////////////////////////
$vim Makefile创建Makefile编译文件,源码如下
///////////////////////////////////////////////START/////////////////////////////////////////////
#Makefile 2.6
objs = hello.o
ifneq ($(KERNELRELEASE),)
mymodule-objs:=${objs}
obj-m:=${objs}
else
PWD:=$(shell pwd)
KVER?=$(shell uname -r)
KDIR:=/usr/src/linux-${KVER} //安装的内核源码树的位置
#KDIR:=/usr/src/linux-headers-2.6.32-21-generic/
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
@rm -rf *.com *.o *.mod.c *.ko .tmp_versions modules.order Module.symvers
endif
///////////////////////////////////////////////END/////////////////////////////////////////////
$make
生成hello.mod.c hello.o Module.symvers hello.ko hello.mod.o modules.order
$tail -f /var/log/message //新打开一个字符终端输入此命令用于查看模块加载、卸载打印
$sudo insmod hello.ko //加载内核,会看到如下打印
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208007] Hello,world
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208021] The process is "insmod", pid is 2357
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208022] are you ok,world
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208024] boolflag = 1
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208025] age[0]:name1
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208026] age[1]:name2
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208029] minor:0
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208030] major:249
$sudo rmmod hello.ko //卸载内核,会看到如下打印
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.236285] Goodbye,cruel world
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.236303] The process is "rmmod", pid is 2358
Apr 15 23:27:16 jayson-desktop kernel: [ 4322.236308] printk
- linux内核与驱动-驱动程序范例
- Linux内核MTD驱动程序与SD卡驱动程序
- Linux键盘驱动范例
- Linux内核:驱动程序
- linux 驱动程序 内核数据类型
- 编写Linux内核驱动程序
- 测试Linux内核驱动程序
- Linux驱动模型 - 驱动程序
- Linux 下的驱动程序与内核的编译
- Linux 下的驱动程序与内核的编译
- 2013/09/23 Android的Linux内核与驱动程序
- Linux驱动程序开发 003- 设备与驱动的关系
- 嵌入式Linux内核与驱动面试要点:
- Linux内核驱动学习难点与学习方法
- Linux内核与驱动面试要点
- linux内核编译与简易驱动
- Linux内核与驱动面试要点
- linux内核配置与驱动注册
- 利用 Windows 8 功能和 MVVM
- 从P1到P7——我在淘宝这7年
- linux sed 命令
- Unity3D之音乐音效的播放【2】
- django apache2.2 mod_wsgi的编译
- linux内核与驱动-驱动程序范例
- 黑马程序员_面向对象03
- 淘宝技术发展
- 设计模式之单例模式(线程安全)
- Python 笔记
- Mac之vim普通命令使用
- 欢迎来到Seven's Home...
- poj 2886 Who Gets the Most Candies? 线段树动态求第k大的数
- 有关优先对列的题——UVA12100 - Printer Queue