当前位置: 技术问答>linux和unix
问下关于put_user问题
来源: 互联网 发布时间:2016-09-25
本文导语: 我想从GPIO寄存器读数据到用户空间,在驱动中用了put_user 问下用户态怎样调用这个,还有我想把读出的数据先放到内核的buf中然后再传到用户态,怎样做 谁有简单的事例程序帮忙写下 | 早就...
我想从GPIO寄存器读数据到用户空间,在驱动中用了put_user
问下用户态怎样调用这个,还有我想把读出的数据先放到内核的buf中然后再传到用户态,怎样做
谁有简单的事例程序帮忙写下
问下用户态怎样调用这个,还有我想把读出的数据先放到内核的buf中然后再传到用户态,怎样做
谁有简单的事例程序帮忙写下
|
早就知道你这100分不好拿
不管是put_user ,还包括IOCTL 的头文件的写法,而一般涉及到ioctl的问题我都不太想答,细节量还是蛮大的,需要几百字才能说清,网上没好资料,我也是从《Linux设备驱动开发技术及应用》这本书上学到的,其他的书几乎就是一笔带过
int at_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
看得出来是一个只需要读取返回值的函数,这个命令需要自己定义头文件,且驱动和应用程序都要包含这个头文件
假设这个命令为第一个,所以基数为0,参数为long型
所以头文件 test_ioctl.h 写为:
#ifndef _TEST_IOCTL__
#define _TEST_IOCTL__ 1
#define IOCTLTEST_MAGIC 'x'
#define IOCTLTEST_AT _IOR(IOCTLTEST_MAGIC,0,long)
#endif
在看你的问题:比如put_user(val,(long *)arg);这个(long *)arg是不是要在内核态定义一个long型的指针或数组,还有在应用层&i是什么?应该在应用层怎样来对应驱动层的程序?
--------------------------------------------------------------
这个arg就是用户传递的参数i :ioctl(fd,IOCTLTEST_AT,&i);
你要在用户程序里定义 long i;
通过这个cmd - IOCTLTEST_AT ,内核和应用程序就对上了嘛
不管是put_user ,还包括IOCTL 的头文件的写法,而一般涉及到ioctl的问题我都不太想答,细节量还是蛮大的,需要几百字才能说清,网上没好资料,我也是从《Linux设备驱动开发技术及应用》这本书上学到的,其他的书几乎就是一笔带过
int at_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
看得出来是一个只需要读取返回值的函数,这个命令需要自己定义头文件,且驱动和应用程序都要包含这个头文件
假设这个命令为第一个,所以基数为0,参数为long型
所以头文件 test_ioctl.h 写为:
#ifndef _TEST_IOCTL__
#define _TEST_IOCTL__ 1
#define IOCTLTEST_MAGIC 'x'
#define IOCTLTEST_AT _IOR(IOCTLTEST_MAGIC,0,long)
#endif
在看你的问题:比如put_user(val,(long *)arg);这个(long *)arg是不是要在内核态定义一个long型的指针或数组,还有在应用层&i是什么?应该在应用层怎样来对应驱动层的程序?
--------------------------------------------------------------
这个arg就是用户传递的参数i :ioctl(fd,IOCTLTEST_AT,&i);
你要在用户程序里定义 long i;
通过这个cmd - IOCTLTEST_AT ,内核和应用程序就对上了嘛
|
小伙, 从你你能看到的 /dev/*** 设备名称说起
user 部分, 就是你的应用程序调用, FILE * : open read write ...
Kernel部分, 系统调用层, 这个是系统的事情了: vfs, vfs_read ...
Kernel部分, Driver 层, 如果你写驱动, 这个又是你的事情了: 对应的 ***_open(struct inode *inode, struct file *file) write
..
当你在read 的时候, 一直调用到***_open ,***_read , 如果没数据可能就阻塞或者直接返回, 取决于FOPEN 的属性, ***_read 的时候, 数据来源就是 put_user 了.
一个很典型的例子: linuxdriverscharcs5535_gpio.c cs5535_gpio_read 就完全这么做的
如果你能坚持从vfs -> inode -> cdev 一路看下来, 那么你会开阔很多了.
user 部分, 就是你的应用程序调用, FILE * : open read write ...
Kernel部分, 系统调用层, 这个是系统的事情了: vfs, vfs_read ...
Kernel部分, Driver 层, 如果你写驱动, 这个又是你的事情了: 对应的 ***_open(struct inode *inode, struct file *file) write
..
当你在read 的时候, 一直调用到***_open ,***_read , 如果没数据可能就阻塞或者直接返回, 取决于FOPEN 的属性, ***_read 的时候, 数据来源就是 put_user 了.
一个很典型的例子: linuxdriverscharcs5535_gpio.c cs5535_gpio_read 就完全这么做的
如果你能坚持从vfs -> inode -> cdev 一路看下来, 那么你会开阔很多了.
|
驱动:
/*
* char-read.c
*
* Character driver with read operation
*
* Copyright (C) 2005 Farsight
*
* 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; either version 2 of the License, or
* (at your option) any 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.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include
#include
#include
#include
#include
#include
MODULE_LICENSE ("GPL");
int hello_major = 253;
int hello_minor = 0;
int number_of_devices = 1;
char data[50]="foobar not equal to barfoo";
struct cdev cdev;
dev_t dev = 0;
static int hello_open (struct inode *inode, struct file *file)
{
printk (KERN_INFO "Hey! device openedn");
return 0;
}
static int hello_release (struct inode *inode, struct file *file)
{
printk (KERN_INFO "Hmmm... device closedn");
return 0;
}
ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp)
{
ssize_t result = 0;
/*这里的buff仅是演示如把内核空间的变量传递给用户空间*/
if (copy_to_user (buff, data, sizeof(data)-1))
result = -EFAULT;
else
printk (KERN_INFO "wrote %d bytesn", count);
return result;
}
ssize_t hello_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
ssize_t ret = 0;
printk (KERN_INFO "Writing %d bytesn", count);
if (count>127) return -ENOMEM;
if (count
/*
* char-read.c
*
* Character driver with read operation
*
* Copyright (C) 2005 Farsight
*
* 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; either version 2 of the License, or
* (at your option) any 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.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include
#include
#include
#include
#include
#include
MODULE_LICENSE ("GPL");
int hello_major = 253;
int hello_minor = 0;
int number_of_devices = 1;
char data[50]="foobar not equal to barfoo";
struct cdev cdev;
dev_t dev = 0;
static int hello_open (struct inode *inode, struct file *file)
{
printk (KERN_INFO "Hey! device openedn");
return 0;
}
static int hello_release (struct inode *inode, struct file *file)
{
printk (KERN_INFO "Hmmm... device closedn");
return 0;
}
ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp)
{
ssize_t result = 0;
/*这里的buff仅是演示如把内核空间的变量传递给用户空间*/
if (copy_to_user (buff, data, sizeof(data)-1))
result = -EFAULT;
else
printk (KERN_INFO "wrote %d bytesn", count);
return result;
}
ssize_t hello_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
ssize_t ret = 0;
printk (KERN_INFO "Writing %d bytesn", count);
if (count>127) return -ENOMEM;
if (count