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)Pipewritewakes up reader if buffer is full, or written is down.Pipereadsleep 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:
In
piperead, why we wake up write first, then releasepi->lock?Why
pipereaddoes not go back to sleep after reading? Why there is no loop forpiperead? Or is there an outside loop?
Last updated
Was this helpful?