Eli nqaku lichaza ukuphunyezwa kwemibhobho kwi-Unix kernel. Ndiphoxekile kukuba inqaku lamva nje elinesihloko esithi "
Sithetha ngantoni?
Imibhobho, βmhlawumbi eyona nto iyilwayo ibalulekileyo kwi-Unix,β luphawu oluchazayo lwentanda-bulumko ye-Unix yokudibanisa iinkqubo ezincinci kunye, kunye nophawu oluqhelekileyo kumgca womyalelo:
$ echo hello | wc -c
6
Oku kusebenza kuxhomekeke kwindlela yokufowuna ebonelelwe ngekernel pipe
, echazwe kumaphepha amaxwebhu
Imibhobho ibonelela ngomjelo ongaqhelekanga wonxibelelwano lwenkqubo. Umbhobho unegalelo (ukubhala ekupheleni) kunye nesiphumo (ukufunda ekupheleni). Idatha ebhaliweyo kwigalelo lombhobho inokufundwa kwisiphumo.
Umbhobho wenziwa ngokusebenzisa umnxeba
pipe(2)
, ebuyisela iinkcazo ezimbini zefayile: enye ibhekisela kwigalelo lombhobho, okwesibini kwimveliso.
Isiphumo sokulandelela kulo myalelo ungasentla sibonisa ukwenziwa kombhobho kunye nokuhamba kwedatha kuyo ukusuka kwinkqubo enye ukuya kwenye:
$ 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
Inkqubo yomzali iminxeba pipe()
ukufumana iinkcazelo zefayile ezinyusiweyo. Inkqubo enye yomntwana ibhalela kwisibambo esinye, kwaye enye inkqubo ifunda idatha efanayo ukusuka kwesinye isiphatho. Iqokobhe lisebenzisa i-dup2 "ukuthiya ngokutsha" izichazi 3 kunye no-4 ukutshatisa i-stdin kunye ne-stdout.
Ngaphandle kwemibhobho, iqokobhe kuya kufuneka ibhale imveliso yenkqubo enye kwifayile kwaye iyigqithisele kwenye inkqubo yokufunda idatha kwifayile. Ngenxa yoko, siya kuchitha izibonelelo ezininzi kunye nendawo yediski. Nangona kunjalo, imibhobho ilungile hayi kuphela ngenxa yokuba ikuvumela ukuba uthintele ukusetyenziswa kweefayile zethutyana:
Ukuba inkqubo izama ukufunda kumbhobho ongenanto ngoko
read(2)
iya kuvala de idatha ifumaneke. Ukuba inkqubo izama ukubhala kumbhobho opheleleyo, ngokowrite(2)
iya kuvala kude kube idatha eyaneleyo ifundiwe kumbhobho ukwenza ukubhala.
Njengemfuno yePOSIX, le yipropati ebalulekileyo: ukubhala kumbhobho ukuya kuthi ga PIPE_BUF
iibytes (ubuncinci ziyi-512) kufuneka zibe yi-atomic ukwenzela ukuba iinkqubo zikwazi ukunxibelelana enye kwenye ngombhobho ngendlela yokuba iifayili eziqhelekileyo (ezinganikeli ziqinisekiso ezinjalo) zingenako.
Xa usebenzisa ifayile eqhelekileyo, inkqubo inokubhala yonke imveliso yayo kuyo kwaye iyigqithisele kwenye inkqubo. Okanye iinkqubo zingasebenza kwimodi ehambelana kakhulu, usebenzisa indlela yokubonisa yangaphandle (njenge-semaphore) ukwazisa omnye nomnye xa ukubhala okanye ukufunda kugqityiwe. Abathumeli basisindise kuyo yonke le ngxaki.
Sijonge ntoni?
Ndiza kuyicacisa ngamagama alula ukuze kube lula kuwe ukuba ucinge ukuba umqhubi wemoto unokusebenza njani. Kuya kufuneka unikeze isithinteli kunye nesimo esithile kwinkumbulo. Uya kufuna imisebenzi yokongeza kunye nokususa idatha kwi-buffer. Uya kufuna ezinye iindlela zokubiza imisebenzi ngexesha lokufunda nokubhala imisebenzi kwiinkcazo zefayile. Kwaye uya kufuna izitshixo ukuphumeza ukuziphatha okukhethekileyo okuchazwe ngasentla.
Ngoku sikulungele ukuhlolisisa ikhowudi yomthombo we-kernel phantsi kwesibane esikhanyayo ukuqinisekisa okanye ukuphikisa imodeli yethu yengqondo engacacanga. Kodwa hlala uzilungiselele izinto ongazilindelanga.
Sijonge phi?
Andazi ukuba iphi ikopi yam yencwadi edumileyo "
Ukuzulazula kwindawo yogcino lwe-TUHS kufana nokutyelela imyuziyam. Singajonga kwimbali yethu ekwabelwana ngayo, kwaye ndinentlonipho yeminyaka emininzi yomzamo wokubuyisela yonke le nto kancinci kancinci kwiikhasethi ezindala kunye noshicilelo. Kwaye ndizazi kakuhle ezo ziqwenga zingekhoyo.
Emva kokuba sanelise umnqweno wethu wokwazi ngembali yamandulo yabahambisi, sinokujonga iinkozo zale mihla ukuze sithelekise.
Ngendlela, pipe
yinkqubo yokufowuna inombolo 42 kwitheyibhile sysent[]
. Ngebhaqo?
Iinkozo ze-Unix zesiNtu (1970-1974)
Khange ndifumane umkhondo pipe(2)
okanye phakathi
I-TUHS ithi
I-Unix 1973rd Edition yayiyinguqulelo yokugqibela ene-kernel ebhalwe ngolwimi lwendibano, kodwa kunye nenguqulelo yokuqala enemibhobho. Ebudeni bowe-XNUMX, kwenziwa umsebenzi wokuphucula uhlelo lwesithathu, ikernel yaphinda yabhalwa ngoC, kwaza kwavela uhlelo lwesine lweUnix.
Omnye umfundi ufumene iskena soxwebhu apho uDoug McIlroy ecebise ngombono "wokudibanisa iinkqubo njengethumbu legadi."
Kwincwadi kaBrian Kernighan
Xa i-Unix yaphuma, ukuthanda kwam ii-coroutines kwandikhokelela ekubeni ndibuze umbhali we-OS, u-Ken Thompson, ukuba avumele idatha ebhaliweyo kwinkqubo ukuba ihambe kungekhona nje kwisixhobo, kodwa kunye nokuphuma kwenye inkqubo. UKen wagqiba kwelokuba kunokwenzeka. Nangona kunjalo, njenge-minimalist, wayefuna ukuba wonke umsebenzi wenkqubo udlale indima ebalulekileyo. Ngaba ukubhala ngokuthe ngqo phakathi kweenkqubo ngokwenene kuyinzuzo enkulu ngaphezu kokubhalela ifayile ephakathi? Kwaba kuphela xa ndenza isindululo esikhethekileyo ngegama elinomtsalane elithi "umbhobho" kunye nenkcazo ye-syntax yokusebenzisana phakathi kweenkqubo apho uKen wadanduluka wathi: "Ndiya kuyenza!"
Kwaye wenza. Ngobunye ubusuku obumnandi, u-Ken watshintsha i-kernel kunye neqokobhe, walungisa iinkqubo ezininzi ezisemgangathweni ukuze balungelelanise indlela abalamkela ngayo igalelo (elinokuvela kumbhobho), kwaye watshintsha namagama eefayile. Ngosuku olulandelayo, imibhobho yaqala ukusetyenziswa kakhulu kwizicelo. Ekupheleni kweveki, oonobhala babewasebenzisela ukuthumela amaxwebhu asuka kwiprosesa yamagama ukuya kumshicileli. Kancinane kamva, uKen wathatha indawo ye-API yoqobo kunye ne-syntax yokusonga ukusetyenziswa kwemibhobho ngeendibano zococeko, eziye zasetyenziswa ukusukela ngoko.
Ngelishwa, ikhowudi yemvelaphi yohlelo lwesithathu Unix kernel ilahlekile. Kwaye nangona sinekhowudi yomthombo we-kernel ebhalwe kwi-C
Sinamaxwebhu okubhaliweyo e pipe(2)
kokubini ukhupho, ngoko ungaqala ngokuphendla uxwebhu pipe(2)
ibhalwe ngolwimi lwendibano kwaye ibuyisela ingcaciso yefayile enye kuphela, kodwa sele ibonelela ngomsebenzi ongundoqo olindelekileyo:
Umnxeba wenkqubo umbhobho yenza igalelo/imveliso indlela ebizwa ngokuba ngumbhobho. Inkcazo yefayile ebuyisiweyo ingasetyenziselwa ukufunda nokubhala imisebenzi. Xa kukho into ebhaliweyo kumbhobho, ukuya kuthi ga kwi-504 bytes yedatha ikhuselwe, emva koko inkqubo yokubhala iyanqunyanyiswa. Xa kufundwa kumbhobho, idatha egciniweyo iyathathwa.
Kunyaka olandelayo ikernel yayibhalwe ngokutsha ngoC, kwaye pipe(fildes)
"
Umnxeba wenkqubo umbhobho yenza igalelo/imveliso indlela ebizwa ngokuba ngumbhobho. Izichazi zefayile ezibuyisiweyo zingasetyenziselwa ukufunda nokubhala imisebenzi. Xa kukho into ebhaliweyo kumbhobho, isiphatho esibuyiswe nge-r1 (resp. fildes[1]) siyasetyenziswa, sigcinwe kwi-4096 bytes yedatha, emva koko inkqubo yokubhala iyanqunyanyiswa. Xa ufunda kumbhobho, isibambo sibuyele kwi-r0 (resp. fildes [0]) sithatha idatha.
Kucingelwa ukuba xa umbhobho uchaziwe, iinkqubo ezimbini (okanye ngaphezulu) zokunxibelelana (ezenziwe ngeminxeba elandelayo Ifom) iya kudlulisela idatha ukusuka kumbhobho usebenzisa iifowuni ukufunda ΠΈ bhala.
Iqokobhe linesivakalisi sokuchaza uluhlu olulandelelanayo lweenkqubo ezidityaniswe ngumbhobho.
Iifowuni zokufunda kumbhobho ongenanto (ongekho datha ye-buffered) enesiphelo esinye kuphela (zonke izichazi zefayile zokubhala zivaliwe) zibuyisela "end of file". Iifowuni zokubhala kwimeko efanayo azihoywa.
Kwangoko
Uhlelo lwesithandathu lweUnix (1975)
Masiqale ukufunda ikhowudi yomthombo we-Unix
Kangangeminyaka emininzi le ncwadi iingonyama yayikuphela koxwebhu kwi Unix kernel ekhoyo ngaphandle kweBell Labs. Nangona ilayisenisi yohlelo lwesithandathu yayivumela ootitshala ukuba basebenzise ikhowudi yomthombo wayo, ilayisenisi yohlelo lwesixhenxe yayingabandakanyi oku, ngoko ke le ncwadi yasasazwa ngokohlobo lweekopi ezichwetheziweyo ezingekho mthethweni.
Namhlanje ungathenga ukuprintwa kwakhona kwencwadi, ikhava ebonisa abafundi kumatshini wokukopisha. Kwaye ndiyabulela kuWarren Toomey (oqale iprojekthi yeTUHS) unokukhuphela
Ngaphezulu kweminyaka eyi-15 eyadlulayo, ndachwetheza ikopi yekhowudi yomthombo enikwe kuyo iingonyama, kuba andizange ndiwuthande umgangatho wekopi yam evela kwinani elingaziwayo lezinye iikopi. I-TUHS yayingekabikho kwaye andizange ndikwazi ukufikelela kwimithombo yakudala. Kodwa ngo-1988, ndafumana iteyiphu endala ye-9-track equlethe i-backup esuka kwikhompyuter ye-PDP11. Kwakunzima ukuxelela ukuba yayisebenza, kodwa kwakukho i-intact / usr / src / umthi apho uninzi lweefayile zibhalwe ngonyaka we-1979, nangona zikhangeleka zamandulo. Yayiluhlelo lwesixhenxe okanye iPWB ephuma kuyo, njengoko ndandikholelwa.
Ndithathe into efunyenweyo njengesiseko kwaye ndahlela ngesandla imithombo kuhlelo lwesithandathu. Enye ikhowudi yahlala ifana, kodwa enye kwafuneka ihlelwe kancinane, itshintshe ithokheni yangoku += ukuya kwephelelwe lixesha =+. Ezinye izinto zicinywe ngokulula, kwaye ezinye kwafuneka zibhalwe ngokutsha, kodwa hayi kakhulu.
Kwaye namhlanje sinokufunda kwi-intanethi kwi-TUHS ikhowudi yomthombo wohlelo lwesithandathu ukusuka
Ngendlela, ekuboneni kuqala, eyona nto iphambili yekhowudi yeC ngaphambi kwexesha leKernighan kunye neRitchie ubufutshane. Ayiqhelekanga ukuba ndikwazi ukufaka amaqhekeza ekhowudi ngaphandle kokuhlela okubanzi ukuze ilingane indawo yokubonisa emxinwa kakhulu kwindawo yam.
Ekuqaleni
/*
* 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
Ubungakanani bebuffer abutshintshanga ukusukela kuhlelo lwesine. Kodwa apha siyabona, ngaphandle kwawo nawaphi na amaxwebhu oluntu, ukuba imibhobho yayikhe yasebenzisa iifayile njengogcino lokugcina!
Ngokuphathelele iifayile ze-LARG, ziyahambelana
Nantsi indlela yokwenyani yokufowuna 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;
}
Izimvo zichaza ngokucacileyo ukuba kuqhubeka ntoni apha. Kodwa ukuqonda ikhowudi akulula kangako, ngokuyinxenye ngenxa yendlela "R0
ΠΈ R1
Iiparamitha zokufowuna kwenkqubo kunye namaxabiso okubuyisela agqithisiwe.
Masizame nge
pipe()
kufuneka idlule R0
ΠΈ R1
buyisela amanani eenkcazo zeefayile zokufunda nokubhala. falloc()
ibuyisela isalathisi kulwakhiwo lwefayile, kodwa kwakhona "ibuyisela" nge u.u_ar0[R0]
kunye nenkcazelo yefayile. Oko kukuthi, ikhowudi igcina ngaphakathi r
isichazi sefayile yokufunda kwaye yabela inkcazo yefayile yokubhala ngokuthe ngqo ukusuka u.u_ar0[R0]
emva kwefowuni yesibini falloc()
.
Iflegi FPIPE
, esibeka xa sidala umbhobho, silawula ukuziphatha komsebenzi
/*
* 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);
}
/* β¦ */
}
Emva koko umsebenzi readp()
Π² pipe.c
ifunda idatha kumbhobho. Kodwa kungcono ukulandelela ukuphunyezwa ukuqala ukusuka writep()
. Kwakhona, ikhowudi iye yaba nzima ngakumbi ngenxa yeengqungquthela zokudlula iingxabano, kodwa ezinye iinkcukacha zinokushiywa.
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;
}
Sifuna ukubhala ii-bytes kwigalelo lombhobho u.u_count
. Okokuqala kufuneka sitshixe i-inode (jonga ngezantsi plock
/prele
).
Emva koko sijonga i-inode reference counter. Ngethuba nje zombini iziphelo zombhobho zihlala zivulekile, i-counter kufuneka ilingane no-2. Sibamba ikhonkco enye (ukusuka rp->f_inode
), ngoko ke ukuba i-counter ingaphantsi kwe-2, kufuneka ithethe ukuba inkqubo yokufunda ivale isiphelo sayo sombhobho. Ngamanye amazwi, sizama ukubhalela kumbhobho ovaliweyo, kwaye oku kuyimpazamo. Ikhowudi yempazamo yexesha lokuqala EPIPE
kunye nomqondiso SIGPIPE
yavela kuhlelo lwesithandathu lwe-Unix.
Kodwa nokuba i-conveyor ivuliwe, inokuba igcwele. Kule meko, sikhulula isitshixo kwaye silale ngethemba lokuba enye inkqubo iya kufunda kwipayipi kwaye ikhulule indawo eyaneleyo kuyo. Emva kokuba sivukile, sibuyela ekuqaleni, sixhoma isitshixo kwakhona kwaye siqale umjikelo omtsha wokurekhoda.
Ukuba kukho indawo eyaneleyo yamahhala kwipayipi, ngoko sibhala idatha kuyo ngokusebenzisa i_size1
inode (ukuba umbhobho awunanto, unokulingana no-0) ubonisa ukuphela kwedatha esele iqulethe. Ukuba kukho indawo yokurekhoda eyaneleyo, sinokugcwalisa umbhobho ukusuka i_size1
Π΄ΠΎ PIPESIZ
. Emva koko sikhulula isitshixo kwaye sizame ukuvusa nayiphi na inkqubo elinde ukufunda kumbhobho. Sibuyela ekuqaleni ukuze sibone ukuba siye sakwazi ukubhala ii-bytes ezininzi njengoko sifuna. Ukuba ayiphumelelanga, ngoko siqala umjikelo omtsha wokurekhoda.
Ngokuqhelekileyo iparameter i_mode
i-inode isetyenziselwa ukugcina iimvume r
, w
ΠΈ x
. Kodwa kwimeko yemibhobho, sibonisa ukuba inkqubo ethile ilindele ukubhala okanye ukufunda usebenzisa amasuntswana IREAD
ΠΈ IWRITE
ngokulandelelanayo. Inkqubo ibeka iflegi kunye neefowuni sleep()
, kwaye kulindeleke ukuba enye inkqubo kwixesha elizayo iya kubangela wakeup()
.
Umlingo wokwenyani uyenzeka sleep()
ΠΈ wakeup()
. Ziphunyezwa kwi
/*
* 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) /* β¦ */
Inkqubo ebangela sleep()
kwijelo elithile, linokuthi kamva livuswe yenye inkqubo, eya kubangela wakeup()
kwitshaneli enye. writep()
ΠΈ readp()
ukulungelelanisa izenzo zabo ngeefowuni ezidityanisiweyo. Qaphela oko pipe.c
isoloko ibeka indawo yokuqala PPIPE
xa ebizwa sleep()
, yiloo nto ke sleep()
inokuphazanyiswa luphawu.
Ngoku sinayo yonke into yokuqonda umsebenzi 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);
}
Ungakufumanisa kulula ukufunda lo msebenzi ukusuka ezantsi ukuya phezulu. Isebe "lokufunda nokubuyisela" lidla ngokusetyenziswa xa kukho idatha ethile kumbhobho. Kule meko, sisebenzisa f_offset
ukufunda, kwaye emva koko uhlaziye ixabiso le-offset ehambelanayo.
Kufundo olulandelayo, umbhobho uya kuba nanto ukuba i-read offset ifikile i_size1
kwi inode. Siseta kwakhona indawo ku-0 kwaye sizame ukuvusa nayiphi na inkqubo efuna ukubhala kumbhobho. Siyazi ukuba xa i-conveyor igcwele, writep()
uya kulala ip+1
. Kwaye ngoku umbhobho ungenanto, sinokuwuvusa ukuze siphinde siqalise umjikelo wawo wokubhala.
Ukuba awunanto yokufunda, ngoko readp()
inokuseta iflegi IREAD
ndize ndilale ip+2
. Siyazi ukuba yintoni eya kumvusa writep()
, xa ibhala idatha ethile kumbhobho.
Izimvo kwi u
"Sinokubaphatha njengemisebenzi eqhelekileyo ye-I / O ethatha ifayile, indawo, i-buffer kwimemori, kwaye ubale inani leebhayithi zokufunda okanye ukubhala.
/*
* 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;
/* β¦ */
Ngokubhekiselele kwi "conservative" blocking, ke readp()
ΠΈ writep()
vala i-inode de bagqibe umsebenzi wabo okanye bafumane isiphumo (oko kukuthi, ukufowuna wakeup
). plock()
ΠΈ prele()
sebenza ngokulula: usebenzisa iseti eyahlukileyo yeefowuni sleep
ΠΈ wakeup
sivumele ukuba sivuse nayiphi na inkqubo efuna isitshixo esisandula ukuyikhulula:
/*
* 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);
}
}
Ekuqaleni ndandingasiqondi isizathu readp()
ayibangeli prele(ip)
phambi kwefowuni wakeup(ip+1)
. Into yokuqala kukuba writep()
ibangela kumjikelo wayo, oku plock(ip)
, ekhokelela kwi-deadlock ukuba readp()
andikayisusi ibhloko yam okwangoku, ngoko ke ikhowudi kufuneka isebenze ngokuchanekileyo. Ukuba ujonga wakeup()
, ke kuyacaca ukuba iphawula kuphela inkqubo yokulala njengoko ilungele ukuphumeza, ukwenzela ukuba kwixesha elizayo sched()
ngenene wayisungula. Ngoko readp()
bangela wakeup()
, isusa isitshixo, iseti IREAD
kunye neefowuni sleep(ip+2)
- konke oku ngaphambili writep()
iqalisa kwakhona umjikelo.
Oku kugqiba inkcazo yabahambisi kuhlelo lwesithandathu. Ikhowudi elula, imiphumo efikelela kude.
Xv6, ikernel elula efana ne-Unix
Ukwenza i-kernel
Ikhowudi iqulethe ukuphunyezwa okucacileyo kunye nokucinga 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()
ibeka imo yophunyezo oluseleyo, olubandakanya imisebenzi piperead()
, pipewrite()
ΠΈ pipeclose()
. Okwenyani umnxeba wenkqubo sys_pipe
sisisongelo esimiliselwe ngaphakathi
Linux 0.01
Linux 0.01 ikhowudi yemvelaphi inokufumaneka. Kuya kuba kufundisa ukufunda ukuphunyezwa kwemibhobho yakhe fs
/pipe.c
. Oku kusebenzisa i-inode ukumela umbhobho, kodwa umbhobho wona ngokwawo ubhalwe ngohlobo lwangoku C. Ukuba uye wasebenza ngendlela yakho ngekhowudi yohlelo lwesi-6, awuyi kuba nangxaki apha. Le yindlela umsebenzi okhangeleka ngayo 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;
}
Ngaphandle kokujonga iinkcazo zesakhiwo, ungafumanisa ukuba ireferensi yokubala ye-inode isetyenziswa njani ukujonga ukuba umsebenzi wokubhala uphumela SIGPIPE
. Ukongeza ekusebenzeni i-byte-by-byte, lo msebenzi kulula ukuthelekisa kunye neengcamango ezichazwe ngasentla. Nkqu nengqondo sleep_on
/wake_up
ayibonakali ingaqhelekanga.
Iinkozo zeLinux zanamhlanje, iFreeBSD, iNetBSD, iOpenBSD
Ngokukhawuleza ndatyhutyha iinkozo zale mihla. Akukho namnye kubo unokuphunyezwa kwediski kwakhona (ayimangalisi). I-Linux inokuphunyezwa kwayo. Nangona iikernel ezintathu ze-BSD zanamhlanje ziqulethe ukuphunyezwa okusekwe kwikhowudi eyabhalwa nguJohn Dyson, ekuhambeni kweminyaka baye bahluke kakhulu omnye komnye.
Ukufunda fs
/pipe.c
(kwiLinux) okanye sys
/kern
/sys_pipe.c
(kwi-BSD), kuthatha ukuzinikela ngokwenene. Ikhowudi yanamhlanje imalunga nokusebenza kunye nenkxaso yeempawu ezifana ne-vector kunye ne-asynchronous I/O. Kwaye iinkcukacha zokwabiwa kwememori, izitshixo kunye noqwalaselo lwe-kernel zonke ziyahluka kakhulu. Oku ayisiyiyo into efunwa ziikholeji kwikhosi yentshayelelo yeenkqubo zokusebenza.
Ngapha koko, bendinomdla wokwemba iipateni ezindala (ezifana nokuvelisa SIGPIPE
kwaye ubuye EPIPE
xa ubhalela kumbhobho ovaliweyo) kuzo zonke ezi nkozo zahlukeneyo zanamhlanje. Andisoze ndibone ikhompyuter ye-PDP-11 ebomini bokwenyani, kodwa kusekho okuninzi ekufuneka ndikufunde kwikhowudi eyabhalwa kwiminyaka ngaphambi kokuba ndizalwe.
Inqaku elibhalwe nguDivi Kapoor ngo-2011:
umthombo: www.habr.com