Linux 字符驱动程序 : blocking ioctl call

标签 linux linux-kernel linux-device-driver ioctl

我是驱动程序开发的新手,我正在尝试编写一个简单的 char 驱动程序,它具有 ioctl,允许用户进程获取我的 char 驱动程序上次读取和写入的时间 (timespec)。

long charmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
    struct charmem_dev *dev = filp->private_data;

    if (down_interruptible(&dev->sem)) {
        printk(KERN_WARNING "I got booted!!\n");
        return -ERESTARTSYS;
    }

    printk(KERN_WARNING "charmem: in ioctl; cmd = %d, arg = %d\n", (int)cmd, (int)arg);
    switch(cmd) {
        case IOCTL_GET_LAST_READ_TIME:
            printk("charmem_ioctl: returning last read time delta, exiting...\n");
            up(&dev->sem);
            return dev->last_read_delta.tv_nsec;
            break;

        case IOCTL_GET_LAST_WRITE_TIME:
            printk("charmem_ioctl: returning last write time delta, exiting...\n");
            up(&dev->sem);
            return dev->last_write_delta.tv_nsec;
            break;

        case IOCTL_RESET_READ: /*return read-pointer to the start of buffer*/
            dev->rp = dev->buffer;
            break;
        case IOCTL_RESET_WRITE: /*return write-pointer to the start of buffer*/
            dev->wp = dev->buffer;
            break;
        case IOCTL_LOAD_BUFFER_TO_CACHE:
            load_buffer_to_cache(dev->buffer, dev->buffer_size);
            break;
        default:
            printk("charmem_ioctl: invalid ioctl command, exiting...\n");
            up(&dev->sem);
            return -EFAULT;
    }

    up(&dev->sem);
    return 0;
}

struct file_operations charmem_fops = {
    .owner = THIS_MODULE,
    .llseek = no_llseek,
    .read = charmem_read,
    .write = charmem_write,
    .unlocked_ioctl = charmem_ioctl,
    .open = charmem_open,
    .release = charmem_release,
};

main.c -- 测试我的字符设备的用户程序:

int fd = 0, ret = 0;
fd = open("/dev/charmem0", O_RDWR);
if (fd < 0) {
    printf("/dev/charmem0  unable to access (fd = %d)... EXITING\n", fd);
    return -1;
}

ret = write(fd,msg1,10);
ret = read(fd,user_buffer,10);
read_delta = ioctl(fd, IOCTL_GET_LAST_READ_TIME);
printf("read_delta : %d\n ", read_delta);
write_delta = ioctl(fd, IOCTL_GET_LAST_WRITE_TIME);
printf("write_delta : %d\n ", write_delta);

main.c 是测试我的字符设备的程序;程序在打印出 read_delta 值后阻塞,我假设它阻塞在 ioctl 上。我的代码哪里做错了?

最佳答案

我没有发现您的代码中信号量的上/下有任何问题。您的程序最有可能阻塞的地方是对 down_interruptible() 的调用。如果你按下 control-c,这将强制 down_interruptible 返回,你应该在 dmesg 或你的控制台或系统日志中看到你的“我被引导”的 printk。然后任务是找出驱动程序中还有什么其他东西持有该信号量。

我想到的另一个想法是……printf 被缓冲了。因此,您的 GET_LAST_WRITE_TIME ioctl 可能确实返回了,并且输出在 stdout 缓冲区中,并且您的程序实际上卡在了更下方的一些代码上。建议在 printf("write delta... 之后添加一个 fflush(stdout) 以消除这种可能性。

迈克尔

关于Linux 字符驱动程序 : blocking ioctl call,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9426606/

相关文章:

linux - Git 从部分存储库中提取?

linux - 如何识别 linux block 设备的请求队列

linux - virtio中guest notifier和host notifier为什么分别使用ioeventfd和irqfd?

linux - 打印到内核日志的限制

linux - Linux内核如何产生方波

linux - 当你给它一个服务的默认端口号时返回一个服务名称的脚本

Linux 打开默认终端文本编辑器

linux - AF-XDP : Is there a bug regarding small packets?

linux - 如何打开/关闭 Linux 内核 Virtio 功能?

memory - 保留内存的设备驱动程序