
Hōʻike kēia ʻatikala i ka hoʻokō ʻana i nā pipeline ma ka kernel Unix. Ua hauʻoli wau i kahi ʻatikala hou i kapa ʻia ʻo ""ua huli mai ole e pili ana i ka hale o loko. Ua lilo au i mea hoihoi a ʻeli au i nā kumu kahiko e ʻike ai i ka pane.
He aha kā mākou e kamaʻilio nei?
ʻO Pipelines, "ʻo ia paha ka mea nui loa ma Unix," he ʻano wehewehe o ka manaʻo kumu Unix o ka hoʻopili ʻana i nā polokalamu liʻiliʻi, a me kahi hōʻailona maʻamau ma ka laina kauoha:
$ echo hello | wc -c
6
Aia kēia hana i ke kelepona ʻōnaehana i hāʻawi ʻia i ka kernel pipe, i wehewehe ʻia ma nā ʻaoʻao palapala и :
Hāʻawi nā Pipeline i kahi ala unidirectional no ke kamaʻilio interprocess. Loaʻa i ka pipeline kahi hoʻokomo (kākau hope) a me kahi puka (heluhelu hope). Hiki ke heluhelu ʻia nā ʻikepili i kākau ʻia i ka hoʻokomo o ka pipeline ma ka puka.
Hana ʻia ka pipeline me ke kelepona
pipe(2), ka mea e hoʻihoʻi i ʻelua faila wehewehe: ʻo kekahi e pili ana i ka hoʻokomo o ka pipeline, ʻo ka lua i ka puka.
Hōʻike ka trace output mai ke kauoha i luna aʻe i ka hana ʻana o ka pipeline a me ke kahe o ka ʻikepili ma o ia mea mai kekahi kaʻina i kekahi:
$ 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
Kahea ka hana makua pipe()e kiʻi i nā mea wehewehe faila i kau ʻia. Hoʻokahi kaʻina hana keiki e kākau i ka lima hoʻokahi, a ʻo kekahi kaʻina e heluhelu i ka ʻikepili like mai kahi lima ʻē aʻe. Hoʻohana ka shell i ka dup2 e "hōʻano hou" i nā mea wehewehe 3 a me 4 e hoʻokūkū i stdin a me stdout.
Me ka ʻole o nā paipu, pono ka pūpū e kākau i ka hopena o kekahi kaʻina hana i kahi faila a hāʻawi i kekahi kaʻina hana e heluhelu ai i ka ʻikepili mai ka faila. ʻO ka hopena, e hoʻopau mākou i nā kumuwaiwai hou aʻe a me nā wahi disk. Eia nō naʻe, maikaʻi nā pipeline ʻaʻole wale no ka mea e ʻae iā ʻoe e pale i ka hoʻohana ʻana i nā faila manawa:
Inā e hoʻāʻo ana kahi kaʻina e heluhelu mai kahi pipeline ʻole a laila
read(2)e ālai a hiki i ka loaʻa ʻana o ka ʻikepili. Inā ho'āʻo kahi hana e kākau i kahi paipu piha, a lailawrite(2)e ālai ʻia a lawa ka ʻikepili mai ka pipeline e hana i ke kākau.
E like me ke koi POSIX, he waiwai nui kēia: kākau i ka pipeline a hiki i PIPE_BUF ʻO nā bytes (ma ka liʻiliʻi loa he 512) pono ke ʻano atomic i hiki i nā kaʻina hana ke kamaʻilio me kekahi i kekahi ma o ka pipeline ma ke ʻano i hiki ʻole ai i nā faila maʻamau (ʻaʻole hāʻawi i kēlā mau hōʻoia).
I ka hoʻohana ʻana i kahi faila maʻamau, hiki i ke kaʻina hana ke kākau i nā mea i hoʻopuka ʻia iā ia a hāʻawi iā ia i kahi kaʻina hana ʻē aʻe. A i ʻole hiki ke hana i nā kaʻina hana ma kahi ʻano like loa, me ka hoʻohana ʻana i kahi mīkini hōʻailona waho (e like me ka semaphore) e hoʻomaopopo i kekahi i ka wā i pau ai kahi kākau a heluhelu paha. Hoʻopakele nā Conveyors iā mākou mai kēia pilikia āpau.
He aha kā mākou e ʻimi nei?
E wehewehe au iā ia ma nā ʻōlelo maʻalahi i maʻalahi iā ʻoe ke noʻonoʻo pehea e hana ai kahi conveyor. Pono ʻoe e hoʻokaʻawale i kahi buffer a me kekahi mokuʻāina i ka hoʻomanaʻo. Pono ʻoe i nā hana e hoʻohui a wehe i ka ʻikepili mai ka buffer. Pono ʻoe i kahi ala e kāhea ai i nā hana i ka wā heluhelu a kākau i nā hana ma nā faila wehewehe. A pono ʻoe i nā laka e hoʻokō i ke ʻano kūikawā i wehewehe ʻia ma luna.
I kēia manawa ua mākaukau mākou e nīnau i ke kumu kumu kernel ma lalo o ke kukui kukui e hōʻoia a hōʻole i kā mākou kumu hoʻohālike noʻonoʻo. Akā e mākaukau mau no ka mea i manaʻo ʻole ʻia.
Ma hea mākou e ʻimi nei?
ʻAʻole maopopo iaʻu i hea kaʻu kope o ka puke kaulana ""me Unix 6 source code, akā mahalo iā hiki iā ʻoe ke ʻimi ma ka pūnaewele ma ʻoiai nā mana kahiko o Unix.
ʻO ka hele ʻana i loko o ka waihona TUHS e like me ke kipa ʻana i kahi hale hōʻikeʻike. Hiki iā mākou ke nānā i kā mākou moʻolelo like, a mahalo wau i nā makahiki he nui o ka hoʻoikaika ʻana e hoʻihoʻi i kēia mau mea āpau mai nā lipine kahiko a me nā paʻi. A ʻike maopopo wau i kēlā mau ʻāpana e nalowale nei.
Ma muli o ko mākou makemake e pili ana i ka mōʻaukala kahiko o nā conveyors, hiki iā mākou ke nānā i nā kernels hou no ka hoʻohālikelike.
Ma ke ala, pipe ʻo ia ka helu kelepona ʻōnaehana 42 ma ka pākaukau sysent[]. ʻAkahi?
Kuʻuna Unix kernels (1970–1974)
ʻAʻole i loaʻa iaʻu kahi meheu pipe(2) ʻaʻole i loko (Ianuali 1970), aole hoi ma (Novema 1971), ʻaʻole hoʻi i ka helu kumu ʻole (Iune 1972).
Wahi a TUHS (Feberuari 1973) i lilo i ka mana mua me nā conveyors:
ʻO Unix 1973rd Edition ka mana hope loa me kahi kernel i kākau ʻia ma ka ʻōlelo hui, akā ʻo ka mana mua pū me nā pipelines. I ka makahiki XNUMX, ua hoʻokō ʻia ka hana e hoʻomaikaʻi i ke kolu o ka paʻi, ua kākau hou ʻia ka kernel ma C, a no laila ua ʻike ʻia ka paʻi ʻehā o Unix.
Ua loaʻa i kahi mea heluhelu kahi scan o kahi palapala i manaʻo ai ʻo Doug McIlroy i ka manaʻo o "hoʻohui ʻana i nā polokalamu e like me ka hose māla."

