Nkan yii ṣe apejuwe imuse ti awọn opo gigun ti epo ni ekuro Unix. Inu mi bajẹ diẹ pe nkan aipẹ kan ti akole rẹ jẹ "
Kini a n sọrọ nipa?
Awọn paipu jẹ “o ṣee ṣe kiikan pataki julọ ni Unix” - ẹya asọye ti imọ-jinlẹ ti Unix ti fifi awọn eto kekere papọ, ati ọrọ-ọrọ laini aṣẹ ti o faramọ:
$ echo hello | wc -c
6
Išẹ yii da lori ipe eto ti a pese ekuro pipe
, eyi ti o jẹ apejuwe lori awọn oju-iwe iwe
Pipelines pese ikanni kan-ọna fun ibaraẹnisọrọ laarin-ilana. Opo gigun ti epo naa ni titẹ sii (ipari kikọ) ati iṣẹjade (opin kika). Awọn data ti a kọ si titẹ sii ti opo gigun ti epo ni a le ka ni abajade.
Opo gigun ti epo ti ṣẹda nipasẹ pipe
pipe(2)
, eyi ti o da awọn apejuwe faili meji pada: ọkan tọka si titẹ sii ti opo gigun ti epo, keji si abajade.
Ijade itọpa lati aṣẹ ti o wa loke fihan ẹda ti opo gigun ti epo ati sisan data nipasẹ rẹ lati ilana kan si ekeji:
$ strace -qf -e execve,pipe,dup2,read,write
sh -c 'echo hello | wc -c'
execve("/bin/sh", ["sh", "-c", "echo hello | wc -c"], …)
pipe([3, 4]) = 0
[pid 2604795] dup2(4, 1) = 1
[pid 2604795] write(1, "hellon", 6) = 6
[pid 2604796] dup2(3, 0) = 0
[pid 2604796] execve("/usr/bin/wc", ["wc", "-c"], …)
[pid 2604796] read(0, "hellon", 16384) = 6
[pid 2604796] write(1, "6n", 2) = 2
Ilana obi awọn ipe pipe()
lati gba so faili apejuwe. Ilana ọmọ kan kọwe si onitumọ kan ati ilana miiran ka data kanna lati ọdọ olutọwe miiran. Awọn ikarahun "tunrukọ" awọn apejuwe 2 ati 3 pẹlu dup4 lati baramu stdin ati stdout.
Laisi awọn opo gigun ti epo, ikarahun naa yoo ni lati kọ abajade ti ilana kan si faili kan ki o pai si ilana miiran lati ka data lati faili naa. Bi abajade, a yoo padanu awọn orisun diẹ sii ati aaye disk. Sibẹsibẹ, awọn opo gigun ti epo dara fun diẹ sii ju yiyọkuro awọn faili igba diẹ lọ:
Ti ilana kan ba gbiyanju lati ka lati opo gigun ti epo ti o ṣofo, lẹhinna
read(2)
yoo dina titi data yoo wa. Ti ilana kan ba gbiyanju lati kọ si opo gigun ti epo, lẹhinnawrite(2)
yoo dina titi di igba ti a ti ka data ti o to lati opo gigun ti epo lati pari kikọ.
Gẹgẹbi ibeere POSIX, eyi jẹ ohun-ini pataki: kikọ si opo gigun ti epo to PIPE_BUF
awọn baiti (o kere ju 512) gbọdọ jẹ atomiki ki awọn ilana le ṣe ibasọrọ pẹlu ara wọn nipasẹ opo gigun ti epo ni ọna ti awọn faili deede (eyiti ko pese iru awọn iṣeduro bẹ) ko le.
Pẹlu faili deede, ilana kan le kọ gbogbo iṣẹjade rẹ si rẹ ki o gbe lọ si ilana miiran. Tabi awọn ilana le ṣiṣẹ ni ipo afiwera lile, ni lilo ẹrọ ifihan itagbangba (bii semaphore) lati sọ fun ara wọn nipa ipari kikọ tabi kika. Awọn olutọpa gba wa lọwọ gbogbo wahala yii.
Kini a nwa?
Emi yoo ṣe alaye lori awọn ika ọwọ mi lati jẹ ki o rọrun fun ọ lati fojuinu bawo ni gbigbe le ṣiṣẹ. Iwọ yoo nilo lati pin ifipamọ ati ipo diẹ ninu iranti. Iwọ yoo nilo awọn iṣẹ lati ṣafikun ati yọkuro data lati ifipamọ. Iwọ yoo nilo ohun elo diẹ lati pe awọn iṣẹ lakoko kika ati kikọ awọn iṣẹ ṣiṣe lori awọn apejuwe faili. Ati pe a nilo awọn titiipa lati ṣe iṣe ihuwasi pataki ti a ṣalaye loke.
A ti ṣetan ni bayi lati ṣe ibeere koodu orisun ti ekuro labẹ ina atupa lati jẹrisi tabi tako awoṣe ọpọlọ aiduro wa. Ṣugbọn nigbagbogbo mura silẹ fun airotẹlẹ.
Nibo ni a nwa?
Emi ko mọ ibiti ẹda mi ti iwe olokiki wa.
Lilọ kiri nipasẹ awọn ile-ipamọ TUHS dabi ṣiṣabẹwo si musiọmu kan. A le wo itan-akọọlẹ ti a pin ati pe Mo ni ibowo fun awọn ọdun igbiyanju lati gba gbogbo ohun elo yii pada nipasẹ bit nipasẹ awọn kasẹti atijọ ati awọn atẹjade. Ati pe Mo mọye gaan ti awọn ajẹkù yẹn ti wọn ṣi nsọnu.
Nini itẹlọrun iwariiri wa nipa itan-akọọlẹ atijọ ti awọn opo gigun ti epo, a le wo awọn ohun kohun ode oni fun lafiwe.
Nipa ọna, pipe
jẹ nọmba ipe eto 42 ninu tabili sysent[]
. Lasan?
Awọn ekuro Unix ti aṣa (1970–1974)
Emi ko ri itọpa kankan pipe(2)
bẹni ni
TUHS sọ pe
Ẹya kẹta ti Unix jẹ ẹya ti o kẹhin pẹlu ekuro ti a kọ sinu apejọ, ṣugbọn tun ẹya akọkọ pẹlu awọn paipu. Ni ọdun 1973, iṣẹ ti nlọ lọwọ lati mu ilọsiwaju ti ẹda kẹta dara, a tun kọ ekuro ni C, ati nitorinaa ẹda kẹrin ti Unix ni a bi.
Oluka kan rii ọlọjẹ ti iwe kan ninu eyiti Doug McIlroy dabaa imọran “awọn eto sisopọ bii okun ọgba.”
Ninu iwe Brian Kernighan
Nigbati Unix han, ifẹ mi fun awọn coroutines jẹ ki n beere lọwọ onkọwe OS, Ken Thompson, lati gba data ti a kọ si ilana kan lati lọ kii ṣe si ẹrọ nikan, ṣugbọn tun si ijade si ilana miiran. Ken ro pe o ṣee ṣe. Sibẹsibẹ, bi minimalist, o fẹ ki gbogbo ẹya eto lati ṣe ipa pataki. Njẹ kikọ taara laarin awọn ilana jẹ anfani nla lori kikọ si faili agbedemeji? Ati ki o nikan nigbati mo ti ṣe kan pato si imọran pẹlu awọn catchy orukọ "pipeline" ati awọn apejuwe ti awọn sintasi ti awọn ibaraenisepo ti awọn ilana, Ken nipari kigbe: "Emi yoo se o!".
O si ṣe. Ni irọlẹ ayanmọ kan, Ken yi ekuro ati ikarahun pada, ṣeto ọpọlọpọ awọn eto boṣewa lati ṣe iwọn bi wọn ṣe gba titẹ sii (eyiti o le wa lati opo gigun ti epo), ati yi awọn orukọ faili pada. Ni ọjọ keji, awọn opo gigun ti epo ni lilo pupọ ni awọn ohun elo. Ni opin ọsẹ, awọn akọwe lo wọn lati fi awọn iwe aṣẹ ranṣẹ lati awọn olutọpa ọrọ si itẹwe. Ni diẹ lẹhinna, Ken rọpo API atilẹba ati sintasi fun fifi ipari si lilo awọn opo gigun ti epo pẹlu awọn apejọ mimọ ti a ti lo lati igba naa.
Laanu, koodu orisun fun ekuro Unix kẹta ti sọnu. Ati pe botilẹjẹpe a ni koodu orisun kernel ti a kọ sinu C
A ni ọrọ iwe fun pipe(2)
lati awọn idasilẹ mejeeji, nitorinaa o le bẹrẹ nipasẹ wiwa iwe naa pipe(2)
ti kọ sinu apejọ ati dapada apejuwe faili kan nikan, ṣugbọn tẹlẹ pese iṣẹ ṣiṣe mojuto ti a nireti:
Ipe eto pipe ṣẹda ẹrọ I/O ti a npe ni opo gigun ti epo. Apejuwe faili ti o pada le ṣee lo fun awọn iṣẹ kika ati kikọ. Nigbati ohun kan ba kọ si opo gigun ti epo, o fa soke si awọn baiti 504 ti data, lẹhinna ilana kikọ ti daduro. Nigbati o ba ka lati opo gigun ti epo, a mu data buffered.
Ni ọdun to nbọ, a ti tun kọ ekuro ni C, ati pipe(fildes)
»:
Ipe eto pipe ṣẹda ẹrọ I/O ti a npe ni opo gigun ti epo. Awọn apejuwe faili ti o pada le ṣee lo ni awọn iṣẹ kika ati kikọ. Nigba ti a ba kọ nkan si opo gigun ti epo, aṣàpèjúwe naa pada ni r1 (resp. fildes [1]) ti lo, ti a fi silẹ si awọn baiti 4096 ti data, lẹhin eyi ti ilana kikọ ti daduro. Nigbati kika lati opo gigun ti epo, apejuwe pada si r0 (resp. fildes [0]) gba data naa.
A ro pe ni kete ti a ti ṣalaye opo gigun ti epo, awọn ilana ibaraenisepo meji (tabi diẹ sii) (ti a ṣẹda nipasẹ awọn ẹbẹ ti o tẹle orita) yoo kọja data lati opo gigun ti epo nipa lilo awọn ipe ka и kọ.
Ikarahun naa ni sintasi kan fun asọye ọna ila ti awọn ilana ti a ti sopọ nipasẹ opo gigun ti epo kan.
Awọn ipe lati ka lati opo gigun ti epo ti o ṣofo (ti ko ni data ti a fi silẹ) ti o ni opin kan nikan (gbogbo awọn apejuwe faili kikọ ni pipade) pada “ipari faili”. Kọ awọn ipe ni iru ipo ti wa ni bikita.
Ni iṣaaju
Ẹ̀dà Unix kẹfà (1975)
Bibẹrẹ lati ka koodu orisun Unix
Fun opolopo odun iwe kiniun jẹ iwe-ipamọ nikan lori ekuro Unix ti o wa ni ita ti Bell Labs. Bó tilẹ̀ jẹ́ pé ìwé àṣẹ ẹ̀dà kẹfà gba àwọn olùkọ́ láyè láti lo kóòdù orísun rẹ̀, ìwé àṣẹ àtúnṣe keje kò yọ̀ọ̀da yìí, nítorí náà, wọ́n pín ìwé náà sínú àwọn ẹ̀dà ẹ̀dà tí kò bófin mu.
Loni o le ra ẹda atuntẹ ti iwe naa, ideri eyiti o ṣe afihan awọn ọmọ ile-iwe ni oludaakọ. Ati ọpẹ si Warren Toomey (ẹniti o bẹrẹ iṣẹ TUHS), o le ṣe igbasilẹ
Ni ọdun 15 sẹhin, Mo ti tẹ ẹda koodu orisun ti a pese sinu kiniunnitori Emi ko fẹran didara ẹda mi lati nọmba aimọ ti awọn ẹda miiran. TUHS ko si tẹlẹ, ati pe Emi ko ni iwọle si awọn orisun atijọ. Ṣugbọn ni ọdun 1988 Mo rii teepu atijọ kan pẹlu awọn orin 9 ti o ni afẹyinti lati kọnputa PDP11 kan. O nira lati mọ boya o ṣiṣẹ, ṣugbọn igi / usr / src kan wa ninu eyiti ọpọlọpọ awọn faili ti samisi ni ọdun 1979, eyiti paapaa lẹhinna dabi atijọ. O jẹ ẹda keje, tabi itọsẹ PWB, Mo ro.
Mo mu wiwa naa gẹgẹbi ipilẹ ati ọwọ satunkọ awọn orisun si ipo ti ẹda kẹfa. Apakan koodu naa wa bakan naa, apakan ni lati ṣatunkọ diẹ, yiyipada ami-ami ode oni += si ti atijo =+. Nkankan ti paarẹ nirọrun, ati pe ohun kan ni lati tun kọ patapata, ṣugbọn kii ṣe pupọ.
Ati loni a le ka lori ayelujara ni TUHS koodu orisun ti ẹda kẹfa ti
Nipa ọna, ni iwo akọkọ, ẹya akọkọ ti koodu C ṣaaju akoko Kernighan ati Ritchie jẹ tirẹ. kukuru. Kii ṣe igbagbogbo pe Mo ni anfani lati fi awọn snippets ti koodu sii laisi ṣiṣatunṣe lọpọlọpọ lati baamu agbegbe ifihan ti o dín jo lori aaye mi.
Ni ibẹrẹ
/*
* Max allowable buffering per pipe.
* This is also the max size of the
* file created to implement the pipe.
* If this size is bigger than 4096,
* pipes will be implemented in LARG
* files, which is probably not good.
*/
#define PIPSIZ 4096
Iwọn ifipamọ ko yipada lati ẹda kẹrin. Ṣugbọn nibi a rii, laisi eyikeyi iwe ti gbogbo eniyan, awọn opo gigun ti epo ni ẹẹkan lo awọn faili bi ibi ipamọ ipadabọ!
Bi fun awọn faili LARG, wọn ṣe deede si
Eyi ni ipe eto gidi pipe
:
/*
* The sys-pipe entry.
* Allocate an inode on the root device.
* Allocate 2 file structures.
* Put it all together with flags.
*/
pipe()
{
register *ip, *rf, *wf;
int r;
ip = ialloc(rootdev);
if(ip == NULL)
return;
rf = falloc();
if(rf == NULL) {
iput(ip);
return;
}
r = u.u_ar0[R0];
wf = falloc();
if(wf == NULL) {
rf->f_count = 0;
u.u_ofile[r] = NULL;
iput(ip);
return;
}
u.u_ar0[R1] = u.u_ar0[R0]; /* wf's fd */
u.u_ar0[R0] = r; /* rf's fd */
wf->f_flag = FWRITE|FPIPE;
wf->f_inode = ip;
rf->f_flag = FREAD|FPIPE;
rf->f_inode = ip;
ip->i_count = 2;
ip->i_flag = IACC|IUPD;
ip->i_mode = IALLOC;
}
Ọrọìwòye ṣe apejuwe ohun ti n ṣẹlẹ ni kedere. Ṣugbọn kii ṣe rọrun lati ni oye koodu naa, ni apakan nitori bii “R0
и R1
Awọn paramita ipe eto ati awọn iye ipadabọ ti kọja.
Jẹ ká gbiyanju pẹlu
pipe()
nitori nipasẹ R0
и R1
pada faili apejuwe awọn nọmba fun kika ati kikọ. falloc()
da a ijuboluwole si a file be, sugbon tun "pada" nipasẹ u.u_ar0[R0]
ati apejuwe faili. Iyẹn ni, koodu ti wa ni ipamọ r
Apejuwe faili fun kika ati ki o sọtọ a apejuwe fun kikọ taara lati u.u_ar0[R0]
lẹhin ipe keji falloc()
.
Flag FPIPE
, eyiti a ṣeto nigbati o ṣẹda opo gigun ti epo, n ṣakoso ihuwasi ti iṣẹ naa
/*
* common code for read and write calls:
* check permissions, set base, count, and offset,
* and switch out to readi, writei, or pipe code.
*/
rdwr(mode)
{
register *fp, m;
m = mode;
fp = getf(u.u_ar0[R0]);
/* … */
if(fp->f_flag&FPIPE) {
if(m==FREAD)
readp(fp); else
writep(fp);
}
/* … */
}
Lẹhinna iṣẹ naa readp()
в pipe.c
ka data lati opo gigun ti epo. Ṣugbọn o dara lati wa kakiri imuse ti o bẹrẹ lati writep()
. Lẹẹkansi, koodu naa ti di idiju diẹ sii nitori iru ariyanjiyan ti o kọja apejọ, ṣugbọn diẹ ninu awọn alaye le yọkuro.
writep(fp)
{
register *rp, *ip, c;
rp = fp;
ip = rp->f_inode;
c = u.u_count;
loop:
/* If all done, return. */
plock(ip);
if(c == 0) {
prele(ip);
u.u_count = 0;
return;
}
/*
* If there are not both read and write sides of the
* pipe active, return error and signal too.
*/
if(ip->i_count < 2) {
prele(ip);
u.u_error = EPIPE;
psignal(u.u_procp, SIGPIPE);
return;
}
/*
* If the pipe is full, wait for reads to deplete
* and truncate it.
*/
if(ip->i_size1 == PIPSIZ) {
ip->i_mode =| IWRITE;
prele(ip);
sleep(ip+1, PPIPE);
goto loop;
}
/* Write what is possible and loop back. */
u.u_offset[0] = 0;
u.u_offset[1] = ip->i_size1;
u.u_count = min(c, PIPSIZ-u.u_offset[1]);
c =- u.u_count;
writei(ip);
prele(ip);
if(ip->i_mode&IREAD) {
ip->i_mode =& ~IREAD;
wakeup(ip+2);
}
goto loop;
}
A fẹ kọ awọn baiti si igbewọle opo gigun ti epo u.u_count
. Ni akọkọ a nilo lati tii inode (wo isalẹ plock
/prele
).
Lẹhinna a ṣayẹwo iye itọkasi inode. Niwọn igba ti awọn opin mejeeji ti opo gigun ti epo wa ni sisi, counter yẹ ki o jẹ 2. A dimu si ọna asopọ kan (lati rp->f_inode
), nitorina ti counter ba kere ju 2, lẹhinna eyi yẹ ki o tumọ si pe ilana kika ti pa opin rẹ ti opo gigun ti epo. Ni awọn ọrọ miiran, a n gbiyanju lati kọ si opo gigun ti epo, eyiti o jẹ aṣiṣe. Koodu aṣiṣe akọkọ EPIPE
ati ifihan agbara SIGPIPE
han ni kẹfa àtúnse ti Unix.
Sugbon paapa ti o ba awọn conveyor wa ni sisi, o le jẹ ni kikun. Ni idi eyi, a tu titiipa silẹ ki o lọ sùn ni ireti pe ilana miiran yoo ka lati inu opo gigun ti epo ati ki o gba aaye ti o to ninu rẹ. Nigba ti a ba ji, a pada si ibẹrẹ, gbe titiipa soke lẹẹkansi ati bẹrẹ ọna kikọ tuntun kan.
Ti aaye ọfẹ ba wa ni opo gigun ti epo, lẹhinna a kọ data si rẹ nipa lilo i_size1
inode'a (pẹlu opo gigun ti o ṣofo le jẹ dogba si 0) tọka si opin data ti o wa ninu tẹlẹ. Ti aaye to ba wa lati kọ, a le kun opo gigun ti epo lati i_size1
si PIPESIZ
. Lẹhinna a tu titiipa silẹ ki o gbiyanju lati ji eyikeyi ilana ti o nduro lati ka lati opo gigun ti epo. A pada si ibẹrẹ lati rii boya a ṣakoso lati kọ ọpọlọpọ awọn baiti bi a ṣe nilo. Ti kii ba ṣe bẹ, lẹhinna a bẹrẹ ọmọ igbasilẹ tuntun kan.
Nigbagbogbo paramita i_mode
inode ti lo lati tọju awọn igbanilaaye r
, w
и x
. Ṣugbọn ninu ọran ti awọn opo gigun ti epo, a ṣe ifihan pe diẹ ninu awọn ilana n duro de kikọ tabi kika nipa lilo awọn die-die IREAD
и IWRITE
lẹsẹsẹ. Ilana naa ṣeto asia ati awọn ipe sleep()
, ati pe o nireti pe ni ọjọ iwaju diẹ ninu awọn ilana miiran yoo pe wakeup()
.
Idan gidi ṣẹlẹ ni sleep()
и wakeup()
. Wọn ti wa ni imuse ni
/*
* Give up the processor till a wakeup occurs
* on chan, at which time the process
* enters the scheduling queue at priority pri.
* The most important effect of pri is that when
* pri<0 a signal cannot disturb the sleep;
* if pri>=0 signals will be processed.
* Callers of this routine must be prepared for
* premature return, and check that the reason for
* sleeping has gone away.
*/
sleep(chan, pri) /* … */
/*
* Wake up all processes sleeping on chan.
*/
wakeup(chan) /* … */
Ilana ti o pe sleep()
fun kan pato ikanni, le nigbamii ti wa ni ji nipa miiran ilana, eyi ti yoo pe wakeup()
fun kanna ikanni. writep()
и readp()
ipoidojuko awọn iṣe wọn nipasẹ iru awọn ipe ti a so pọ. ṣe akiyesi pe pipe.c
nigbagbogbo ayo PPIPE
nigbati a npe ni sleep()
, nitorina gbogbo sleep()
le ti wa ni Idilọwọ nipa a ifihan agbara.
Bayi a ni ohun gbogbo lati ni oye iṣẹ naa readp()
:
readp(fp)
int *fp;
{
register *rp, *ip;
rp = fp;
ip = rp->f_inode;
loop:
/* Very conservative locking. */
plock(ip);
/*
* If the head (read) has caught up with
* the tail (write), reset both to 0.
*/
if(rp->f_offset[1] == ip->i_size1) {
if(rp->f_offset[1] != 0) {
rp->f_offset[1] = 0;
ip->i_size1 = 0;
if(ip->i_mode&IWRITE) {
ip->i_mode =& ~IWRITE;
wakeup(ip+1);
}
}
/*
* If there are not both reader and
* writer active, return without
* satisfying read.
*/
prele(ip);
if(ip->i_count < 2)
return;
ip->i_mode =| IREAD;
sleep(ip+2, PPIPE);
goto loop;
}
/* Read and return */
u.u_offset[0] = 0;
u.u_offset[1] = rp->f_offset[1];
readi(ip);
rp->f_offset[1] = u.u_offset[1];
prele(ip);
}
O le rii pe o rọrun lati ka iṣẹ yii lati isalẹ de oke. Ẹka “ka ati ipadabọ” ni a maa n lo nigbati data diẹ wa ninu opo gigun ti epo. Ni idi eyi, a lo f_offset
ka, ati ki o mu awọn iye ti awọn ti o baamu aiṣedeede.
Lori awọn kika atẹle, opo gigun ti epo yoo ṣofo ti aiṣedeede kika ba ti de i_size1
ni inode. A tun ipo naa pada si 0 ati gbiyanju lati ji eyikeyi ilana ti o fẹ lati kọ si opo gigun ti epo. A mọ pe nigbati awọn conveyor ti kun, writep()
sun oorun lori ip+1
. Ati ni bayi pe opo gigun ti epo ti ṣofo, a le ji dide lati tun bẹrẹ iyipo kikọ rẹ.
Ti ko ba si nkankan lati ka, lẹhinna readp()
le ṣeto asia IREAD
si ti kuna sun oorun lori ip+2
. A mọ ohun ti yoo ji i writep()
nigbati o kọ diẹ ninu awọn data si opo gigun ti epo.
Comments lori u
»A le ṣe itọju wọn bii awọn iṣẹ I/O deede ti o mu faili kan, ipo kan, ifipamọ ni iranti, ati ka nọmba awọn baiti lati ka tabi kọ.
/*
* Read the file corresponding to
* the inode pointed at by the argument.
* The actual read arguments are found
* in the variables:
* u_base core address for destination
* u_offset byte offset in file
* u_count number of bytes to read
* u_segflg read to kernel/user
*/
readi(aip)
struct inode *aip;
/* … */
/*
* Write the file corresponding to
* the inode pointed at by the argument.
* The actual write arguments are found
* in the variables:
* u_base core address for source
* u_offset byte offset in file
* u_count number of bytes to write
* u_segflg write to kernel/user
*/
writei(aip)
struct inode *aip;
/* … */
Bi fun "Konsafetifu" ìdènà, lẹhinna readp()
и writep()
tii inodes titi wọn o fi pari tabi gba abajade (ie ipe wakeup
). plock()
и prele()
ṣiṣẹ nìkan: lilo kan ti o yatọ ṣeto ti awọn ipe sleep
и wakeup
gba wa laaye lati ji eyikeyi ilana ti o nilo titiipa ti a ṣẹṣẹ tu silẹ:
/*
* Lock a pipe.
* If its already locked, set the WANT bit and sleep.
*/
plock(ip)
int *ip;
{
register *rp;
rp = ip;
while(rp->i_flag&ILOCK) {
rp->i_flag =| IWANT;
sleep(rp, PPIPE);
}
rp->i_flag =| ILOCK;
}
/*
* Unlock a pipe.
* If WANT bit is on, wakeup.
* This routine is also used to unlock inodes in general.
*/
prele(ip)
int *ip;
{
register *rp;
rp = ip;
rp->i_flag =& ~ILOCK;
if(rp->i_flag&IWANT) {
rp->i_flag =& ~IWANT;
wakeup(rp);
}
}
Ni akọkọ Emi ko le loye idi readp()
ko fa prele(ip)
ṣaaju ipe wakeup(ip+1)
. Ohun akọkọ writep()
Awọn ipe ninu awọn oniwe-lupu, yi plock(ip)
, eyi ti àbábọrẹ ni a deadlock ti o ba ti readp()
ko tii yọ bulọọki rẹ kuro sibẹsibẹ, nitorinaa koodu gbọdọ ṣiṣẹ bakan ni deede. Ti o ba wo wakeup()
, o han gbangba pe o jẹ ami si ilana sisun nikan bi o ti ṣetan fun ipaniyan, ki ni ojo iwaju sched()
gan se igbekale o. Nitorina readp()
awọn okunfa wakeup()
, ṣiṣi silẹ, ṣeto IREAD
ati awọn ipe sleep(ip+2)
- gbogbo eyi ṣaaju writep()
tun bẹrẹ ọmọ.
Eyi pari apejuwe awọn pipeline ni ẹda kẹfa. Koodu ti o rọrun, awọn ilolu ti o jinna.
Xv6, ekuro ti o dabi Unix ti o rọrun
Lati ṣẹda arin
Awọn koodu ni kan ko o ati laniiyan imuse pipealloc()
:
#define PIPESIZE 512
struct pipe {
struct spinlock lock;
char data[PIPESIZE];
uint nread; // number of bytes read
uint nwrite; // number of bytes written
int readopen; // read fd is still open
int writeopen; // write fd is still open
};
int
pipealloc(struct file **f0, struct file **f1)
{
struct pipe *p;
p = 0;
*f0 = *f1 = 0;
if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
goto bad;
if((p = (struct pipe*)kalloc()) == 0)
goto bad;
p->readopen = 1;
p->writeopen = 1;
p->nwrite = 0;
p->nread = 0;
initlock(&p->lock, "pipe");
(*f0)->type = FD_PIPE;
(*f0)->readable = 1;
(*f0)->writable = 0;
(*f0)->pipe = p;
(*f1)->type = FD_PIPE;
(*f1)->readable = 0;
(*f1)->writable = 1;
(*f1)->pipe = p;
return 0;
bad:
if(p)
kfree((char*)p);
if(*f0)
fileclose(*f0);
if(*f1)
fileclose(*f1);
return -1;
}
pipealloc()
ṣeto ipo ti gbogbo awọn iyokù imuse, eyiti o pẹlu awọn iṣẹ piperead()
, pipewrite()
и pipeclose()
. Awọn gangan eto ipe sys_pipe
ti wa ni a wrapper muse ni
Linux 0.01
O le wa koodu orisun fun Linux 0.01. Yoo jẹ itọnisọna lati ṣe iwadi imuse ti awọn opo gigun ti epo ni tirẹ fs
/pipe.c
. Nibi, a ti lo inode lati ṣe aṣoju opo gigun ti epo, ṣugbọn opo gigun ti ara rẹ ni a kọ ni igbalode C. Ti o ba ti gepa ọna rẹ nipasẹ koodu ẹda kẹfa, iwọ kii yoo ni wahala nibi. Eyi ni ohun ti iṣẹ naa dabi write_pipe()
:
int write_pipe(struct m_inode * inode, char * buf, int count)
{
char * b=buf;
wake_up(&inode->i_wait);
if (inode->i_count != 2) { /* no readers */
current->signal |= (1<<(SIGPIPE-1));
return -1;
}
while (count-->0) {
while (PIPE_FULL(*inode)) {
wake_up(&inode->i_wait);
if (inode->i_count != 2) {
current->signal |= (1<<(SIGPIPE-1));
return b-buf;
}
sleep_on(&inode->i_wait);
}
((char *)inode->i_size)[PIPE_HEAD(*inode)] =
get_fs_byte(b++);
INC_PIPE( PIPE_HEAD(*inode) );
wake_up(&inode->i_wait);
}
wake_up(&inode->i_wait);
return b-buf;
}
Paapaa laisi wiwo awọn asọye igbekale, o le ro ero bawo ni a ṣe lo kika itọkasi inode lati ṣayẹwo boya iṣẹ ṣiṣe kikọ ba ni abajade SIGPIPE
. Ni afikun si iṣẹ baiti-nipasẹ-baiti, iṣẹ yii rọrun lati ṣe afiwe pẹlu awọn ero ti o wa loke. Ani ogbon sleep_on
/wake_up
ko dabi ajeji.
Awọn ekuro Linux ode oni, FreeBSD, NetBSD, OpenBSD
Mo yara lọ lori diẹ ninu awọn ekuro ode oni. Ko si ọkan ninu wọn ti ni imuse orisun disiki (kii ṣe iyalẹnu). Lainos ni imuse tirẹ. Ati pe botilẹjẹpe awọn ekuro BSD ode oni mẹta ni awọn imuse ti o da lori koodu ti a kọ nipasẹ John Dyson, ni awọn ọdun diẹ wọn ti yatọ pupọ si ara wọn.
Lati ka fs
/pipe.c
(lori Linux) tabi sys
/kern
/sys_pipe.c
(lori * BSD), o gba iyasọtọ gidi. Iṣe ati atilẹyin fun awọn ẹya bii fekito ati asynchronous I/O ṣe pataki ni koodu loni. Ati awọn alaye ti ipin iranti, awọn titiipa, ati iṣeto ekuro gbogbo yatọ pupọ. Eyi kii ṣe ohun ti awọn ile-ẹkọ giga nilo fun ikẹkọ iṣafihan lori awọn ọna ṣiṣe.
Ni eyikeyi idiyele, o jẹ iyanilenu fun mi lati ṣawari awọn ilana atijọ diẹ (fun apẹẹrẹ, ti ipilẹṣẹ SIGPIPE
ati pada EPIPE
nigba kikọ si opo gigun ti epo) ni gbogbo iwọnyi, ti o yatọ, awọn kernels ode oni. Emi kii yoo rii kọnputa PDP-11 laaye laaye, ṣugbọn ọpọlọpọ tun wa lati kọ ẹkọ lati koodu ti a kọ ni ọdun diẹ ṣaaju ki a bi mi.
Ti a kọ nipasẹ Divi Kapoor ni ọdun 2011, nkan naa "
orisun: www.habr.com