首页 > 解决方案 > Book Linux device driver 3rd 中关于循环缓冲区中断处理程序的问题

问题描述

我正在阅读 LLDR3,在“实现处理程序”部分中对 P.271 有疑问

底部是我有问题的代码:

我看到writer ( ISR )reader ( ISR 唤醒 ) 他们正在触及同一个缓冲区 ( short_queue ),因为他们正在触及共享资源,不担心“ short_i_read ”被打断的情况由编写器 ISR 在缓冲区工作时执行?

我可以理解 ISR 编写器不会被中断,因为它是 ISR,通常 IRQ 将被禁用直到完成。但是对于缓冲区读取 "short_i_read" ,我看不到任何地方可以保证原子操作。

我注意到的一件事是:

这是否意味着这里的代码让写入器和读取器只接触不同的变量以实现无锁循环缓冲区

irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
    struct timeval tv;    
    int written;
    do_gettimeofday(&tv);
    /* Write a 16 byte record. Assume PAGE_SIZE is a multiple of 16 */
    written = sprintf((char *)short_head,"%08u.%06u\n", (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec));    
    BUG_ON(written != 16);
    short_incr_bp(&short_head, written);
    wake_up_interruptible(&short_queue);
    /* awake any reading process */
    return IRQ_HANDLED; 
}


static inline void short_incr_bp(volatile unsigned long *index, int delta) {
    unsigned long new = *index + delta;
    barrier();  /* Don't optimize these two together */
    *index = (new >= (short_buffer + PAGE_SIZE)) ? short_buffer : new; 
}

ssize_t short_i_read (struct file *filp, char __user *buf, size_t count,     loff_t *f_pos) 
{
    int count0;
    DEFINE_WAIT(wait);
    while (short_head == short_tail) {
        prepare_to_wait(&short_queue, &wait, TASK_INTERRUPTIBLE);
        if (short_head == short_tail)
            schedule();
        finish_wait(&short_queue, &wait);
        if (signal_pending (current))  /* a signal arrived */
            return -ERESTARTSYS; /* tell the fs layer to handle it */    
    }    
    /* count0 is the number of readable data bytes */
    count0 = short_head - short_tail;
    if (count0 < 0) /* wrapped */
    count0 = short_buffer + PAGE_SIZE - short_tail;
    if (count0 < count) count = count0;
    if (copy_to_user(buf, (char *)short_tail, count))
        return -EFAULT;
    short_incr_bp (&short_tail, count); 
    return count; 
}

标签: linuxlinux-device-driverdevicelock-freecircular-buffer

解决方案


推荐阅读