Linux Char Driver: блокировка вызова ioctl - PullRequest
0 голосов
/ 24 февраля 2012

Я новичок в разработке драйверов, и я пытаюсь написать простой драйвер char с ioctl, который позволяет пользовательскому процессу получать время (временную спецификацию), которое мой драйвер char выполнял при последнем чтении и записи.

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. Что я делаю не так в своем коде?

1 Ответ

2 голосов
/ 15 марта 2012

Я не вижу проблем с увеличением / уменьшением семафора в вашем коде. Наиболее вероятное место, которое блокирует ваша программа, - это вызов down_interruptible (). Если вы нажмете control-c, это заставит down_interruptible вернуться, и вы должны увидеть свой printk «Я загрузился» в dmesg или в вашей консоли или syslog. Тогда задача состоит в том, чтобы выяснить, что еще в вашем драйвере содержит этот семафор.

Еще одна мысль, которая приходит мне в голову ... printf буферизируется. Поэтому возможно, что ваш ioctl GET_LAST_WRITE_TIME действительно возвратился, и вывод находится в буфере stdout, и ваша программа фактически застряла в каком-то коде ниже. Рекомендуем добавить fflush (stdout) после printf («написать дельту ...», чтобы исключить эту возможность.

Michael

...