Пишу свой первый драйвер (модуль ядра) под linux. И вот наткнулся
на интересную фишку. В функциях dev_read() и dev_write()
забыл поставить copy_to_user() и copy_from_user() соответственно.
Самое интересное что обнаружил это только через несколько дней.
Все это время драйвер исправно работал. Кто нибудь из kernel guru
может пояснить почему так получилось. Интересно просто..
Ядро у меня 2.4.18, компилятор 2.95.3
// reads from the internal memory of a device, automatically selects HPI or DMA
// depending on block size and memory region (some are not accessible via DMA)
static ssize_t dev_read(struct file *f, char *buf, size_t len, loff_t *off)
{
struct dev_res *dev;
unsigned dsp_addr = *off;
DECLARE_WAITQUEUE(wait, current);
ssize_t retval;
dprintk("dev_read \n");
if(!(dev = dev_ptr(f)))
return -EINVAL;
if(should_use_hpi(dev, dsp_addr, len)) {
dprintk("hpi_read: addr 0x%x len %d \n", dsp_addr, len);
if(hpi_read(dev, dsp_addr, (unsigned *)buf, len/4) == -1)
return -EAGAIN;
return len;
}
dprintk("dma_read: addr 0x%x len %d \n", dsp_addr, len);
spin_lock_irq(&dev_lock);
dev->is_reading = 1;
spin_unlock_irq(&dev_lock);
dma_read(dev, dsp_addr, len);
add_wait_queue(&dev_waitq, &wait);
current->state = TASK_INTERRUPTIBLE;
while(1) {
int is_reading;
spin_lock_irq(&dev_lock);
is_reading = dev->is_reading;
spin_unlock_irq(&dev_lock);
if(!is_reading)
break;
if(f->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
goto out1;
}
if(signal_pending(current)) {
retval = -ERESTARTSYS;
goto out1;
}
schedule();
}
copy_to_user(buf, (void *)dev->dma_buf, len);
retval = len;
out1:
current->state = TASK_RUNNING;
remove_wait_queue(&dev_waitq, &wait);
return retval;
}