Я читаю LLDR3, у меня есть вопрос по P.271 в разделе " Реализация обработчика * "
Внизу приведены коды, у меня есть вопросы:
Я вижу writer (ISR) и reader (который активируется ISR), они касаются одного и того же буфера ( short_queue ), поскольку они касаются общегоресурс, разве это не беспокоит случай, когда " short_i_read " был прерван ISR модуля записи, когда он работает с буфером?
Я могу понять, что модуль ISR Writer не будет прерван, посколькуэто 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;
}