Maqaalkani waxa uu sharaxayaa hirgelinta dhuumaha gudaha Unix kernel. Waxaan xoogaa ka xumaaday maqaal dhawaan soo baxay oo ciwaankiisu ahaa "
Maxaan ka hadlaynaa?
Dhuumaha, "malaha hal-abuurka ugu muhiimsan ee Unix," ayaa ah sifada qeexeysa falsafada Unix ee hoose ee isku xirka barnaamijyada yaryar, iyo sidoo kale calaamad caan ah oo ku taal khadka taliska:
$ echo hello | wc -c
6
Shaqadani waxay kuxirantahay wicitaanka nidaamka kernel-ku bixiyo pipe
, kaas oo lagu sifeeyay boggaga waraaqaha
Tuubooyinku waxay bixiyaan kanaal aan jiho lahayn oo loogu talagalay isgaadhsiinta hab-socodka. Dhuunuhu waxa uu leeyahay gelinta (dhammaadka qor) iyo wax soo saar (dhammaadka akhrinta). Xogta lagu qoray gelinta dhuumaha waxaa laga akhriyi karaa soo-saarka.
Dhuumaha waxaa la sameeyaa iyadoo la isticmaalayo wicitaanka
pipe(2)
, kaas oo soo celinaya laba tilmaame oo faylal ah: mid tixraacaya gelinta dhuumaha, kan labaadna soosaarka.
Wax soo saarka raadraaca ee amarka kore wuxuu muujinayaa abuurista dhuumaha iyo qulqulka xogta iyada oo loo marayo hal hab oo kale:
$ 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
Habka waalidku wuu wacaa pipe()
si aad u hesho sharraxayaasha faylka la rakibay. Mid ka mid ah habraaca cunuga wuxuu wax ku qoraa hal gacan, mid kalena wuxuu akhriyaa xog isku mid ah gacan kale. qoloftu waxay isticmaashaa dup2 si ay u "bedesho" sharaxayaasha 3 iyo 4 si ay u dhigmaan stdin iyo stdout.
Tuubooyinka la'aanteed, qolofku waa inuu ku qoraa natiijada hal hab faylal una gudbiyaa hab kale si uu u akhriyo xogta faylka. Natiijo ahaan, waxaan luminay kheyraad badan iyo meel disk ah. Si kastaba ha ahaatee, dhuumaha ma wanaagsana kaliya sababtoo ah waxay kuu ogolaanayaan inaad ka fogaato isticmaalka faylasha ku meel gaarka ah:
Haddii nidaamku isku dayayo in laga akhriyo dhuumaha maran markaa
read(2)
xannibi doona ilaa xogta laga helayo. Haddii nidaamku isku dayo inuu u qoro dhuumo buuxa, markaawrite(2)
xannibi doona ilaa xog ku filan laga akhriyo dhuumaha si loo sameeyo qoraalka.
Sida shardiga POSIX, kani waa hanti muhiim ah: wax u qorida dhuumaha ilaa PIPE_BUF
bytes (ugu yaraan 512) waa in ay noqdaan atomic si hab-socodka ay ugu wada xiriiraan midba midka kale iyada oo loo marayo dhuumaha si aan faylasha caadiga ah (kuwaas oo aan bixineynin dammaanadahaas) aysan awoodin.
Marka la isticmaalayo faylka caadiga ah, nidaamku wuxuu u qori karaa dhammaan wax soo saarkiisa wuxuuna u gudbin karaa hab kale. Ama habraacyadu waxay ku shaqayn karaan qaab isbarbar socda, iyadoo la adeegsanayo habka calaamadaynta dibadda (sida semaphore) si ay midba midka kale ugu wargaliyo marka qoraal ama akhris la dhammeeyo. Gaadiidleyda ayaa naga badbaadiya dhibkan oo dhan.
Maxaan raadineynaa?
Waxaan ku sharixi doonaa erayo fudud si ay kuugu sahlanaato inaad qiyaasto sida uu u shaqayn karo gaadiid qaade. Waxaad u baahan doontaa inaad qoondayso kaydka iyo xaalad xusuusta ah. Waxaad u baahan doontaa hawlo si aad ugu darto ugana saarto xogta kaydiyaha Waxaad u baahan doontaa habab aad ku wacdo hawlaha inta lagu jiro akhrinta iyo qorista hawlgallada sharraxayaasha faylka. Waxaadna u baahan doontaa quful si aad u fuliso hab-dhaqanka gaarka ah ee kor lagu sheegay.
Hadda waxaan diyaar u nahay inaan su'aalo weydiinno koodhka isha kernel-ka hoostiisa si aan u xaqiijinno ama u beeninno qaabkayaga maskaxeed ee aan caddayn. Laakin mar walba u diyaar garow wax aan la fileyn.
Halkee ayaan raadineynaa?
Ma garanayo halka uu ku yaal nuqulka buugga caanka ah "
Ku dhex wareegidda kaydka TUHS waxay la mid tahay booqashada matxafka. Waxaan eegi karnaa taariikhdayada aan wadaagno, waxaanan ixtiraam u hayaa sannadaha badan ee dadaalka loogu jiro soo kabashada dhammaan walxahan xoogaa cajalado iyo daabacaado duug ah. Waxaan si weyn ula socdaa jajabyadaas weli maqan.
Markaan ku qanacnay xiisaha aan u qabno taariikhda qadiimiga ah ee alaab-qaadayaasha, waxaan eegi karnaa kernels casriga ah marka la barbardhigo.
By habka, pipe
waa nidaamka call number 42 ee shaxda sysent[]
. Shil?
Kernels-dhaqameedka Unix (1970-1974)
Wax raad ah maan helin pipe(2)
midna ma gelin
TUHS ayaa sheegaysa in
Daabacaadda 1973aad ee Unix ayaa ahaa nuqulkii ugu dambeeyay ee kernel ku qoran luqadda kulanka, laakiin sidoo kale nuqulkii ugu horreeyay oo leh dhuumo. Intii lagu jiray XNUMX, waxaa la sameeyay shaqada si loo hagaajiyo daabacaadda saddexaad, kernel ayaa dib loogu qoray C, sidaas darteed daabacaadda afraad ee Unix ayaa soo baxday.
Mid ka mid ah akhristayaasha ayaa helay sawir dukumeenti ah kaas oo Doug McIlroy uu soo jeediyay fikradda "isku xirka barnaamijyada sida tuubada beerta."
Buugga Brian Kernighan
Markii Unix soo baxday, xiisaha aan u qabo coroutines ayaa ii horseeday inaan weydiiyo qoraaga OS-ga, Ken Thompson, inuu oggolaado xogta loo qoray habka inay u baxdo oo keliya ma aha qalabka, laakiin sidoo kale inaan u soo saaro hab kale. Ken wuxuu go'aansaday inay suurtagal tahay. Si kastaba ha ahaatee, sida ugu yar, wuxuu rabay in nidaam kastaa uu shaqeeyo door muhiim ah. Qoritaanka tooska ah ee hababka u dhexeeya run ahaantii faa'iido weyn ma ka leedahay qorista faylka dhexe? Waxay ahayd markii aan sameeyay soo jeedin gaar ah oo leh magaca soo jiidashada leh ee "tuubada" iyo sharaxaadda ereyga isdhexgalka ee u dhexeeya hababka ayuu Ken ugu dambeyntii ku dhawaaqay: "Waan samayn doonaa!"
Oo sameeyey. Habeen fiid ah, Ken waxa uu beddelay kernel-ka iyo qolofka, waxa uu hagaajiyay dhawr barnaamij oo caadi ah si loo jaangooyo sida ay u aqbaleen gelinta (taas oo ka iman karta dhuumaha), waxa kale oo uu beddelay magacyo faylal ah. Maalintii xigtay, dhuumaha ayaa bilaabay in si weyn loogu isticmaalo codsiyada. Dhammaadkii usbuuca, xoghayayaashu waxay adeegsanayeen si ay dukumentiyada uga soo diraan qalabka wax lagu daabaco. Wax yar ka dib, Ken wuxuu bedelay API-gii asalka ahaa iyo syntax si loogu duubo isticmaalka dhuumaha oo leh heshiisyo nadiif ah, kuwaas oo la isticmaalay tan iyo markaas.
Nasiib darro, koodhka isha ee daabacaadda saddexaad ee Unix kernel ayaa lumay. In kasta oo aan hayno koodhka isha kernel ee ku qoran C
Waxaan u haynaa dukumeenti qoraal ah pipe(2)
laga bilaabo labada siideyn, si aad ku bilaabi karto raadinta dukumentiyada pipe(2)
wuxuu ku qoran yahay luqadda kulanka wuxuuna soo celinayaa kaliya hal sharaxe oo fayl, laakiin wuxuu horey u bixiyaa shaqeynta aasaasiga ah ee la filayo:
Wacitaanka nidaamka biibiile abuuraa habka wax-gelinta/soo-saarka loo yaqaan pipeline. Sharaxa faylka la soo celiyay waxaa loo isticmaali karaa hawlgallada akhrinta iyo qorista. Marka wax lagu qoro dhuumaha, ilaa 504 bytes oo xog ah ayaa la xiraa, ka dib habka qorista waa la hakiyaa. Markaad wax ka akhrinayso dhuumaha, xogta la xidhay waa la qaadayaa.
Sannadkii xigay kernel-ka ayaa dib loogu qoray C, iyo pipe(fildes)
Β»:
Wacitaanka nidaamka biibiile abuuraa habka wax-gelinta/soo-saarka loo yaqaan pipeline. Sharaxayaasha faylka la soo celiyay waxaa loo isticmaali karaa akhrinta iyo qorista. Marka wax lagu qoro dhuunta, gacanta lagu soo celiyo r1 (resp. fildes[1]) ayaa la isticmaalaa, oo lagu kaydiyaa 4096 bytes oo xog ah, ka dib habka qorista waa la hakiyaa. Markaad wax ka akhrinayso dhuumaha, gacantu waxay ku soo noqotay r0 (resp. fildes[0]) waxay qaadataa xogta.
Waxaa loo malaynayaa in marka dhuumaha la qeexo, laba (ama ka badan) hababka isgaadhsiinta (oo ay abuuraan wicitaano xiga fargeeto ah) waxay ku wareejin doontaa xogta dhuumaha adoo isticmaalaya wicitaano akhri ΠΈ ku qor.
Qolfoofku wuxuu leeyahay hab-raac lagu qeexo habraacyo toosan oo isku xidhan oo dhuumo ah.
Wicitaannada lagu akhriyo dhuunta maran (oo aan ku jirin xog la daboolay) oo leh hal dhammaad (dhammaan sharraxayaasha faylka qoraalka waa la xiray) soo celinta "dhamaadka faylka". Wicitaannada lagu qorayo xaalad la mid ah waa la iska indhatiraa.
Ugu horrayn
Daabacaaddii lixaad ee Unix (1975)
Aan bilowno akhrinta koodka isha Unix
Sannado badan buuggu Lions wuxuu ahaa dukumeentiga kaliya ee ku jira kernel-ka Unix ee laga heli karo meel ka baxsan Bell Labs. In kasta oo shatiga daabacaadda lixaad uu u oggolaaday macallimiinta inay adeegsadaan koodka isha, shatiga daabacaadda toddobaad ayaa meesha ka saaray suurtagalnimadan, sidaas darteed buugga waxaa loo qaybiyay qaab nuqullo qoraal ah oo sharci-darro ah.
Maanta waxaad iibsan kartaa daabacaadda dib u daabacaadda buugga, kaas oo daboolkiisu uu muujinayo ardayda mashiinka nuqulka ah. Waad ku mahadsan tahay Warren Toomey (oo bilaabay mashruuca TUHS) waad soo dejisan kartaa
In ka badan 15 sano ka hor, waxaan qoray nuqul ka mid ah koodka isha ee lagu bixiyay Lions, sababtoo ah maan jeclayn tayada koobigayga oo aan ka helay tiro aan la garanayn oo koobiyo kale ah. TUHS ma jirin wali manaan helin ilahii hore. Laakiin sannadkii 1988kii, waxaan helay cajalad 9-track ah oo hore oo ay ku jirtay kaydka kombayutarka PDP11. Way adkeyd in la sheego in ay shaqaynayso iyo in kale, laakiin waxa jiray geed/usr/src/ geed aan fiicneyn oo inta badan faylalka lagu calaamadiyay sanadka 1979, kaas oo xitaa u muuqday mid qadiimi ah. Waxay ahayd daabacaaddii toddobaad ama PWB-ga laga soo xigtay, sida aan rumaystay.
Helitaanka waxa aan u qaatay gundhig oo waxa aan gacanta ku tafatiray ilihii ilaa daabacaddii lixaad. Qaar ka mid ah koodku sidiisii ββayay ahaan jireen, laakiin qaar waa in wax yar la tafatiray, taas oo beddeleysa calaamadda casriga ah ee += mid duugowday =+. Waxyaabaha qaarkood si fudud ayaa loo tirtiray, qaarna waxay ahayd in si buuxda dib loo qoro, laakiin aan aad u badnayn.
Maantana waxaan ka akhrisan karnaa internetka TUHS koodhka isha ee daabacaadda lixaad ee ka yimid
Jid ahaan, jaleecada hore, muuqaalka ugu weyn ee C-code ka hor muddada Kernighan iyo Ritchie waa soo koobid. Inta badan ma aha in aan awoodo in aan geliyo qaybo kood ah iyada oo aan la samayn tafatir ballaaran si aan ugu habboonaado aag muuqaal cidhiidhi ah oo ku yaal boggayga.
Bilowgii
/*
* 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
Cabbirku isma beddelin ilaa daabacaaddii afraad. Laakiin halkan waxaan ku aragnaa, iyada oo aan la helin wax dukumeenti dadweyne ah, in dhuumahaas mar hore u isticmaali jireen galalka kaydinta kaydinta!
Xagga faylalka LARG, waxay u dhigmaan
Halkan waa wicitaanka nidaamka dhabta ah 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;
}
Faallada ayaa si cad u qeexaysa waxa halkan ka socda. Laakiin fahamka koodhka ma fududa, qayb ahaan sababtoo ah jidka "R0
ΠΈ R1
Xaddiga wicitaanka nidaamka iyo qiyamka soo celinta waa la dhaafay.
Aan isku dayno
pipe()
waa in loo maraa R0
ΠΈ R1
soo celi nambarada sharaxaadaha faylka si aad u akhrido oo u qorto. falloc()
ku soo celiyaa tilmaame qaab dhismeedka faylka, laakiin sidoo kale "soo noqda" iyada oo loo marayo u.u_ar0[R0]
iyo sharraxaha faylka. Taasi waa, koodku wuxuu kaydiyaa gudaha r
Faylka sharaxaha si loo akhriyo oo u xilsaaro sharraxaaha faylka si toos ah wax looga qoro u.u_ar0[R0]
ka dib markii labaad falloc()
.
Calanka FPIPE
, kaas oo aan dejineyno marka la abuurayo dhuumaha, waxay xakameysaa habdhaqanka shaqada
/*
* 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);
}
/* β¦ */
}
Markaa shaqada readp()
Π² pipe.c
akhriyo xogta dhuumaha. Laakiin way fiicantahay in la raadiyo hirgelinta laga bilaabo writep()
. Mar labaad, koodhka ayaa noqday mid aad u adag sababtoo ah heshiisyada doodaha gudbinta, laakiin faahfaahinta qaar ayaa laga saari karaa.
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;
}
Waxaan rabnaa inaan ku qorno bytes gelinta dhuumaha u.u_count
. Marka hore waxaan u baahanahay inaan xirno inode (eeg hoos plock
/prele
).
Kadibna waxaanu hubinaynaa miiska tixraaca inode. Ilaa iyo inta labada daraf ee dhuumuhu ay furan yihiin, miisanku waa inuu la siman yahay 2. Waxaan haynaa hal xiriiriye (laga bilaabo). rp->f_inode
), marka haddii miiska uu ka yar yahay 2, waa in ay ka dhigan tahay in habka wax-akhrisku uu xiray dhamaadka dhuumaha. Si kale haddii loo dhigo, waxaan isku dayeynaa inaan u qorno dhuumaha xiran, tani waa qalad. Koodhka qaladka markii ugu horeysay EPIPE
iyo calaamad SIGPIPE
ka soo muuqday daabacaaddii lixaad ee Unix.
Laakin xataa hadii uu furmo qaadku, waxa laga yaabaa in ay buuxdo. Xaaladdan oo kale, waxaan sii deyneynaa qufulka oo aan seexanno rajada ah in hab kale uu ka akhriyo dhuumaha oo uu xoreeyo meel ku filan. Markaan soo kacnay, waxaan ku soo laabanaa bilawgii, dib u dhig qufulka oo aan bilownay wareeg cusub oo duubis ah.
Haddii ay jirto meel bannaan oo bilaash ah oo ku filan dhuumaha, ka dibna waxaan u qornaa xogta annaga oo isticmaalaya i_size1
at inode (haddii dhuumuhu madhan yihiin waxay la mid noqon kartaa 0) waxay muujinaysaa dhammaadka xogta ay hore ugu jirtay. Haddii ay jirto meel ku filan oo wax lagu duubo, waxaan ka buuxin karnaa dhuumaha i_size1
si ay u PIPESIZ
. Kadibna waxaan sii deyneynaa qufulka oo aan isku daynaa inaan toosino nidaam kasta oo sugaya in laga akhriyo dhuunta. Waxaan dib ugu laabanaa bilawgii si aan u aragno inaan awoodnay inaan qorno inta ugu badan ee aan u baahanahay. Haddii aan lagu guulaysan, markaas waxaan bilaabeynaa wareeg cusub oo duubis ah.
Caadi ahaan halbeegga i_mode
inode waxa loo isticmaalaa in lagu kaydiyo ogolaanshaha r
, w
ΠΈ x
. Laakiin marka laga hadlayo dhuumaha, waxaanu tilmaamaynaa in nidaamka qaarkood uu sugayo qorista ama akhrinta iyadoo la isticmaalayo xoogaa yar IREAD
ΠΈ IWRITE
siday u kala horreeyaan. Nidaamku wuxuu dejiyaa calanka iyo wicitaanada sleep()
, waxaana la filayaa in hannaan kale oo mustaqbalka ay keeni doonaan wakeup()
.
Sixirka dhabta ah ayaa ku dhaca sleep()
ΠΈ wakeup()
. Waxaa lagu hirgeliyaa gudaha
/*
* 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) /* β¦ */
Habka sababa sleep()
Kanaal gaar ah, waxaa laga yaabaa in hadhow lagu toosiyo hab kale, taas oo keeni doonta wakeup()
isla kanaalka. writep()
ΠΈ readp()
isku dubbarid ficilladooda iyada oo loo marayo wicitaannada lammaanaha ah. ogow taas pipe.c
had iyo jeer waxay siisaa mudnaanta PPIPE
marka loo yeero sleep()
, waa sidaas sleep()
waxaa hakad geli kara calaamad
Hadda waxaan haynaa wax walba si aan u fahanno shaqada 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);
}
Waxaa laga yaabaa inaad ku fududaato inaad akhrido shaqadan hoose ilaa sare. Qaybta "akhri oo soo celi" waxaa badanaa la isticmaalaa marka ay jiraan xog qaar ah oo ku jira dhuumaha. Xaaladdan oo kale, waxaan isticmaalnaa f_offset
akhrinta, ka dibna cusboonaysii qiimaha dhimista u dhiganta.
Akhrinta soo socota, dhuumaha ayaa madhnaan doona haddii ka-dhaafka akhrigu uu gaaro i_size1
iyo inode. Waxaan dib u dhignay booska 0 waxaanan isku daynaa inaan toosinno hannaan kasta oo raba in loo qoro dhuumaha. Waxaynu ognahay in marka qaadku buuxsamo. writep()
ku seexan doona ip+1
. Oo hadda oo ay dhuumuhu maran yihiin, waxaan ku kicin karnaa si aan dib ugu bilowno wareegtada qoraalka.
Haddii aadan haysan wax aad akhrido, markaa readp()
calan dhigi kara IREAD
oo hurdo la seexdo ip+2
. Waanu ognahay waxa isaga kicin doona writep()
, marka ay u qorto xogta qaar ka mid ah dhuumaha.
Faallo ku saabsan u
"Waxaan ula dhaqmi karnaa sida hawlaha caadiga ah ee I/O ee qaata fayl, boos, kayd xusuusta, oo tirinaya tirada bytes si loo akhriyo ama loo qoro.
/*
* 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;
/* β¦ */
Dhanka xannibaadda "muxaafidka", markaa readp()
ΠΈ writep()
xannibo inode-ka ilaa ay ka dhammeeyaan shaqadooda ama ay helaan natiijo (taasi waa, wac wakeup
). plock()
ΠΈ prele()
si fudud u shaqee: adoo isticmaalaya wicitaano kala duwan sleep
ΠΈ wakeup
noo ogolow inaan toosinno hanaan kasta oo u baahan qufulka aan hadda siidaynay:
/*
* 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);
}
}
Markii hore ma fahmin sababta readp()
ma keeno prele(ip)
wicitaanka ka hor wakeup(ip+1)
. Waxa ugu horreeya waa writep()
sababa in ay wareegga, this plock(ip)
, taasoo keenaysa xidhidh haddii readp()
Wali ma saarin block-kayga, markaa si uun koodku waa inuu si sax ah u shaqeeyaa. Hadii aad eegto wakeup()
, ka dibna waxay caddaynaysaa in ay calaamad u tahay oo kaliya habka hurdada oo diyaar u ah in la fuliyo, si mustaqbalka sched()
runtii bilaabay. Markaa readp()
sababta wakeup()
, ka saartaa qufulka, dhigaysa IREAD
iyo wac sleep(ip+2)
- waxaas oo dhan ka hor writep()
dib u bilaabaya wareegga
Tani waxay dhamaystiraysaa sharraxaadda gaadiidka qaada ee daabacaadda lixaad. Koodhka fudud, cawaaqibta fog.
Xv6, kernel fudud oo u eg Unix
Si loo abuuro kernel-ka
Xeerku waxa uu ka kooban yahay dhaqangelin cad oo fikir leh 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()
dejinaya xaaladda inta ka hartay hirgelinta, oo ay ku jiraan hawlaha piperead()
, pipewrite()
ΠΈ pipeclose()
. wac nidaamka dhabta ah sys_pipe
waa duub lagu hirgeliyay
Linux 0.01
Koodhka isha ee Linux 0.01 waa la heli karaa. Waxay noqon doontaa mid wax ku ool ah in la barto hirgelinta dhuumaha tuubooyinka fs
/pipe.c
. Tani waxay isticmaashaa inode si ay u matasho dhuumaha, laakiin dhuunta lafteeda waxay ku qoran tahay C casriga ah. Haddii aad ka soo shaqeysay habkaaga iyada oo loo marayo koodka daabacaadda XNUMXaad, dhib kuma yeelan doontid halkan. Tani waa sida shaqadu u egtahay 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;
}
Adigoon xitaa fiirin qeexitaannada qaab-dhismeedka, waxaad ogaan kartaa sida tirinta tixraaca inode-ka loo isticmaalo si loo hubiyo in hawlgal qoraal ahi uu ka dhashay SIGPIPE
. Marka lagu daro shaqada byte-by-byte, shaqadani way fududahay in la barbardhigo fikradaha kor lagu sharaxay. Xataa macquul sleep_on
/wake_up
uma eka shisheeye.
Kernel-ka casriga ah ee Linux, FreeBSD, NetBSD, OpenBSD
Waxaan si degdeg ah u dhex maray qaar ka mid ah kernels casriga ah. Midkoodna ma haysto hirgelinta diskka (la yaab ma leh). Linux waxay leedahay hirgelinteeda. In kasta oo saddexda kernel ee casriga ah ee BSD ay ka kooban yihiin hirgelinta ku salaysan kood uu qoray John Dyson, sannadihii la soo dhaafay aad ayay uga duwan yihiin midba midka kale.
In la akhriyo fs
/pipe.c
(Linux) ama sys
/kern
/sys_pipe.c
(on *BSD), waxay u baahan tahay dadaal dhab ah. Koodhka maanta waxa uu ku saabsan yahay waxqabadka iyo taageerada astaamaha sida vector iyo asynchronous I/O. Iyo faahfaahinta qoondaynta xusuusta, qufulka iyo qaabaynta kernel dhamaantood aad bay u kala duwan yihiin. Tani ma aha waxa kulliyaduhu u baahan yihiin koorsada hababka hawlgalka ee hordhaca ah.
Si kastaba ha noqotee, waxaan xiisaynayay inaan qodo qaabab hore (sida abuurista SIGPIPE
oo soo noqda EPIPE
markaad wax u qorayso dhuumo xiran) dhammaan kernels casri ah oo kala duwan. Malaha waligay ma arki doono kombuyuutar PDP-11 nolosha dhabta ah, laakiin wali waxaa jira waxyaabo badan oo laga baran karo koodka la qoray sanado kahor intaanan dhalan.
Maqaal uu qoray Divi Kapoor 2011:
Source: www.habr.com