您的位置:首页 > 其它

BQ27501驱动和用户空间交互数据

2012-04-10 19:22 435 查看
内核中的数据与用户空间数据交互常用的函数有copy_to_user,copy_from_user,和宏定义put_user,get_user,__put_user,__get_user。copy_from_user和copy_to_user函数复制块数据,如数组,结构体;put_user,get_user,__put_user,__get_user复制的内存是简单类型,如char,int,long,而且只能复制1,2,4,8个字节。put_user,get_user,__put_user,__get_user执行效率比copy_to_user,copy_from_user的效率要高很多。put_user和__put_user区别在于,前者会调用access_ok进行内核地址的检查,而后者不进行地址检查。bq27501驱动的功能是向用户空间提供电池相关的信息;而且不需要用户空间向电池输入数据;另外电池的信息都是很小的数据,都可以使用unsigned short表示,所以没有必要使用copy_to_user块数据传递的函数;另外再根据《Linux驱动程序》书中“大多数驱动程序代码中都不需要access_ok,内存管理程序会处理它”,所以选择__put_user来向用户空间传递电池信息数据。

__put_user(var, ptr),var将内核中的数据var复制到用户空间;ptr是用户地址空间的指针,指向内核空间中ioctl最后一个参数。bq27501与用户空间交互的代码片段如下:
static long bq27501_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
BATT_INFO *pBattInfo = &BattInfo;
unsigned short temp;
switch(cmd)
{
case GET_RM:
if((i2c_read_reg(&bq27501_i2c_client,RM_REG_ADDR_L, &pBattInfo->RemainingCapacity))>=0){
printk(KERN_ALERT"RaminingCapacity is %u mAh ...\n",pBattInfo->RemainingCapacity);
__put_user(pBattInfo->RemainingCapacity, (int __user *)arg);
}
break;
……
}
在用户空间, ioctl 系统调用的原型为:int ioctl(int fd, unsigned long cmd, ...); 这个原型中的点表示函数有一个单个可选的参数, 传统上标识为 char *argp. 这些点在那里只是为了阻止在编译时的类型检查。第二个参数,是用户向驱动传递的命令(如读取剩余电量值)。第三个参数的实际特点依赖所发出的特定的控制命令,即第二个参数。一些命令不用参数, 一些用一个整数值, 以及一些使用指向其他数据的指针。是否使用参数和指针是根据打开字符设备的方式决定,打开设备的方式有三种,在fcntl.h有其宏定义,只读,只写,读写,如下所示:
#define O_RDONLY	     00
#define O_WRONLY	     01
#define O_RDWR		     02
用户空间读取驱动中参数代码片段如下:
if((fd = open("/dev/bq27501",2)) == -1)
{
perror("device open err!\n");
return -1;
}
printf("open ok!\n");
ioctl(fd,atoi(argv[1]),&v); //v是一个整型,用于保存内核空间传递过来的数据
printf("(2)........cmd = [%d],val = [%d]...........\n",atoi(argv[1]),v);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: