我尝试将数据从用户空间发送到驱动程序,然后从驱动程序发送到用户空间。我使用copy_from_user和copy_to_user。 我可以将数据从用户发送到驱动程序,但是当我尝试使用copy_to_user时,我遇到了问题 - 数据没有发送。我使用printk来查找错误,在my_read中,message_buf具有正确的值,但不是。
我使用mmap,也许这里有错误?
司机:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/sem.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include <linux/ipc.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/scatterlist.h>
#include <linux/mm.h>
#include "query_ioctl.h"
#define FIRST_MINOR 0
#define MINOR_CNT 1
#define BUFSIZE 30
#define PCI_VENDOR_ID_WZAB 0xabba
#define PCI_DEVICE_ID_WZAB_WZADC1 0x0133
static dev_t dev;
static struct cdev c_dev;
static struct class *cl;
//static char buf[] = " ";
int buffsize = 0;
char *message_buf;
char *write_buf;
struct semaphore sem;
static const struct vm_operations_struct mod_mem_ops = {
};
static int my_open(struct inode *i, struct file *f) {
message_buf = kmalloc(BUFSIZE, GFP_KERNEL);
if(down_interruptible(&sem))
{
printk("KERN_ALERT device is already held ..cant be opened\n");
return -1;
}
else
{
printk("KERN_ALERT device opened\n");
return 0;
}
}
static int my_mmap(struct file *filp, struct vm_area_struct *vma) {
size_t size = vma->vm_end - vma->vm_start;
vma->vm_ops = &mod_mem_ops;
vma->vm_pgoff = virt_to_phys(message_buf)>>PAGE_SHIFT;
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, vma->vm_page_prot)){
return -EAGAIN;
}
return 0;
}
static ssize_t my_read(struct file *f, char *buf, size_t len, loff_t *f_pos){
int retval;
ssize_t bytes;
if(buffsize < len)
bytes = buffsize;
else
bytes = len;
retval = copy_to_user(buf, message_buf, sizeof(message_buf));
printk("read %d bytes as : %s \n", retval, buf);
printk(KERN_INFO "message read: %s \n", message_buf);
printk(KERN_INFO "buf : %s \n", buf);
if (retval){
printk(KERN_INFO "copy_to_user fail");
return -EFAULT;
}
else
{
printk(KERN_INFO "copy_to_user successed\n");
buffsize -= bytes;
return bytes;
}
}
static ssize_t my_write(struct file *f, char *buf, size_t len, loff_t *f_pos){
int retval;
memset(message_buf, 0, BUFSIZE);
if (len >BUFSIZE)
len = BUFSIZE;
retval = copy_from_user(message_buf, buf, len);
printk("write %d bytes as : %s \n", retval, message_buf);
printk("buf write : %s \n", buf);
buffsize = len;
return len;
}
static ssize_t my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
size_t len;
switch (cmd) {
case GET_VARIABLES:
/*//funkcja kodująca - arg buf
encode(buf);
strcpy(d.bufor_enc, buf);
//printk("temp2 : %s zmienna ", d.bufor_enc);
if (copy_to_user((data *) arg, &d, sizeof(data)))
{
return -EACCES;
}
*/
len = strlen(message_buf);
my_read(f, (char*)arg, len, 0);
break;
case SET_VARIABLES:
len = strlen((char *)arg);
my_write(f, (char*)arg, len, 0);
/* if (copy_from_user(&d, (data *) arg, sizeof(data)))
{
return -EACCES;
}
strcpy(buf, d.bufor_mess);
*/
break;
default:
return -EINVAL;
}
return 0;
}
static int my_close(struct inode *i, struct file *f) {
up(&sem);
return 0;
}
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = my_open,
.release = my_close,
.unlocked_ioctl = my_ioctl,
.mmap = my_mmap
};
static int __init ioctl_init(void) {
int ret;
struct device *dev_ret;
sema_init(&sem,1);
if ((ret = alloc_chrdev_region(&dev, FIRST_MINOR, MINOR_CNT, "query_ioctl")) < 0) {
return ret;
}
cdev_init(&c_dev, &fops);
if ((ret = cdev_add(&c_dev, dev, MINOR_CNT)) < 0) {
return ret;
}
if (IS_ERR(cl = class_create(THIS_MODULE, "char"))) {
cdev_del(&c_dev);
unregister_chrdev_region(dev, MINOR_CNT);
return PTR_ERR(cl);
}
if (IS_ERR(dev_ret = device_create(cl, NULL, dev, NULL, "query"))) {
class_destroy(cl);
cdev_del(&c_dev);
unregister_chrdev_region(dev, MINOR_CNT);
return PTR_ERR(dev_ret);
}
return 0;
}
static void __exit ioctl_exit(void) {
device_destroy(cl, dev);
class_destroy(cl);
cdev_del(&c_dev);
unregister_chrdev_region(dev, MINOR_CNT);
}
module_init(ioctl_init);
module_exit(ioctl_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anna Czabatorowicz");
MODULE_DESCRIPTION("Encoder Driver");
APP:
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include "query_ioctl.h"
char number_sem = 0;
int choose_option();
void get_vars(int fd)
{
data d;
if (ioctl(fd, GET_VARIABLES, &d) == -1)
{
perror("get data not access");
}
else
{
printf("Character sequence to encoder : %s\n", d.var);
}
}
void clr_vars(int fd)
{
if (ioctl(fd, CLR_VARIABLES) == -1)
{
perror("character sequence clr");
}
}
void set_vars(int fd)
{
char v[30];
data d;
printf("Enter character sequence - max 30 char: ");
scanf("%s", v);
getchar();
strcpy(d.var, v);
if (ioctl(fd, SET_VARIABLES, &d) == -1)
{
perror("character sequence not set");
}
}
int main(int argc, char *argv[]){
char *file_name = "/dev/query";
int fd;
//int option;
fd = open(file_name, O_RDWR);
if (fd == -1)
{
perror("query_apps not open");
return 2;
}
//option = choose_option();
/**
switch (option)
{
case 1:
get_vars(fd);
break;
case 2:
clr_vars(fd);
break;
case 3:
set_vars(fd);
break;
default:
break;
}
**/
number_sem = fork();
set_vars(fd);
get_vars(fd);
clr_vars(fd);
close(fd);
return 0;
}
头文件:
#ifndef QUERY_IOCTL_H
#define QUERY_IOCTL_H
#include <linux/ioctl.h>
#define GET_VARIABLES _IOR('d', 1, data *)
#define CLR_VARIABLES _IO('d', 2)
#define SET_VARIABLES _IOW('d', 3, data *)
#endif