Comment on page

How unix pipes work?

int pipewrite(struct pipe *pi, uint64 addr, int n)
{
int I;
char ch;
struct proc *pr = myproc();
acquire(&pi->lock);
for(I = 0; I < n; I++){
while(pi->nwrite == pi->nread + PIPESIZE){ *//DOC: pipewrite-full*
if(pi->readopen == 0 || myproc()->killed){
release(&pi->lock);
return -1;
}
wakeup(&pi->nread);
sleep(&pi->nwrite, &pi->lock);
}
if(copyin(pr->pagetable, &ch, addr + I, 1) == -1)
break;
pi->data[pi->nwrite++ % PIPESIZE] = ch;
}
wakeup(&pi->nread);
release(&pi->lock);
return n;
}
int
piperead(struct pipe *pi, uint64 addr, int n)
{
int i;
struct proc *pr = myproc();
char ch;
acquire(&pi->lock);
while(pi->nread == pi->nwrite && pi->writeopen){ *//DOC: pipe-empty*
if(myproc()->killed){
release(&pi->lock);
return -1;
}
sleep(&pi->nread, &pi->lock); *//DOC: piperead-sleep*
}
for(I = 0; I < n; I++){ *//DOC: piperead-copy*
if(pi->nread == pi->nwrite)
break;
ch = pi->data[pi->nread++ % PIPESIZE];
if(copyout(pr->pagetable, addr + i, &ch, 1) == -1)
break;
}
wakeup(&pi->nwrite); *//DOC: piperead-wakeup*
release(&pi->lock);
return i;
}
  • Pipe buffer wraps around.
  • a full buffer (nwrite == nread+PIPESIZE)
  • an empty buffer(nwrite == nread)
  • Pipewrite wakes up reader if buffer is full, or written is down.
  • Piperead sleep if no more data. Or read data from pipe, copy out to address. Then wake up the write channel.

Flow

TODO

Add more code.

A few open questions:

  1. 1.
    In piperead, why we wake up write first, then release pi->lock?
  2. 2.
    Why piperead does not go back to sleep after reading? Why there is no loop for piperead? Or is there an outside loop?