在Android上编译linux内核驱动程序

一、新建新的驱动程序目录:
shanl@ubuntu:~/Android/android-2.3.5_r1$ cd kernel/goldfish/drivers/
shanl@ubuntu:~/Android/android-2.3.5_r1/kernel/goldfish/drivers$ mkdir hello

二、hello目录里建立一个hello.h头文件,加入一个虚拟设备驱动,内容如下:

#ifndef _HELLO_H
#define _HELLO_H

#include <linux/cdev.h>    //字符设备需要的头文件

struct hello_dev{
	int reg;
	struct cdev dev;
};

#endif

#ifndef#define#endif的用法
头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

    #ifndef <标识>

    #define <标识>

    ......

    ......

    #endif
    <标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h
    #ifndef _STDIO_H_

    #define _STDIO_H_

    ......

    #endif
回到之前的头文件,该文件中定义了一个字符设备结构体hello_dev,这个就是我们虚拟的硬件设备了,reg成员变量就代表设备里面的寄存器,它的类型为int,dev成员变量是一个内嵌的字符设备,这个Linux驱动程序自定义的字符设备结构体。
三、 在hello目录中增加hello.c文件,这是驱动程序的实现部分。 首先写上一个字符设备的框架

#include <linux/fs.h>
#include <linux/module.h>
#include "hello.h"

#define CHARDEV "hello_char"

static int hello_major = 0;  
static int hello_minor = 0; 

static struct hello_dev* hellodev = NULL;  

struct file_operations hello_fops = {//需要头文件linux/fs.h

};

static int hellodev_init(struct hello_dev *dev) //字符设备的初始化封装函数
{
	struct cdev cdev= dev->dev;
	int err;
	dev_t devno = MKDEV(hello_major,hello_minor);
	cdev_init(&cdev, &hello_fops);
	cdev.owner = THIS_MODULE;//需要头文件linux/modules.h
	cdev.ops = &hello_fops;

	err = cdev_add(&(dev->dev),devno, 1);  
	if(err) {  
		return err;  
	}   
	return 0;	
}

static int __init hello_init(void)
{
	dev_t dev = 0;
	int err;
	err = alloc_chrdev_region(&dev, 0, 1,CHARDEV);//dev是个输出参数,这个函数动态分配主设备和次设备号
	if (err < 0) {
		printk(KERN_ERR "Fail to alloc chardev num\n");
		goto fail;
	}

	//获取主设备和次设备号
	hello_major = MAJOR(dev);
	hello_minor = MINOR(dev);

	hellodev = kmalloc(sizeof(struct hello_dev), GFP_KERNEL);//分配虚拟设备空间
	if (!hellodev) 
		return -ENOMEM;

	//初始化字符设备
	hellodev_init(hellodev);

fail:
	return err;

}

static void __exit hello_exit(void)
{
	dev_t dev = MKDEV(hello_major,hello_minor);
	cdev_del(&(hellodev->dev));
	kfree(hellodev);
	unregister_chrdev_region(dev, 1);		
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("First Android Driver"); 

四、修改配置文件将hello驱动编译到内核中:

1.加入Kconfig文件

shanl@ubuntu:~/Android/android-2.3.5_r1/kernel/goldfish/drivers/hello$ vi Kconfig

内容:

config HELLO
tristate "First Android Driver"
default n
help
    This is the first android driver.
加入这个Kconfig后,会在make menuconfig中找到相应的选项

2.加入Makefile文件:

shanl@ubuntu:~/Android/android-2.3.5_r1/kernel/goldfish/drivers/hello$ vi Makefile

内容:

obj-$(CONFIG_HELLO) += hello.o
3.进入上一层目录:

shanl@ubuntu:~/Android/android-2.3.5_r1/kernel/goldfish/drivers$ vi Kconfig

和arch/arm/Kconfig文件

shanl@ubuntu:~/Android/android-2.3.5_r1/kernel/goldfish/arch/arm$ vi Kconfig

在menu "Device Drivers"和endmenu之间加入:

source "drivers/hello/Kconfig"

4.shanl@ubuntu:~/Android/android-2.3.5_r1/kernel/goldfish/drivers$ vi Makefile

加入:obj-$(CONFIG_HELLO) += hello/

5.make menuconfig 选中 First Android Driver

6.重新编译内核。

启动模拟器,adb shell

shanl@ubuntu:~$ adb shell
# cd /proc
# cat devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 90 mtd
128 ptm
136 pts
252 hello_char
253 ttyS
254 rtc

Block devices:
  1 ramdisk
259 blkext
  7 loop
 31 mtdblock
 43 nbd
179 mmc
254 device-mapper
#
发现我们注册的字符设备已经注册成功了。

总结一下如何注册字符设备:

1.alloc_chrdev_region :动态分配主设备号和次设备号,输出到dev_t参数中。由MAJOR(dev_t),MINOR(dev_t)获取。

2.cdev_init(&cdev, &hello_fops);//初始化cdev,将字符设备的相关操作函数指针付给cdev的成员ops

3.cdev_add:将字符设备加入到系统中。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值