注:本文爲個人學習記錄,可能存在個別或多處錯誤,歡迎指正和討論。
新建了一個 驅動程序,提供 “/dev/sample” 設備作爲測試使用。
/*
* Sample Driver
*
* Copyright (C) 2012 Alex,All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/sample.h>
static int sample_val = 0;
static int sample_open(struct inode *node, struct file *filp)
{
printk(KERN_INFO"open sample dev done! \n");
return 0;
}
static int sample_close(struct inode *node, struct file *filp)
{
printk(KERN_INFO"close sample dev done! \n");
return 0;
}
static ssize_t sample_write(struct file *filp,const char __user *ubuf,
size_t length,loff_t *offset)
{
int rets = 0;
if(length> sizeof(sample_val))
length = sizeof(sample_val);
rets = copy_from_user(&sample_val,ubuf,length);
if(rets !=0){
printk(KERN_ERR"sample_write failed! \n");
rets = length - rets;
}else{
rets = length;
}
return rets;
}
static ssize_t sample_read(struct file *filp,char __user *ubuf,
size_t length,loff_t *offset)
{
int rets =0;
rets = copy_to_user(ubuf,&sample_val,sizeof(sample_val));
if(rets !=0){
rets = sizeof(sample_val) - rets;
printk(KERN_ERR"sample_read failed! \n");
}
else{
rets = sizeof(sample_val);
}
return rets;
}
static long sample_ioctl(struct file *filp , unsigned int cmd, unsigned long arg)
{
int ret = 0;
switch(cmd)
{
case SAMPLE_IOTEST_CMD:
printk(KERN_INFO"SAMPLE_IOTEST_SETCMD! \n");
break;
case SAMPLE_IOTEST_SETVAL:
printk(KERN_INFO"SAMPLE_IOTEST_SETVAL! \n");
if(copy_from_user(&sample_val,(int __user *)arg,sizeof(sample_val))){
ret = -EFAULT;
printk(KERN_ERR"SAMPLE_IOTEST_SETVAL failed! \n");
}
break;
case SAMPLE_IOTEST_GETVAL:
printk(KERN_INFO"SAMPLE_IOTEST_GETVAL! \n");
if(copy_to_user((int __user *)arg,&sample_val,sizeof(sample_val))){
ret = -EFAULT;
printk(KERN_ERR"SAMPLE_IOTEST_SETVAL failed! \n");
}
break;
default:
printk(KERN_ERR"unsupport commond! \n");
break;
}
return ret;
}
static struct file_operations sample_fops = {
.owner = THIS_MODULE,
.open = sample_open,
.release = sample_close,
.read = sample_read,
.write = sample_write,
.unlocked_ioctl = sample_ioctl,
};
static struct miscdevice sample_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "sample",
.fops = &sample_fops,
};
static int __init sample_init(void)
{
int rets =0;
printk("drivr sample \n");
rets = misc_register(&sample_misc);
if (rets != 0){
printk("Sample misc register failed!");
return -1;
}
return 0;
}
static void __exit sample_exit(void)
{
misc_deregister(&sample_misc);
return;
}
module_init(sample_init);
module_exit(sample_exit);
MODULE_AUTHOR("Alex");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("sample driver");
MODULE_VERSION("v0.0.1")
頭文件:
#ifndef _SAMPLE_H_
#define _SAMPLE_H_
/* ioctls
0x53 is 'S' */
#define SAMPLE_IOTEST_CMD 0x5300
#define SAMPLE_IOTEST_SETVAL 0x5301
#define SAMPLE_IOTEST_GETVAL 0x5302
#endif
Android系統中使用魔術字會報錯,直接定義數字。
頭文件路徑:
include/uapi/linux/
HAL層關聯的路徑是:
bionic/libc/kernel/uapi/linux/
關於bionic的介紹:
Bionic是Android平臺爲了使用C/C++進行原生應用程序開發所有提供的POSIX標準C庫。它是Google爲Android操作系統提供的BSD標準C庫的衍生庫。同時Bionic是專門爲移動計算而精心設計的,針對移動設備上有限的CPU週期和可用內存進行了裁剪以提高工作效率。
網上還有很多介紹。