Ma ka puke a Brian Kernighan", ma ka moʻolelo o ka puka ʻana o nā conveyors, ua ʻōlelo ʻia kēia palapala: "... ua kau ʻia ma ka paia ma koʻu keʻena ma Bell Labs no 30 mau makahiki." Eia , a me kekahi moʻolelo mai :
I ka puka ʻana mai o Unix, ʻo koʻu hoihoi i nā coroutine ua alakaʻi iaʻu e nīnau i ka mea kākau o OS, ʻo Ken Thompson, e ʻae i ka ʻikepili i kākau ʻia i kahi kaʻina e hele ʻaʻole wale i ka hāmeʻa, akā e hoʻopuka pū i kahi kaʻina hana ʻē aʻe. Ua hoʻoholo ʻo Ken e hiki. Eia nō naʻe, ma ke ʻano he minimalist, makemake ʻo ia i kēlā me kēia hana ʻōnaehana e hana i kahi kuleana koʻikoʻi. ʻO ke kākau pololei ʻana ma waena o nā kaʻina hana he pono nui ma mua o ke kākau ʻana i kahi faila waena? ʻO ia wale nō kaʻu i hana ai i kahi manaʻo kikoʻī me ka inoa hopu "pipeline" a me ka wehewehe ʻana i ka syntax no ka launa pū ʻana ma waena o nā kaʻina hana i ʻōlelo hope ai ʻo Ken: "E hana wau!"
A hana. I kekahi ahiahi pōʻino, ua hoʻololi ʻo Ken i ka kernel a me ka shell, hoʻoponopono i nā papahana maʻamau e hoʻohālikelike i ke ʻano o kā lākou ʻae ʻana i ke komo ʻana (hiki ke hele mai mai kahi pipeline), a hoʻololi pū i nā inoa faila. I ka lā aʻe, ua hoʻomaka e hoʻohana nui ʻia nā pipeline i nā noi. I ka pau ʻana o ka pule, ua hoʻohana nā mea kākau ʻōlelo iā lākou e hoʻouna i nā palapala mai nā mea hana huaʻōlelo i ka mea paʻi. Ma hope iki, ua hoʻololi ʻo Ken i ka API kumu a me ka syntax no ka hoʻopili ʻana i ka hoʻohana ʻana i nā pipeline me nā hui hoʻomaʻemaʻe, i hoʻohana ʻia mai ia manawa.
ʻO ka mea pōʻino, ua nalowale ke kumu kumu no ka paʻi ʻekolu o Unix kernel. A ʻoiai ua loaʻa iā mākou ke kumu kumu kernel i kākau ʻia ma C , i hoʻokuʻu ʻia ma Nowemapa 1973, akā ua puka mai i kekahi mau mahina ma mua o ka hoʻokuʻu ʻia ʻana a ʻaʻole i loaʻa nā hoʻokō pipeline. He mea hilahila ke nalowale ke kumu kumu no kēia hana Unix kaao, a mau loa paha.
Loaʻa iā mākou nā palapala kikokikona no pipe(2) mai nā hoʻokuʻu ʻelua, no laila hiki iā ʻoe ke hoʻomaka ma ka ʻimi ʻana i ka palapala (no kekahi mau huaʻōlelo, i kaha ʻia "manual", he string o nā huaʻōlelo ^H, a ukali ʻia e kahi kaha lalo!). ʻO kēia proto-pipe(2) ua kākau ʻia ma ka ʻōlelo hui a hoʻihoʻi i hoʻokahi wale nō faila wehewehe, akā ua hāʻawi mua i ka hana kumu i manaʻo ʻia:
Kāhea pūnaewele paipu hoʻokumu i kahi mīkini hoʻokomo / puka i kapa ʻia he pipeline. Hiki ke hoʻohana ʻia ka mea wehewehe waihona i hoʻihoʻi ʻia no nā hana heluhelu a kākau. Ke kākau ʻia kekahi mea i ka pipeline, a hiki i 504 bytes o ka ʻikepili i hoʻopaʻa ʻia, a laila hoʻokuʻu ʻia ke kaʻina hana kākau. I ka heluhelu ʻana mai ka pipeline, lawe ʻia ka ʻikepili buffered.
I ka makahiki aʻe, ua kākau hou ʻia ka kernel ma C, a loaʻa i kona ʻano hou me ka prototype "pipe(fildes)»:
Kāhea pūnaewele paipu hoʻokumu i kahi mīkini hoʻokomo / puka i kapa ʻia he pipeline. Hiki ke hoʻohana ʻia nā mea wehewehe faila i ka heluhelu a kākau ʻana. Ke kākau ʻia kekahi mea i ka pipeline, hoʻohana ʻia ka pahu i hoʻihoʻi ʻia ma r1 (resp. fildes [1]), i hoʻopaʻa ʻia i 4096 bytes o ka ʻikepili, a laila hoʻokuʻu ʻia ke kaʻina hana kākau. I ka heluhelu ʻana mai ka pipeline, ua hoʻihoʻi ka lima i r0 (resp. fildes[0]) e lawe i ka ʻikepili.
Ua manaʻo ʻia i ka manawa e wehewehe ʻia ai kahi pipeline, ʻelua (a ʻoi aku paha) kaʻina hana kamaʻilio (i hana ʻia e nā kelepona ma hope i ke'ō) e hoʻoili i ka ʻikepili mai ka pipeline me ka hoʻohana ʻana i nā kelepona heluhelu и kakau.
Loaʻa i ka pūpū kahi syntax no ka wehewehe ʻana i kahi laina laina o nā kaʻina i hoʻopili ʻia e kahi pipeline.
Kāhea e heluhelu mai kahi paipu ʻole (ʻaʻohe ʻikepili i hoʻopaʻa ʻia) hoʻokahi wale nō hopena (ua pani ʻia nā mea wehewehe faila kākau) e hoʻihoʻi i ka "hopena o ka faila". ʻAʻole mālama ʻia nā kelepona e kākau ma kahi kūlana like.
mua loa pili (Iune 1974), akā ua aneane like ia me ka mea i puka mai ma ka hoʻokuʻu aʻe. Ua hoʻohui ʻia nā manaʻo, no laila hiki iā ʻoe ke hoʻokuʻu i ka paʻi ʻelima.
Puka ʻeono o Unix (1975)
E hoʻomaka kākou e heluhelu i ka code source Unix (Mei 1975). Mahalo nui iā Lions ʻoi aku ka maʻalahi o ka loaʻa ʻana ma mua o nā kumu o nā mana mua:
No nā makahiki he nui ka puke Lions ʻo ia wale nō ka palapala ma ka Unix kernel i loaʻa ma waho o Bell Labs. ʻOiai ua ʻae ka laikini paʻi ʻeono i nā kumu e hoʻohana i kāna code kumu, ua kāpae ka laikini paʻi ʻehiku i kēia hiki, no laila ua puʻunaue ʻia ka puke ma ke ʻano o nā kope kope kope ʻole.
I kēia lā hiki iā ʻoe ke kūʻai i kahi paʻi hou o ka puke, ʻo ka uhi e hōʻike ana i nā haumāna ma kahi mīkini kope. A mahalo iā Warren Toomey (nāna i hoʻomaka i ka papahana TUHS) hiki iā ʻoe ke hoʻoiho . Makemake wau e hāʻawi iā ʻoe i ka manaʻo o ka nui o ka hoʻoikaika ʻana i ka hana ʻana i ka faila:
ʻOi aku ma mua o 15 mau makahiki i hala, ua paʻi au i kahi kope o ka code kumu i hāʻawi ʻia Lions, no ka mea ʻaʻole wau i makemake i ka maikaʻi o kaʻu kope mai kahi helu ʻike ʻole o nā kope ʻē aʻe. ʻAʻole i loaʻa ʻo TUHS a ʻaʻole hiki iaʻu ke komo i nā kumu kahiko. Akā i ka makahiki 1988, ua loaʻa iaʻu kahi lipine 9-track kahiko i loaʻa kahi waihona mai kahi kamepiula PDP11. He mea paʻakikī ke haʻi inā e hana ana, akā aia kahi lāʻau /usr/src/ i hoʻopaʻa ʻia i ka hapa nui o nā faila me ka makahiki 1979, ʻoiai he mea kahiko. ʻO ia ka hiku o ka paʻi ʻana a i ʻole kāna huaʻōlelo PWB, e like me kaʻu i manaʻoʻiʻo ai.
Lawe au i ka ʻike ma ke ʻano he kumu a hoʻoponopono lima i nā kumu i ka paʻi ʻeono. Ua mau kekahi o nā code, akā pono e hoʻoponopono iki ʻia kekahi, e hoʻololi i ka hōʻailona += hou i ka =+ kahiko. Ua holoi wale ʻia kekahi mau mea, a pono e kākau hou ʻia kekahi, ʻaʻole naʻe i ka nui.
A i kēia lā hiki iā mākou ke heluhelu ma ka pūnaewele ma TUHS ke kumu kumu o ka paʻi ʻeono mai .
Ma ke ala, i ka nānā mua ʻana, ʻo ka hiʻohiʻona nui o ka C-code ma mua o ka manawa o Kernighan lāua ʻo Ritchie pōkole. ʻAʻole hiki iaʻu ke hoʻokomo i nā ʻāpana code me ka ʻole o ka hoʻoponopono nui ʻana e kūpono i kahi wahi hōʻike haiki ma kaʻu pūnaewele.
I ka hoʻomaka aia kahi ʻōlelo wehewehe (a ʻae, aia kekahi ):
/*
* 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
ʻAʻole i loli ka nui buffer mai ka paʻi ʻehā. Eia naʻe ke ʻike nei mākou, me ka ʻole o nā palapala lehulehu, ua hoʻohana nā pipeline i nā faila i mālama ʻia!
No nā faila LARG, pili lākou , i hoʻohana ʻia e ka "algorithm addressing nui" e hana e kākoʻo i nā ʻōnaehana faila nui. No ka mea, ʻoi aku ka maikaʻi o ka hoʻohana ʻole ʻana iā Ken, e hauʻoli wau e lawe i kāna ʻōlelo.
Eia ke kelepona ʻōnaehana maoli 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;
}
Hōʻike maopopo ka manaʻo i nā mea e hana nei. Akā ʻaʻole maʻalahi ka hoʻomaopopo ʻana i ke code, ma muli o ke ala "»a me na kakau inoa R0 и R1 Ua hala nā ʻāpana kelepona a me nā waiwai hoʻihoʻi.
E hoao kakou me kau ma ka diski , a me ke kokua - e kau i ʻelua ma ka hoʻomanaʻo . Inā holo maikaʻi nā mea a pau, e hoʻonoho mākou i nā hae e ʻike i kēia mau faila ma ke ʻano he ʻelua mau kihi o ka pipeline, kuhikuhi iā lākou i ka inode hoʻokahi (nona ka helu kuhikuhi e hoʻonohonoho ʻia i 2), a e kaha i ka inode i hoʻololi ʻia a hoʻohana ʻia. E hoʻolohe i nā noi i i nā ala hewa e hōʻemi i ka helu kuhikuhi ma ka inode hou.
pipe() pono ma R0 и R1 e hoʻihoʻi i nā helu wehewehe waihona no ka heluhelu a me ke kākau ʻana. falloc() hoʻihoʻi i kahi kuhikuhi i ka hoʻolālā faila, akā "hoʻi" ma o u.u_ar0[R0] a me kahi faila wehewehe. ʻO ia hoʻi, mālama ke code i loko r waihona wehewehe no ka heluhelu ʻana a hāʻawi i kahi wehewehe faila no ke kākau pololei ʻana mai u.u_ar0[R0] mahope o ka lua o ke kahea ana falloc().
Ho'āka FPIPE, ka mea a mākou i hoʻonohonoho ai i ka hana ʻana i ka pipeline, kaohi i ka ʻano o ka hana ke kāhea ʻana i nā hana maʻamau I/O:
/*
* 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);
}
/* … */
}
A laila ka hana readp() в pipe.c heluhelu 'ikepili mai ka paipu. Akā ʻoi aku ka maikaʻi o ka ʻimi ʻana i ka hoʻokō e hoʻomaka ana writep(). Eia hou, ua lilo ke code i mea paʻakikī ma muli o nā kuʻina o ka hoʻopaʻapaʻa ʻana, akā hiki ke waiho ʻia kekahi mau kikoʻī.
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;
}
Makemake mākou e kākau i nā bytes i ka hoʻokomo pipeline u.u_count. Pono mua mākou e laka i ka inode (e nānā i lalo plock/prele).
A laila, nānā mākou i ka helu kuhikuhi inode. I ka wā e wehe ʻia nā ʻaoʻao ʻelua o ka pipeline, pono e like ka counter me 2. Paʻa mākou i hoʻokahi loulou (mai rp->f_inode), no laila inā ʻoi aku ka liʻiliʻi o ka counter ma mua o 2, ʻo ia ke ʻano o ke kaʻina heluhelu ua pani ʻia kona hopena o ka pipeline. I nā huaʻōlelo ʻē aʻe, ke hoʻāʻo nei mākou e kākau i kahi pipeline i pani ʻia, a he hewa kēia. Kakahi helu kuhi hewa EPIPE a me ka hoailona SIGPIPE ua ʻike ʻia ma ka paʻi ʻeono o Unix.
Akā inā hāmama ka conveyor, piha paha. I kēia hihia, hoʻokuʻu mākou i ka laka a hele i ka hiamoe me ka manaʻolana e heluhelu ʻia kahi kaʻina hana hou mai ka pipeline a hoʻokuʻu i kahi ākea i loko. Ma hope o ke ala ʻana, hoʻi mākou i ka hoʻomaka, kau hou i ka laka a hoʻomaka i kahi pōʻai hoʻopaʻa leo hou.
Inā lawa ka hakahaka o ka pipeline, a laila kākau mākou i ka ʻikepili iā ia me ka hoʻohana ʻana ... Parameter i_size1 ma ka inode (inā nele ka pipeline hiki ke like me 0) hōʻike i ka hopena o ka ʻikepili i loaʻa iā ia. Inā lawa ka leo hoʻopaʻa, hiki iā mākou ke hoʻopiha i ka pipeline mai i_size1 i luna PIPESIZ. A laila hoʻokuʻu mākou i ka laka a ho'āʻo e ala i kekahi kaʻina hana e kali nei e heluhelu mai ka pipeline. Hoʻi mākou i ka hoʻomaka e ʻike inā hiki iā mākou ke kākau i nā bytes e like me kā mākou makemake. Inā hāʻule, a laila hoʻomaka mākou i kahi pōʻai hoʻopaʻa leo hou.
ʻO ka mea maʻamau ka palena i_mode hoʻohana ʻia ka inode e mālama i nā ʻae r, w и x. Akā i ka hihia o nā pipeline, hōʻailona mākou e kali ana kekahi kaʻina hana no kahi kākau a heluhelu paha me ka hoʻohana ʻana i nā bits IREAD и IWRITE pakahi. Hoʻonohonoho ka hana i ka hae a me nā kelepona sleep(), a ua manaʻo ʻia e hana ʻia kekahi hana ʻē aʻe i ka wā e hiki mai ana wakeup().
Hiki ke kilokilo maoli i loko sleep() и wakeup(). Hoʻokō ʻia lākou ma , ke kumu o ka mea kaulana "ʻAʻole i manaʻo ʻia ʻoe e hoʻomaopopo i kēia" ʻōlelo. ʻO ka mea pōmaikaʻi, ʻaʻole pono mākou e hoʻomaopopo i ke code, e nānā wale i kekahi mau ʻōlelo:
/*
* 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) /* … */
ʻO ke kaʻina hana sleep() no kekahi alahele, hiki ke hoala ia mai e kekahi kaʻina hana, e kumu wakeup() no ke ala like. writep() и readp() hoʻonohonoho i kā lākou mau hana ma o ia mau kelepona paʻa. e hoʻomaopopo i kēlā pipe.c hāʻawi mua i nā manawa a pau PPIPE ke kaheaia sleep(), pela iho la sleep() hiki ke hookiia e ka hoailona.
I kēia manawa ua loaʻa iā mākou nā mea āpau e hoʻomaopopo i ka hana 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);
}
Hiki iā ʻoe ke maʻalahi ka heluhelu ʻana i kēia hana mai lalo a luna. Hoʻohana mau ʻia ka lālā "heluhelu a hoʻihoʻi" inā loaʻa kekahi ʻikepili i ka pipeline. I kēia hihia, hoʻohana mākou heluhelu mākou e like me ka nui o ka ʻikepili e hoʻomaka ana mai ka mea i kēia manawa f_offset heluhelu, a laila hoʻololi i ka waiwai o ka offset pili.
Ma nā heluhelu aʻe, e nele ka pipeline inā ua hiki i ka offset heluhelu i_size1 ma ka inode. Hoʻihoʻi mākou i ke kūlana i ka 0 a hoʻāʻo e ala i kahi kaʻina hana e makemake e kākau i ka pipeline. Ua ʻike mākou i ka piha ʻana o ka conveyor, writep() e hiamoe ana ma ip+1. A i kēia manawa ua nele ka pipeline, hiki iā mākou ke hoʻāla iā ia e hoʻomau i kāna pōʻai kākau.
Inā ʻaʻohe āu mea e heluhelu ai, a laila readp() hiki ke kau i ka hae IREAD a hiamoe ma ip+2. ʻIke mākou i ka mea e hoʻāla iā ia writep(), ke kākau ʻo ia i kekahi mau ʻikepili i ka pipeline.
Manaʻo ma e kōkua iā ʻoe e hoʻomaopopo ma mua o ka hele ʻana i nā ʻāpana ma o "u"Hiki iā mākou ke mālama iā lākou e like me nā hana I/O maʻamau e lawe i kahi faila, kahi kūlana, kahi pale i ka hoʻomanaʻo, a helu i ka helu o nā bytes e heluhelu a kākau paha.
/*
* 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;
/* … */
No ka "conservative" blocking, a laila readp() и writep() e ālai i ka inode a hoʻopau i kā lākou hana a loaʻa paha kahi hopena (ʻo ia hoʻi, kāhea wakeup). plock() и prele() hana maʻalahi: me ka hoʻohana ʻana i nā kelepona ʻokoʻa sleep и wakeup e ʻae iā mākou e ala i kekahi kaʻina hana e pono ai ka laka a mākou i hoʻokuʻu ai:
/*
* 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);
}
}
I ka wā mua ʻaʻole hiki iaʻu ke hoʻomaopopo i ke kumu readp() ʻaʻole kumu prele(ip) mamua o ke kahea ana wakeup(ip+1). ʻO ka mea mua writep() kumu i loko o kona pōʻaiapuni, kēia plock(ip), ka mea e alakai i ka deadlock ina readp() ʻaʻole i wehe i kaʻu poloka i kēia manawa, no laila pono e hana pololei ke code. Inā ʻoe e nānā wakeup(), a laila e maopopo ai he mākaʻikaʻi wale nō ia i ke kaʻina hana hiamoe i mākaukau e hoʻokō, no laila i ka wā e hiki mai ana. sched() hoʻolana maoli. No laila readp() mau kumu wakeup(), wehe i ka laka, hoonoho IREAD a kelepona sleep(ip+2)- kēia mau mea ma mua writep() hoʻomaka hou i ka pōʻaiapuni.
Hoʻopau kēia i ka wehewehe ʻana o nā conveyors i ka paʻi ʻeono. Code maʻalahi, hopena lōʻihi.
(Ianuali 1979) he hoʻokuʻu nui hou (ʻehā makahiki ma hope) i hoʻolauna i nā noi hou a me nā hiʻohiʻona kernel. Ua hoʻololi nui ʻia hoʻi e pili ana i ka hoʻohana ʻana i ke ʻano hoʻoheheʻe ʻana, nā uniona a me nā kuhikuhi kikoʻī i nā hale. Eia naʻe ʻaʻole i loli. Hiki iā mākou ke hoʻokuʻu i kēia paʻi.
Xv6, he kernel like me Unix maʻalahi
No ka hana ʻana i ka kernel i hoʻoikaika ʻia e ka paʻi ʻeono o Unix, akā ua kākau ʻia i ka C hou e holo ma nā kaʻina hana x86. He maʻalahi ka heluhelu a hoʻomaopopo ʻia ke code. Eia kekahi, ʻaʻole like me nā kumu Unix me TUHS, hiki iā ʻoe ke hōʻuluʻulu, hoʻololi, a holo ma kahi mea ʻē aʻe ma kahi PDP 11/70. No laila, hoʻohana nui ʻia kēia kernel i nā kulanui ma ke ʻano he mea hoʻonaʻauao ma nā ʻōnaehana hana. Nā kumu .
Loaʻa i ke code kahi hoʻokō a maopopo a noʻonoʻo , kākoʻo ʻia e kahi paʻa i ka hoʻomanaʻo ma kahi o kahi inode ma ka disk. Eia wau e hāʻawi wale i ka wehewehe ʻana o "pipeline structural" a me ka hana 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() hoʻonohonoho i ke kūlana o ke koena o ka hoʻokō, e komo pū ana nā hana piperead(), pipewrite() и pipeclose(). Kāhea ʻōnaehana maoli sys_pipe he wīwī i hoʻokomo ʻia i loko . Manaʻo wau e heluhelu i kāna code holoʻokoʻa. Aia ka paʻakikī ma ke kiʻekiʻe o ke code kumu o ka paʻi ʻeono, akā ʻoi aku ka maʻalahi a ʻoi aku ka leʻaleʻa o ka heluhelu.
Linux 0.01
Hiki ke loaʻa ke code kumu Linux 0.01. He mea aʻoaʻo e aʻo i ka hoʻokō ʻana i nā paipu i kāna fs/pipe.c. Hoʻohana kēia i ka inode e hōʻike i ka pipeline, akā ua kākau ʻia ka pipeline ponoʻī i ka C hou. ʻO kēia ke ʻano o ka hana 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;
}
Me ka nānā ʻole ʻana i ka wehewehe ʻana, hiki iā ʻoe ke noʻonoʻo pehea e hoʻohana ʻia ai ka helu kuhikuhi inode e nānā i ka hopena o kahi hana kākau. SIGPIPE. Ma waho aʻe o ka hana byte-by-byte, maʻalahi kēia hana e hoʻohālikelike me nā manaʻo i hōʻike ʻia ma luna. ʻOiai noʻonoʻo sleep_on/wake_up ʻaʻole ʻano malihini.
Nā kernel Linux hou, FreeBSD, NetBSD, OpenBSD
Holo wikiwiki au i kekahi mau kernel hou. ʻAʻohe o lākou i hoʻokō i ka disk (ʻaʻole kahaha). Loaʻa iā Linux kona hoʻokō ponoʻī. ʻOiai ʻo nā kernels BSD hou ʻekolu i loaʻa nā hoʻokō e pili ana i ke code i kākau ʻia e John Dyson, i nā makahiki he ʻokoʻa loa lākou mai kekahi i kekahi.
E heluhelu fs/pipe.c (ma Linux) a i ʻole sys/kern/sys_pipe.c (ma *BSD), pono ia i ka hoʻolaʻa maoli. ʻO ke code o kēia lā e pili ana i ka hana a me ke kākoʻo no nā hiʻohiʻona e like me vector a me asynchronous I/O. A ʻokoʻa loa nā kikoʻī o ka hoʻokaʻawale hoʻomanaʻo, nā laka a me ka hoʻonohonoho kernel. ʻAʻole kēia ka mea e pono ai nā koleke no kahi papa ʻōnaehana hoʻomaka.
Eia nō naʻe, makemake wau i ka ʻeli ʻana i kekahi mau hiʻohiʻona kahiko (e like me ka hana ʻana SIGPIPE a hoi mai EPIPE i ka wā e kākau ai i kahi paipu paʻa) i kēia mau ʻano ʻokoʻa o kēia manawa. ʻAʻole paha au e ʻike i kahi kamepiula PDP-11 i ke ola maoli, akā nui nā mea e aʻo ai mai nā code i kākau ʻia i nā makahiki ma mua o koʻu hānau ʻana.
He ʻatikala i kākau ʻia e Divi Kapoor ma 2011:" hāʻawi i kahi ʻike o ka hana ʻana o nā pipelines (mau) ma Linux. A e hōʻike ana i kahi hoʻohālike pipeline o ka launa pū ʻana, nona ka mana ma mua o nā faila manawa; a e hōʻike pū ana i ka lōʻihi o ka loaʻa ʻana o nā pipeline mai ka "loka conservative loa" o ka paʻi ʻeono o Unix kernel.
Source: www.habr.com
