Linux 司机。仅读取 IOCTL 命令有效
Linux Drivers. Only read IOCTL commands work
我在 Raspberry Pi 上写入 IOCTL 操作时遇到一些问题。
我的driver:
static struct file_operations st7735_syahniuk_device_fops =
{
.owner = THIS_MODULE,
.open = st7735_syahniuk_device_open,
.release = st7735_syahniuk_device_release,
.unlocked_ioctl = st7735_syahniuk_device_ioctl,
.read = st7735_syahniuk_device_read,
.write = st7735_syahniuk_device_write
};
static long st7735_syahniuk_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
...
case ST7735_SYAHNIUK_IOCTL_READ_DISPLAY_DELAY_MS:
printk(KERN_INFO "ST7735 IOCTL: Reading display delay\n");
uldata = g_display.display_thread_sleep_ms;
err = copy_to_user((void *)arg, &uldata, sizeof(uldata));
if(err) {
printk(KERN_ERR "ST7735 IOCTL: Error\n");
err = -EIO;
}
break;
case ST7735_SYAHNIUK_IOCTL_WRITE_DISPLAY_DELAY_MS:
printk(KERN_INFO "ST7735 IOCTL: Writing display delay\n");
err = copy_from_user(&uldata, (void *)arg, sizeof(uldata));
if(err) {
printk(KERN_ERR "ST7735 IOCTL: Error\n");
err = -EIO;
break;
}
g_display.display_thread_sleep_ms = uldata;
break;
}
...
}
有IOCTL命令定义:
#define MAJIC_NUM 'k'
#define ST7735_SYAHNIUK_IOCTL_READ_DISPLAY_DELAY_MS _IOR(MAJIC_NUM, 10, unsigned long)
#define ST7735_SYAHNIUK_IOCTL_WRITE_DISPLAY_DELAY_MS _IOW(MAJIC_NUM, 11, unsigned long)
有测试用户空间应用程序:
...
if(ioctl(fd, ST7735_SYAHNIUK_IOCTL_READ_DISPLAY_DELAY_MS, &display_delay_ms) < 0) {
perror("Failed to read Display Delay (ms) register");
goto finish;
}
...
if(ioctl(fd, ST7735_SYAHNIUK_IOCTL_WRITE_DISPLAY_DELAY_MS, &display_delay_ms) < 0) {
perror("Failed to write Display Delay (ms) register");
goto finish;
}
当我启动读取命令时运行良好,但写入命令出现错误 ENOTTY - 设备的 ioctl 不合适。
我已经尝试了不同的幻数,但所有读取命令都运行良好,但写入命令却不行。
加法
我用 strace 检查了 userland 应用程序,发现了一些奇怪的东西。当我打开我的设备文件时,它 return 我的文件描述符编号(例如“3”)。当我用读取命令调用 ioctl 时,strace 显示函数是用 fd=3 调用的。但是由于某种原因,fd=1 是随写命令一起传输的。为什么它用 1 (stdout) 而不是我的设备文件的 fd 调用?
原因是在其中一个读取命令之后,我的文件描述符的值与我打开设备文件时的值不同。可能导致内存泄漏。
我在 Raspberry Pi 上写入 IOCTL 操作时遇到一些问题。
我的driver:
static struct file_operations st7735_syahniuk_device_fops =
{
.owner = THIS_MODULE,
.open = st7735_syahniuk_device_open,
.release = st7735_syahniuk_device_release,
.unlocked_ioctl = st7735_syahniuk_device_ioctl,
.read = st7735_syahniuk_device_read,
.write = st7735_syahniuk_device_write
};
static long st7735_syahniuk_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
...
case ST7735_SYAHNIUK_IOCTL_READ_DISPLAY_DELAY_MS:
printk(KERN_INFO "ST7735 IOCTL: Reading display delay\n");
uldata = g_display.display_thread_sleep_ms;
err = copy_to_user((void *)arg, &uldata, sizeof(uldata));
if(err) {
printk(KERN_ERR "ST7735 IOCTL: Error\n");
err = -EIO;
}
break;
case ST7735_SYAHNIUK_IOCTL_WRITE_DISPLAY_DELAY_MS:
printk(KERN_INFO "ST7735 IOCTL: Writing display delay\n");
err = copy_from_user(&uldata, (void *)arg, sizeof(uldata));
if(err) {
printk(KERN_ERR "ST7735 IOCTL: Error\n");
err = -EIO;
break;
}
g_display.display_thread_sleep_ms = uldata;
break;
}
...
}
有IOCTL命令定义:
#define MAJIC_NUM 'k'
#define ST7735_SYAHNIUK_IOCTL_READ_DISPLAY_DELAY_MS _IOR(MAJIC_NUM, 10, unsigned long)
#define ST7735_SYAHNIUK_IOCTL_WRITE_DISPLAY_DELAY_MS _IOW(MAJIC_NUM, 11, unsigned long)
有测试用户空间应用程序:
...
if(ioctl(fd, ST7735_SYAHNIUK_IOCTL_READ_DISPLAY_DELAY_MS, &display_delay_ms) < 0) {
perror("Failed to read Display Delay (ms) register");
goto finish;
}
...
if(ioctl(fd, ST7735_SYAHNIUK_IOCTL_WRITE_DISPLAY_DELAY_MS, &display_delay_ms) < 0) {
perror("Failed to write Display Delay (ms) register");
goto finish;
}
当我启动读取命令时运行良好,但写入命令出现错误 ENOTTY - 设备的 ioctl 不合适。
我已经尝试了不同的幻数,但所有读取命令都运行良好,但写入命令却不行。
加法
我用 strace 检查了 userland 应用程序,发现了一些奇怪的东西。当我打开我的设备文件时,它 return 我的文件描述符编号(例如“3”)。当我用读取命令调用 ioctl 时,strace 显示函数是用 fd=3 调用的。但是由于某种原因,fd=1 是随写命令一起传输的。为什么它用 1 (stdout) 而不是我的设备文件的 fd 调用?
原因是在其中一个读取命令之后,我的文件描述符的值与我打开设备文件时的值不同。可能导致内存泄漏。