/* Null read succeeds. */ if (unlikely(total_len == 0)) return0;
ret = 0; __pipe_lock(pipe); // 获取管道锁
/* * We only wake up writers if the pipe was full when we started * reading in order to avoid unnecessary wakeups. * * But when we do wake up writers, we do so using a sync wakeup * (WF_SYNC), because we want them to get going and generate more * data for us. */ was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage); // 初始管道是否满 // ** 主循环:读取数据 ** for (;;) { /* Read ->head with a barrier vs post_one_notification() */ // 通过内存屏障安全获取头指针 unsignedint head = smp_load_acquire(&pipe->head); unsignedint tail = pipe->tail; unsignedint mask = pipe->ring_size - 1;
// 处理监控队列通知 #ifdef CONFIG_WATCH_QUEUE if (pipe->note_loss) { structwatch_notificationn;
if (total_len < 8) { if (ret == 0) ret = -ENOBUFS; break; }
n.type = WATCH_TYPE_META; n.subtype = WATCH_META_LOSS_NOTIFICATION; n.info = watch_sizeof(n); if (copy_to_iter(&n, sizeof(n), to) != sizeof(n)) { if (ret == 0) ret = -EFAULT; break; } ret += sizeof(n); total_len -= sizeof(n); pipe->note_loss = false; } #endif
// 限制读取量为用户读取的剩余量 if (chars > total_len) { if (buf->flags & PIPE_BUF_FLAG_WHOLE) { // 不允许部分读取 if (ret == 0) ret = -ENOBUFS; break; } chars = total_len; }
// 确认缓冲区有效性 error = pipe_buf_confirm(pipe, buf); if (error) { if (!ret) ret = error; break; }
// 将内核页数据拷贝到用户空间 written = copy_page_to_iter(buf->page, buf->offset, chars, to); if (unlikely(written < chars)) { if (!ret) ret = -EFAULT; break; } // 更新缓冲区状态 ret += chars; buf->offset += chars; // 偏移量增加 buf->len -= chars; // 剩余长度减少
/* Was it a packet buffer? Clean up and exit */ // 处理包模式 if (buf->flags & PIPE_BUF_FLAG_PACKET) { total_len = chars; buf->len = 0; }
// 缓冲区读空,更新尾指针 if (!buf->len) tail = pipe_update_tail(pipe, buf, tail); total_len -= chars; if (!total_len) break; /* common path: read succeeded */ if (!pipe_empty(head, tail)) /* More to do? */ continue; }
// ** 处理阻塞与唤醒 ** // 查看是否有写者,没有则退出 if (!pipe->writers) break; // 已有部分数据或错误 if (ret) break; // 非阻塞模式立即返回-EAGAIN if ((filp->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT)) { ret = -EAGAIN; break; } // 释放锁 __pipe_unlock(pipe);
/* * We only get here if we didn't actually read anything. * * However, we could have seen (and removed) a zero-sized * pipe buffer, and might have made space in the buffers * that way. * * You can't make zero-sized pipe buffers by doing an empty * write (not even in packet mode), but they can happen if * the writer gets an EFAULT when trying to fill a buffer * that already got allocated and inserted in the buffer * array. * * So we still need to wake up any pending writers in the * _very_ unlikely case that the pipe was full, but we got * no data. */ // 若管道之前是满的,唤醒写进程 if (unlikely(was_full)) wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM); kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
/* * But because we didn't read anything, at this point we can * just return directly with -ERESTARTSYS if we're interrupted, * since we've done any required wakeups and there's no need * to mark anything accessed. And we've dropped the lock. */ // 阻塞等待数据到达 if (wait_event_interruptible_exclusive(pipe->rd_wait, pipe_readable(pipe)) < 0) return -ERESTARTSYS; // 被信号中断