Ity lahatsoratra ity dia mamaritra ny fampiharana ny fantsona ao amin'ny kernel Unix. Somary diso fanantenana aho fa nisy lahatsoratra vao haingana mitondra ny lohateny hoe "
Inona no resahina?
Pipelines dia "angamba ny famoronana manan-danja indrindra ao amin'ny Unix" - endri-javatra mamaritra ny filozofia fototry ny Unix amin'ny fametrahana programa kely, sy ny teny filamatra mahazatra:
$ echo hello | wc -c
6
Io fampiasa io dia miankina amin'ny antson'ny rafitra nomen'ny kernel pipe
, izay voalaza ao amin'ny pejin'ny antontan-taratasy
Ny fantsona dia manome fantsona tokana ho an'ny fifandraisana eo amin'ny dingana. Ny fantsona dia manana fidirana (manoratana farany) ary mivoaka (vakiana farany). Ny angona voasoratra amin'ny fidirana amin'ny fantsona dia azo vakiana amin'ny famoahana.
Ny fantsona dia noforonina amin'ny fiantsoana
pipe(2)
, izay mamerina mpamaritra rakitra roa: ny iray dia manondro ny fampidirana ny fantsona, ny faharoa amin'ny famoahana.
Ny vokatra trace avy amin'ny baiko etsy ambony dia mampiseho ny famoronana fantsona sy ny fikorianan'ny angona avy amin'ny dingana iray mankany amin'ny iray hafa:
$ 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
Miantso ny fizotry ny ray aman-dreny pipe()
mba hahazoana famariparitana rakitra mifatotra. Ny fizotry ny ankizy iray dia manoratra amin'ny mpamoritra iray ary ny dingana iray hafa mamaky angona mitovy amin'ny mpamoritra iray hafa. Ny akorandriaka "manova anarana" famaritana 2 sy 3 miaraka amin'ny dup4 hifanaraka amin'ny stdin sy stdout.
Raha tsy misy pipelines, ny akorandriaka dia tsy maintsy manoratra ny vokatra avy amin'ny dingana iray mankany amin'ny rakitra iray ary mitondra izany mankany amin'ny dingana hafa mba hamakiana ny angona avy amin'ny rakitra. Vokatr'izany dia handany loharano bebe kokoa sy habaka kapila izahay. Na izany aza, ny fantsona dia tsara kokoa noho ny fisorohana ny rakitra vonjimaika:
Raha misy dingana manandrana mamaky amin'ny fantsona tsy misy na inona na inona, dia
read(2)
hosakanana mandra-pivoaka ny angona. Raha misy dingana manandrana manoratra amin'ny fantsona feno, diawrite(2)
dia hosakanana mandra-pamakiana ny angona ampy avy amin'ny fantsona hamitana ny fanoratana.
Tahaka ny fepetra takian'ny POSIX, fananana manan-danja ity: manoratra amin'ny fantsona hatramin'ny PIPE_BUF
bytes (farafaharatsiny 512) dia tsy maintsy atomika mba hahafahan'ireo dingana mifandray amin'ny alΓ lan'ny fantsona amin'ny fomba tsy ahafahan'ny rakitra mahazatra (izay tsy manome antoka toy izany).
Miaraka amin'ny rakitra mahazatra, ny dingana iray dia afaka manoratra ny vokatra rehetra ao aminy ary mampita izany amin'ny dingana hafa. Na ny dingana dia afaka miasa amin'ny fomba mitovy mafy, mampiasa mekanika famantarana ivelany (toy ny semaphore) hifampilazana momba ny fahavitan'ny fanoratana na famakiana. Manavotra antsika amin'izany fahasahiranana rehetra izany ny mpitatitra.
Inona no tadiavintsika?
Hazavaiko amin'ny rantsantanako mba hahamora kokoa ny sary an-tsainao ny fomba fiasan'ny conveyor. Mila mametraka buffer sy fanjakana sasany ao anaty fitadidiana ianao. Mila fiasa ianao hanampiana sy hanesorana ny angona amin'ny buffer. Mila fitaovana sasany ianao hiantso ireo asa mandritra ny famakiana sy fanoratana amin'ny mpamoritra rakitra. Ary ilaina ny hidin-trano mba hampiharana ny fihetsika manokana voalaza etsy ambony.
Vonona izahay hanadihady ny kaody loharanon'ny kernel eo ambanin'ny jiro mamirapiratra mba hanamafisana na hanaporofoana ny modely ara-tsainay. Fa miomana mandrakariva amin'ny tsy ampoizina.
Aiza no tadiavintsika?
Tsy fantatro hoe aiza no misy ny dika mitovy amin'ilay boky malaza.
Toy ny mitsidika tranombakoka ny mandehandeha amin'ny arsiva TUHS. Afaka mijery ny tantarantsika isika ary manaja ny ezaka an-taonany hamerenana tsikelikely ireo fitaovana rehetra ireo avy amin'ny kasety sy ny printy taloha. Ary fantatro tsara ireo sombiny mbola tsy hita.
Rehefa afa-po ny fahalianantsika momba ny tantaran'ny fantsona taloha, dia afaka mijery ireo cores maoderina isika ho fampitahana.
Raha eny, pipe
dia ny laharana antso an-tariby 42 eo amin'ny latabatra sysent[]
. Kisendrasendra?
Kernel Unix nentim-paharazana (1970β1974)
Tsy nahita soritra aho pipe(2)
na in
Manambara izany ny TUHS
Ny andiany fahatelo amin'ny Unix dia ny dikan-teny farany misy kernel voasoratra amin'ny assembler, fa koa ny dikan-teny voalohany misy pipelines. Nandritra ny taona 1973, nisy ny asa hanatsarana ny andiany fahatelo, naverina nosoratana tamin'ny C ny kernel, ka teraka ny andiany fahefatra amin'ny Unix.
Ny mpamaky iray dia nahita scan ny antontan-taratasy iray izay nanoloran'i Doug McIlroy ny hevitra hoe "fampifandraisana fandaharana toy ny hose zaridaina."
Ao amin'ny bokin'i Brian Kernighan
Rehefa niseho ny Unix, ny fitiavako ny coroutine dia nahatonga ahy hanontany ny mpanoratra OS, Ken Thompson, mba hamela ny angon-drakitra voasoratra amin'ny dingana sasany handeha tsy amin'ny fitaovana ihany, fa koa amin'ny fivoahana mankany amin'ny dingana hafa. Nanapa-kevitra i Ken fa azo atao izany. Na izany aza, amin'ny maha minimalist azy, tiany hanana anjara toerana lehibe ny endri-javatra rehetra. Tena tombony lehibe tokoa ve ny fanoratana mivantana eo anelanelan'ny dingana raha oharina amin'ny fanoratana amin'ny rakitra mpanelanelana? Ary rehefa nanao tolo-kevitra manokana miaraka amin'ny anarana mahasarika "pipeline" sy ny famaritana ny syntax ny fifaneraserana amin'ny dingana aho, dia nihiaka ihany i Ken tamin'ny farany: "Izaho no hanao izany!".
Ary nanao. Indray takariva nahatsiravina, nanova ny kernel sy ny akorany i Ken, nanamboatra programa manara-penitra maromaro mba hanara-penitra ny fomba fanekeny ny fidirana (izay mety ho avy amin'ny fantsona), ary nanova ny anaran-drakitra. Ny ampitson'iny, dia tena be mpampiasa amin'ny fampiharana ny pipelines. Tamin'ny faran'ny herinandro dia nampiasa azy ireo ny sekretera mba handefasana antontan-taratasy avy amin'ny mpanodina teny mankany amin'ny mpanonta. Somary taty aoriana, nosoloin'i Ken ny API sy syntax tany am-boalohany amin'ny famenoana ny fampiasana fantsona miaraka amin'ny fivoriambe madio kokoa izay nampiasaina hatramin'izay.
Indrisy anefa fa very ny code source ho an'ny kernel Unix andiany fahatelo. Ary na dia manana ny code source kernel voasoratra ao amin'ny C
Manana lahatsoratra momba ny antontan-taratasy izahay pipe(2)
avy amin'ny famoahana roa, mba hahafahanao manomboka amin'ny fikarohana ny antontan-taratasy pipe(2)
dia voasoratra ao amin'ny assembler ary tsy mamerina afa-tsy iray ny famaritana ny rakitra, fa efa manome ny asa fototra andrasana:
System antso sodina mamorona mekanika I/O antsoina hoe pipeline. Ny mpamaritra rakitra naverina dia azo ampiasaina amin'ny asa famakiana sy fanoratana. Rehefa misy zavatra voasoratra ao amin'ny fantsona, dia mitahiry angon-drakitra hatramin'ny 504 bytes izany, ary avy eo dia miato ny fizotran'ny fanoratana. Rehefa mamaky avy amin'ny fantsona dia alaina ny angon-drakitra buffered.
Tamin'ny taona nanaraka, ny kernel dia naverina nosoratana tamin'ny C, ary pipe(fildes)
"
System antso sodina mamorona mekanika I/O antsoina hoe pipeline. Ireo mpamoritra rakitra naverina dia azo ampiasaina amin'ny asa famakiana sy fanoratana. Rehefa misy zavatra voasoratra ao amin'ny pipeline, dia ampiasaina ny descriptor miverina amin'ny r1 (resp. fildes [1]), voatahiry hatramin'ny 4096 bytes ny angona, ary avy eo dia miato ny fizotran'ny fanoratana. Rehefa mamaky avy amin'ny fantsona dia miverina amin'ny r0 (resp. fildes[0]) ny descriptor maka ny angona.
Heverina fa rehefa voafaritra ny fantsona iray, dia misy dingana roa (na mihoatra) mifandray (natao tamin'ny fiantsoana manaraka. sotro rovitra) dia handefa angona avy amin'ny fantsona mampiasa antso vakio ny ΠΈ manoratra.
Ny akorandriaka dia manana syntax hamaritana ny fizotry ny dingana mifandray amin'ny alalan'ny fantsona.
Antso hamaky avy amin'ny fantsona tsy misy na inona na inona (tsy misy angon-drakitra voatahiry) izay manana fiafarana tokana (mihidy avokoa ny famaritana rakitra rehetra) dia mamerina ny "faran'ny rakitra". Ny fanoratana antso amin'ny toe-javatra mitovy amin'izany dia tsy raharahaina.
voalohany
Unix Sixth Edition (1975)
Manomboka mamaky ny kaody loharano Unix
Nandritra ny taona maro ny boky Lions no hany antontan-taratasy momba ny kernel Unix hita ivelan'ny Bell Labs. Na dia namela ny mpampianatra hampiasa ny kaody loharanony aza ny fahazoan-dΓ lana fanontana fahenina, ny fahazoan-dΓ lana fanontana fahafito dia tsy nampiditra izany fahafahana izany, ka nozaraina tamin'ny kopia tsy ara-dalΓ na ilay boky.
Androany dia afaka mividy dika mitovy amin'ny boky ianao, izay mampiseho ireo mpianatra ao amin'ny copier ny fonony. Ary misaotra an'i Warren Toomey (izay nanomboka ny tetikasa TUHS), azonao atao ny misintona
Maherin'ny 15 taona lasa izay, nitendry dika mitovy amin'ny kaody loharano nomena aho Lionssatria tsy tiako ny kalitaon'ny dikako avy amin'ny isa tsy fantatra hafa. Tsy mbola nisy ny TUHS, ary tsy nahazo ny loharano taloha aho. Saingy tamin'ny 1988 dia nahita horonam-peo tranainy misy lΓ lam-pandehanana 9 aho izay nanana backup avy amin'ny solosaina PDP11. Sarotra ny nahafantatra raha niasa izy io, saingy nisy hazo / usr / src / tsy misy dikany izay nanamarika ny ankamaroan'ny rakitra tamin'ny 1979, izay toa tranainy aza. Fanontana fahafito io, na derivative PWB, hoy aho.
Noraisiko ho fototry ny fikarohana ary nanova ny loharano ho amin'ny toetry ny andiany fahenina aho. Ny ampahany amin'ny kaody dia tsy miova, ny ampahany dia tsy maintsy ovaina kely, nanova ny marika maoderina += ho amin'ny =+ efa lany andro. Nisy nofafana tsotra izao, ary nisy zavatra tsy maintsy naverina nosoratana tanteraka, fa tsy be loatra.
Ary ankehitriny dia afaka mamaky an-tserasera ao amin'ny TUHS ny kaody loharanon'ny andiany fahenina amin'ny
Raha ny marina, raha vao jerena, ny tena mampiavaka ny C-code talohan'ny vanim-potoanan'i Kernighan sy Ritchie dia ny azy. fohy. Matetika aho no afaka mampiditra sombin-kaody tsy misy fanitsiana be dia be mba hifanaraka amin'ny faritra fampisehoana somary tery amin'ny tranokalako.
Tany am-piandohana
/*
* 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
Tsy niova ny haben'ny buffer hatramin'ny andiany fahefatra. Saingy eto isika dia mahita, tsy misy antontan-taratasy ho an'ny daholobe, fa ny pipelines indray mandeha dia nampiasa rakitra ho fitahirizana miverina!
Raha ny rakitra LARG dia mifanaraka amin'ny
Ity ny tena antson'ny rafitra 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;
}
Ny fanehoan-kevitra dia mamaritra mazava tsara ny zava-mitranga eto. Saingy tsy mora ny mahatakatra ny kaody, amin'ny ampahany noho ny fomba "R0
ΠΈ R1
ny paramètre antso an-tariby sy ny sanda miverina dia mandalo.
Andeha isika hanandrana
pipe()
amin'ny alalan'ny R0
ΠΈ R1
avereno ny laharan'ny famaritana rakitra ho an'ny famakiana sy fanoratana. falloc()
mamerina tondro mankany amin'ny firafitry ny rakitra, fa koa "miverina" amin'ny alΓ lan'ny u.u_ar0[R0]
ary mpamoritra rakitra. Izany hoe, voatahiry ao ny kaody r
mpamoritra rakitra ho an'ny famakiana ary manendry mpamoritra ho an'ny fanoratana mivantana avy u.u_ar0[R0]
aorian'ny fiantsoana faharoa falloc()
.
sainam-pirenena FPIPE
, izay apetrakay rehefa mamorona ny fantsona, dia mifehy ny fihetsiky ny asa
/*
* 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);
}
/* β¦ */
}
Avy eo ny asa readp()
Π² pipe.c
mamaky angona avy amin'ny fantsona. Saingy tsara kokoa ny manara-maso ny fampiharana manomboka amin'ny writep()
. Indray mandeha, nanjary sarotra kokoa ny fehezan-dalΓ na noho ny toetry ny fifanolanana mandalo, saingy azo esorina ny antsipiriany sasany.
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;
}
Te-hanoratra bytes amin'ny fampidirana pipeline izahay u.u_count
. Voalohany dia mila manidy ny inode isika (jereo eto ambany plock
/prele
).
Avy eo dia manamarina ny isan'ny reference inode isika. Raha mbola misokatra ny tendrony roa amin'ny fantsona dia tokony ho 2 ny kaontera. Mifikitra amin'ny rohy iray isika (avy amin'ny rp->f_inode
), koa raha latsaky ny 2 ny kaontera, dia tokony hidika izany fa nanakatona ny faran'ny fantsona ny fizotran'ny famakiana. Amin'ny teny hafa, miezaka manoratra amin'ny fantsona mihidy izahay, izay fahadisoana. Kaody fahadisoana voalohany EPIPE
ary signal SIGPIPE
niseho tamin'ny andiany fahenina amin'ny Unix.
Fa na dia misokatra aza ny conveyor dia mety ho feno. Amin'ity tranga ity, dia mamoaka ny hidin-trano izahay ary matory amin'ny fanantenana fa hisy dingana hafa hamaky ny fantsona ary hanafaka toerana ampy ao anatiny. Rehefa mifoha isika dia miverina amin'ny voalohany, ahantona indray ny hidin-trano ary manomboka tsingerina fanoratana vaovao.
Raha toa ka ampy ny toerana malalaka ao amin'ny fantsona, dia manoratra angon-drakitra amin'izany izahay i_size1
ny inode'a (miaraka amin'ny fantsona tsy misy na inona na inona dia mety mitovy amin'ny 0) manondro ny faran'ny angona efa misy azy. Raha ampy ny toerana hanoratana dia afaka mameno ny fantsona isika i_size1
Π΄ΠΎ PIPESIZ
. Avy eo dia mamoaka ny hidin-trano izahay ary manandrana mamoha ny dingana rehetra miandry ny famakiana avy amin'ny fantsona. Miverina any amin'ny voalohany isika mba hijery raha nahavita nanoratra bytes betsaka araka izay ilainay. Raha tsy izany dia manomboka tsingerina fandraisam-peo vaovao isika.
Matetika parameter i_mode
inode dia ampiasaina hitahiry fahazoan-dΓ lana r
, w
ΠΈ x
. Fa amin'ny resaka pipelines, dia manambara izahay fa misy dingana miandry ny fanoratana na famakiana mampiasa bits IREAD
ΠΈ IWRITE
tsirairay avy. Ny dingana dia mametraka ny saina sy miantso sleep()
, ary antenaina fa amin'ny ho avy dia hisy dingana hafa hiantso wakeup()
.
Ny tena majika dia mitranga ao sleep()
ΠΈ wakeup()
. Izy ireo dia ampiharina amin'ny
/*
* 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) /* β¦ */
Ny dingana izay miantso sleep()
ho an'ny fantsona manokana, dia mety ho fohazina amin'ny dingana iray hafa, izay hiantso wakeup()
ho an'ny fantsona iray ihany. writep()
ΠΈ readp()
mandrindra ny hetsika ataon'izy ireo amin'ny alalan'ny antso mitambatra toy izany. Mariho fa pipe.c
atao laharam-pahamehana foana PPIPE
rehefa antsoina sleep()
, ka ny rehetra sleep()
azo tapahina amin'ny alalan'ny famantarana.
Ankehitriny isika dia manana ny zava-drehetra mba hahatakatra ny asa 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);
}
Mety ho mora kokoa aminao ny mamaky ity asa ity manomboka any ambany ka hatrany ambony. Ny sampana "mamaky sy miverina" dia matetika ampiasaina rehefa misy angon-drakitra ao anaty fantsona. Amin'ity tranga ity, mampiasa izahay f_offset
vakio, ary havaozy avy eo ny sandan'ny offset mifanaraka amin'izany.
Amin'ny famakiana manaraka dia ho foana ny fantsona raha toa ka tonga ny offset vakina i_size1
amin'ny inode. Averinay amin'ny 0 ny toerana ary manandrana mamoha ny dingana rehetra te hanoratra amin'ny fantsona. Fantatsika fa rehefa feno ny conveyor, writep()
matory amin'ny ip+1
. Ary satria foana ny fantsona, dia afaka mamoha azy isika hanohy ny tsingerina fanoratana.
Raha tsy misy zavatra hovakiana dia readp()
afaka mametraka saina IREAD
ary renoky ny torimaso ip+2
. Fantatsika izay hanaitra azy writep()
rehefa manoratra angona sasany amin'ny fantsona.
Hevitra momba ny u
Β» Azontsika atao toy ny fiasa I/O mahazatra izy ireo izay maka rakitra, toerana, buffer amin'ny fitadidiana, ary manisa ny isan'ny bytes hovakiana na soratana.
/*
* 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;
/* β¦ */
Raha ny fanakanana "conservative" indray, dia readp()
ΠΈ writep()
manidy inodes mandra-pahavitan'izy ireo na mahazo valiny (izany hoe antso wakeup
). plock()
ΠΈ prele()
miasa tsotra: mampiasa andian-antso hafa sleep
ΠΈ wakeup
avelao izahay hamoha izay dingana mila ny hidin-trano vao navoakanay:
/*
* 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);
}
}
Tsy azoko ny antony readp()
tsy miteraka prele(ip)
alohan'ny fiantsoana wakeup(ip+1)
. Ny zavatra voalohany writep()
miantso ao amin'ny tadivavarana, ity plock(ip)
, izay miteraka fahatapahana raha readp()
mbola tsy nanala ny sakanany, noho izany dia tsy maintsy miasa tsara ny kaody. Raha mijery ianao wakeup()
, dia lasa mazava fa manamarika ny dingana fatoriana ho vonona ho amin'ny famonoana, ka amin'ny ho avy sched()
tena namoaka azy. Noho izany readp()
antony wakeup()
, mamoha, mametraka IREAD
ary miantso sleep(ip+2)
- izany rehetra izany teo aloha writep()
mamerina ny tsingerina.
Izany dia mameno ny famaritana ny fantsona amin'ny andiany fahenina. Kaody tsotra, misy fiantraikany lavitra.
Xv6, kernel tsotra mitovy amin'ny Unix
Mba hamorona nucleus
Ny fehezan-dalΓ na dia misy fampiharana mazava sy feno fisainana 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()
mametraka ny toetry ny sisa rehetra amin'ny fampiharana, izay ahitana ny asa piperead()
, pipewrite()
ΠΈ pipeclose()
. Ny tena antso rafitra sys_pipe
dia wrapper ampiharina ao
Linux 0.01
Azonao atao ny mahita ny kaody loharano ho an'ny Linux 0.01. Hanampy ny fianarana ny fampiharana ny fantsona ao aminy fs
/pipe.c
. Eto, misy inode ampiasaina hanehoana ny fantsona, fa ny fantsona mihitsy dia nosoratana tamin'ny C maoderina. Raha toa ianao ka nijirika ny lalanao tamin'ny alΓ lan'ny kaody andiany fahenina, dia tsy hanana olana ianao eto. Toy izao ny endri-javatra 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;
}
Na dia tsy mijery ny famaritana struct aza dia azonao fantarina ny fomba ampiasana ny fanisan'ny inode hanamarina raha misy asa fanoratana SIGPIPE
. Ankoatra ny asa byte-by-byte, ity fiasa ity dia mora ampitahaina amin'ireo hevitra etsy ambony. Na ny lojika aza sleep_on
/wake_up
toa tsy dia vahiny loatra.
Kernel Linux maoderina, FreeBSD, NetBSD, OpenBSD
Nandeha haingana ireo voany maoderina sasany aho. Tsy misy amin'izy ireo efa manana fampiharana mifototra amin'ny disk (tsy mahagaga). Linux dia manana ny fampiharana azy manokana. Ary na dia misy fampiharana mifototra amin'ny kaody nosoratan'i John Dyson aza ireo kernel BSD maoderina telo, dia nanjary tsy nitovy loatra izy ireo nandritra ny taona maro.
Mamaky fs
/pipe.c
(amin'ny Linux) na sys
/kern
/sys_pipe.c
(amin'ny *BSD), mila fanoloran-tena marina izany. Zava-dehibe amin'ny kaody ankehitriny ny fampisehoana sy fanohanana ireo endri-javatra toy ny vector sy asynchronous I/O. Ary ny antsipirian'ny fizarana fahatsiarovana, hidin-trano, ary ny fanamafisana kernel dia samy hafa be. Tsy izany no ilain'ny oniversite amin'ny fampianarana fampidirana momba ny rafitra fiasana.
Na izany na tsy izany, nahaliana ahy ny nanangona lamina tranainy vitsivitsy (ohatra, famoronana SIGPIPE
ary miverina EPIPE
rehefa manoratra amin'ny fantsona mihidy) amin'ireo voany maoderina rehetra ireo, tena samy hafa. Mety tsy hahita solosaina PDP-11 mivantana mihitsy aho, saingy mbola betsaka ny ianarana avy amin'ny fehezan-dalΓ na nosoratana taona vitsivitsy talohan'ny nahaterahako.
Nosoratan'i Divi Kapoor tamin'ny 2011, ilay lahatsoratra "
Source: www.habr.com