android分层学习笔记(五)
来源:互联网 发布:淘宝网男童保暖内衣 编辑:程序博客网 时间:2024/05/22 10:29
在android系统中,以上几个小节文章中,把它的分层做了一些简单的描述,接下就是内核驱动相关的内容。这是一个自由的世界,当然很复杂。也正是因为自由,才可以构建不同的操作系统世界,android是其中之一。不管android是不是传统意义上的linux上的操作系统,它毕竟实现了一些很有用的东西。
对于内核这里不想详细展开,毕竟自己的功底也有限。单说一些简单的驱动。事实上,自己所接触的驱动颇为简单,无外乎管脚的控制。下面以一个简单char驱动来说明android底层的东西,其实就是linux驱动内容:
对于驱动开发,那么肯定是要看“Linux设备驱动程序第三版2.6”(LDDP)这本书了。目前已经是2.6版本了,有中文版本。
看完这本书,再看以下例子,你会觉得非常简单。不看那本书,按照以下例子,当然也可以写一个简单的驱动程序,需要注意的下面的例子是字符驱动。
写linux下驱动有一个框架,一般来说完成以下几个函数就可以了。
xxx_read(struct file *filp, char __user*buff, size_t count, loff_t *offp)
xxx_write(struct file *filp, const char__user *buff, size_t count, loff_t *offp)
xxx_open(struct inode *inode, struct file*filp)
xxx_release(struct inode *inode, structfile *filp)
xxx_ioctl(struct inode *inode, struct file*file,
unsignedint cmd, unsigned long arg)
static int __init xxx_init(void)
static void __exit xxx_exit(void)
module_init(xxx_init);
module_exit(xxx_exit);
实际应用中,字符驱动write/read函数很少用到。一般也可以不实现,可以由ioctl函数来实现。
驱动与应用程序接口函数对应,看驱动函数的名字就知道了。
xxx_read <---> read
xxx_write <---> write
xxx_open <---> open
xxx_release <---> close
xxx_ioctl <---> ioctl
也就是说,在应用程序调用read,write,open,ioctl函数,最终就是调用其驱动的对应的函数。
在insmod时,会调用xxx_init
在rmmod时,会调用xxx_exit
对于xxx_init函数,那么要实现的东西比较多,比如io口的设置,或其他变量的初始赋值,驱动的注册,设备节点的创建等。相应地,xxx_exit就完成xxx_init所做事下结逆过程。此处详说:
每个驱动都有一个主设备号和次设备号,可以固定设置,但不能有冲突。最好的方法是系统分配,这也是LDDP作者所建议的。
static structfile_operations xxx_fops =
{
.owner = THIS_MODULE,
.open = xxx_open,
.release = xxx_release,
.ioctl = xxx_ioctl,
.read = xxx_read,
.write = xxx_write,
};
struct cdev xxx_cdev;
struct class *xxx_class;
Intxxx_init(void)
{
int res, err;
dev_t dev = MKDEV(xxx_major, 0);
if (xxx_major)
{
res = register_chrdev_region(dev, 1,DEVICE_NAME); //固定分配
}
else
{
res = alloc_chrdev_region(&dev, 0,1, DEVICE_NAME);//动态分配
xxx_major = MAJOR(dev);
}
if (res < 0)
{
printk("xxx_device: unable to getmajor %d/n", xxx_major);
return res;
}
if (xxx_major == 0)
{
xxx_major = res;
}
cdev_init(&xxx_cdev, &xxx_fops);
xxx_cdev.owner = THIS_MODULE;
xxx_cdev.ops = &xxx_fops;
err = cdev_add (&xxx_cdev, dev, 1);//注册cdev
if (err)
{
printk ("Error %d adding xxx%d",err, 0);
}
xxx_class = class_create(THIS_MODULE,"xxx_class");
device_create(xxx_class, NULL, dev,DEVICE_NAME, "xxx%d", 0);
other_init();
}
int xxx_exit(void)
{
xxx_release(NULL, NULL);
cdev_del(&xxx_cdev);
device_destroy(xxx_class, MKDEV(xxx_major, 0));
class_destroy(xxx_class);
unregister_chrdev_region(MKDEV(xxx_major, 0), 1);
}
对于xxx_open, 可以简单提示一些信息,表示此驱动加载。同样xxx_release也可以用简单的提示一些信息,表明关闭驱动了。
重点是在xxx_ioctl函数,我们基本所有的操作就在这里了。
static intepi_ioctl(struct inode *inode, struct file *file,
unsigned intcmd, unsigned long arg)
{
char val = 1;
switch (cmd)
{
case IO_CMD_TEST_SET:
copy_from_user(&val, (char *)arg, 1);
printk(“%d”, val);
break;
case IO_CMD_TEST_GET:
copy_to_user( (char *)arg, &val, 1);
break;
default:
break;
}
return 0;
}
以上所实现的是从arg中取得数据,把数据放到arg中两个功能。用到了copy_from_usr和copy_to_usr两个函数。为什么有这两个函数:是因为驱动是工作内核空间,应用程序是工作在用户空间。如果直接用memcpy这些函数,可能内核空间的数据已经实效,那么复制到用户空间的则可能得到错误的信息。
写完驱动,就可进行编译,那么要写Makefile以方便编译。
obj-m += xxx.o
#内核代码树位置
KDIR:=/home/alsa/kernel/linux_2.6.28
#设置编译器
CROSS_COMPILE = arm-none-linux-gnueabi-
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
PWD=$(shell pwd)
all: build install
build: clean
$(MAKE)-C $(KDIR) M=$(PWD) modules
clean:
rm-rf *.o *.ko
保存,后运行make,则在当前目录下生成xxx.ko文件。
最后通过加载驱动:
加载: insmod xxx.ko
卸载: rmmod xxx
- android分层学习笔记(五)
- android 分层学习笔记
- android分层学习笔记(一)
- android分层学习笔记(二)
- android分层学习笔记(三)
- android分层学习笔记(四)
- Android学习笔记(五)
- android学习笔记(五)
- Android学习笔记(五)
- Android学习笔记(五)
- Android学习笔记五
- Android 学习笔记(五)
- Android开发学习笔记(五)Android五大布局
- Spring笔记之五(分层 Bean Factory 使用)
- 游戏开发笔记(五)——服务端系统分层
- Isometric Game Programming 笔记(五)分层绘制物体
- Android分层架构笔记
- Android学习笔记(五):AndroidDebug
- 诚求一毕业课题“基于flex架构的企业管理系统的研究与实现”
- sqlserver 2000 sp3补丁
- 客户要的是简约不是简单!
- 在Delphi中实现将Font.Style写入INI文件
- LR监控服务器以及在服务器上安装rstatd守护进程
- android分层学习笔记(五)
- 设计模式之工厂方法模式
- SQL中用到的基本函数(备用)
- 浅析JSP开发中的对象和范围属性
- system.map文件分析
- window启动过程详解
- 设计模式之观察者模式
- 初到乍来
- diff patch 代码补丁