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

来源:互联网 发布:mac系统qq开视频播放器 编辑:程序博客网 时间:2024/05/16 11:28
一、新建新的驱动程序目录:
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.hcdev.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:将字符设备加入到系统中。





原创粉丝点击