linux - Book Linux device driver 3rd 中关于循环缓冲区中断处理程序的问题
问题描述
我正在阅读 LLDR3,在“实现处理程序”部分中对 P.271 有疑问
底部是我有问题的代码:
我看到writer ( ISR )和reader ( ISR 唤醒 ) 他们正在触及同一个缓冲区 ( short_queue ),因为他们正在触及共享资源,不担心“ short_i_read ”被打断的情况由编写器 ISR 在缓冲区工作时执行?
我可以理解 ISR 编写器不会被中断,因为它是 ISR,通常 IRQ 将被禁用直到完成。但是对于缓冲区读取 "short_i_read" ,我看不到任何地方可以保证原子操作。
我注意到的一件事是:
- 缓冲区写入器(ISR)仅在 short_head 上增加
- 缓冲区阅读器仅在 short_tail 上增加
这是否意味着这里的代码让写入器和读取器只接触不同的变量以实现无锁循环缓冲区?
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;
}
解决方案
推荐阅读
- php - 在 php 中为动态生成的链接设置活动类
- ssl - nginx ssl 设置 servernotfound 和 error.log 文件为空
- java - 使用 HTMLUNIT 从本地 html 文件中读取 html
- r - 以不同方式对具有数字索引的 data.table 列进行子集时的不同结果
- c# - 使用 MediaComposition 将立体声 .mp4 文件中的音频转码为单声道 WAV 16KHz
- tfs - 使用 VS Code 将文件夹添加到 TFVC
- c++ - 将 3D 矢量浮点数打包成 unsigned int 并将其解包
- angular - 如何限制angular2下拉列表中的重复值
- gmail - 如何在新版 Gmail 中禁用智能回复?
- sql - 如何将列转换为行并替换列名