Я пишу модуль ядра, который включает операции ioctl на символьных устройствах. Мой драйвер принимает вызовы ioctl, и я хочу передать некоторые данные из пространства ядра в пространство пользователя. У меня проблемы с передачей больших структур данных. Мне интересно, есть ли способ решить эту проблему и как-то обойти это ограничение.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include "ioctl_def.h"
typedef struct
{
char data[9999];
} DATA;
#define MAGIC 'v'
#define IOCTL_GET_DATA _IOR(MAGIC, 1, DATA)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Noob");
MODULE_DESCRIPTION("Test module");
MODULE_VERSION("0.01");
#define MAJOR 400
#define NAME "vdev"
static void __exit modexit(void)
{
printk(KERN_INFO "Modexit\n");
unregister_chrdev(MAJOR, NAME);
}
static int dev_open( struct inode *n, struct file *f )
{
printk(KERN_INFO "Devopen\n");
try_module_get(THIS_MODULE);
return 0;
}
static int dev_release( struct inode *n, struct file *f )
{
printk(KERN_INFO "Devrelease\n");
module_put(THIS_MODULE);
return 0;
}
static long dev_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
printk("dev_ioctl cmd: %d\n", cmd);
if((_IOC_TYPE(cmd) != MAGIC))
{
return -ENOTTY;
}
switch(cmd)
{
case IOCTL_GET_DATA:
{
printk("IOCTL_GET_DATA: %d\n", cmd);
DATA d;
memset(&d, 0, sizeof(DATA));
snprintf(d.data, sizeof(d.data), "%s", "Hello");
copy_to_user((void*)arg, &d, _IOC_SIZE(cmd));
}
break;
}
return 0;
}
static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
printk("input length: %d\n", count);
char* data = kmalloc(count, GFP_KERNEL);
memset(data, 0, count);
if (copy_from_user(data + *offset, buf, (unsigned long)count))
{
printk("read error!\n");
}
else
{
if (data[count - 1] == 10) // ascii line feed dec = 10
{
data[count - 1] = 0;
}
printk("%s", data);
}
kfree(data);
return count;
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
.open = dev_open,
.write = dev_write,
.release = dev_release,
// .read = dev_read,
.unlocked_ioctl = dev_ioctl
};
static int __init modinit(void)
{
printk(KERN_INFO "Modinit\n");
unregister_chrdev(MAJOR, NAME);
int ret = register_chrdev(MAJOR, NAME, &fops);
if( ret < 0 )
{
printk(KERN_ERR "Could not register chardev\n" );
}
printk(KERN_ERR "Device initialized\n" );
return ret;
}
module_init(modinit);
module_exit(modexit);
Текущий код компилируется, но размер данных недостаточен для моего приложения в пользовательском пространстве. Однако всякий раз, когда я увеличиваю массив для хранения большего количества данных, например
typedef struct
{
char data[99999];
} DATA;
Код не скомпилируется, и возникает следующая ошибка:
vdev.c:54:3: error: case label does not reduce to an integer constant
case IOCTL_GET_DATA:
^~~~