Artikel ieu ngajelaskeun palaksanaan pipelines dina kernel Unix. Kuring rada kuciwa yén tulisan anyar anu judulna "
Naon urang ngobrol ngeunaan?
Pipelines, "panginten penemuan anu paling penting dina Unix," mangrupikeun ciri anu ngahartikeun filosofi Unix anu ngahubungkeun program-program leutik babarengan, ogé tanda anu biasa dina garis paréntah:
$ echo hello | wc -c
6
Fungsionalitas ieu gumantung kana panggero sistem anu disayogikeun ku kernel pipe
, anu dijelaskeun dina kaca dokuméntasi
Pipelines nyadiakeun saluran unidirectional pikeun komunikasi interprocess. Pipa boga input (tulis tungtung) jeung kaluaran (baca tungtung). Data anu ditulis kana input pipa tiasa dibaca dina kaluaran.
Pipa didamel nganggo telepon
pipe(2)
, anu mulihkeun dua deskriptor file: hiji ngarujuk kana input pipa, anu kadua pikeun kaluaran.
Kaluaran renik tina paréntah di luhur nunjukkeun nyiptakeun pipa sareng aliran data ngaliwatan éta tina hiji prosés ka anu sanés:
$ 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
Prosés indungna nelepon pipe()
pikeun meunangkeun deskriptor file dipasang. Hiji prosés anak nulis ka hiji cecekelan, sarta prosés séjén maca data anu sarua ti cecekelan sejen. Cangkang ngagunakeun dup2 pikeun "ganti ngaran" deskriptor 3 jeung 4 pikeun cocog stdin na stdout.
Tanpa pipa, cangkang kedah nyerat kaluaran hiji prosés kana file sareng ngalirkeun kana prosés anu sanés pikeun maca data tina file. Hasilna, urang bakal miceunan langkung seueur sumber sareng rohangan disk. Nanging, saluran pipa saé sanés ngan ukur ngamungkinkeun anjeun ngahindarkeun panggunaan file samentawis:
Upami prosés nyobian maca tina pipa kosong teras
read(2)
bakal meungpeuk nepi ka data sadia. Upami prosés nyobian nyerat kana pipa pinuh, teraswrite(2)
bakal meungpeuk dugi cukup data geus dibaca tina pipa pikeun ngalakukeun nulis.
Kawas sarat POSIX, ieu mangrupa sipat penting: nulis kana pipa nepi ka PIPE_BUF
bait (sahenteuna 512) kudu atom ambéh prosés bisa komunikasi saling ngaliwatan pipa dina cara nu file biasa (nu teu nyadiakeun jaminan misalna) teu bisa.
Lamun maké file biasa, hiji prosés bisa nulis sakabéh kaluaran na kana eta sarta ngalirkeun kana ka prosés séjén. Atawa prosés bisa beroperasi dina modeu kacida paralel, ngagunakeun hiji mékanisme signalling éksternal (kawas semafor a) pikeun ngabejaan silih lamun nulis atawa maca geus réngsé. Conveyors nyalametkeun urang tina sagala repot ieu.
Naon anu urang pilari?
Kuring bakal ngajelaskeun eta dina istilah basajan ambéh leuwih gampang pikeun anjeun ngabayangkeun kumaha conveyor a tiasa jalan. Anjeun bakal kedah allocate a panyangga sarta sababaraha kaayaan dina mémori. Anjeun peryogi fungsi pikeun nambihan sareng mupus data tina panyangga. Anjeun peryogi sababaraha cara pikeun nelepon fungsi nalika operasi maca sareng nyerat dina deskriptor file. Sareng anjeun peryogi konci pikeun ngalaksanakeun kabiasaan khusus anu dijelaskeun di luhur.
Ayeuna kami siap ngainterogasi kode sumber kernel dina lampu lampu anu terang pikeun ngonfirmasi atanapi ngabantah modél mental kami anu samar. Tapi salawasna jadi disiapkeun keur kaduga.
Dimana urang pilari?
Abdi henteu terang dimana salinan buku anu kasohor "
Ngumbara ngaliwatan arsip TUHS téh kawas ngadatangan museum. Urang bisa nempo sajarah urang dibagikeun, sarta kuring hormat keur sababaraha taun usaha cageur kabeh bahan ieu bit ku bit tina kaset heubeul na prints. Sareng kuring sadar pisan kana fragmen anu masih leungit.
Saatos nyugemakeun rasa panasaran urang ngeunaan sajarah kuno conveyors, urang tiasa ningali kernels modern pikeun ngabandingkeun.
Ku jalan kitu, pipe
nyaeta sistem panggero angka 42 dina tabél sysent[]
. Kabeneran?
Kernel Unix Tradisional (1970–1974)
Abdi henteu mendakan jejak pipe(2)
henteu di
TUHS nyatakeun yén
Unix 1973rd Edition éta versi panungtungan kalawan kernel ditulis dina basa assembly, tapi oge versi munggaran kalayan pipelines. Salila taun XNUMX, gawé dilumangsungkeun pikeun ngaronjatkeun édisi katilu, kernel ieu ditulis ulang dina C, sahingga édisi kaopat Unix mucunghul.
Hiji pamaca mendakan scan dokumen dimana Doug McIlroy ngusulkeun ide "ngahubungkeun program sapertos selang kebon."
Dina buku Brian Kernighan
Nalika Unix kaluar, karesep kuring sareng coroutines nyababkeun kuring naroskeun ka panulis OS, Ken Thompson, pikeun ngantepkeun data anu diserat kana prosés henteu ngan ukur ka alat, tapi ogé kaluaran kana prosés anu sanés. Ken mutuskeun éta mungkin. Nanging, salaku minimalis, anjeunna hoyong unggal fungsi sistem maénkeun peran anu penting. Nyaeta nulis langsung antara prosés bener kaunggulan badag leuwih nulis kana file panengah? Ngan nalika kuring nyieun proposal husus kalawan ngaran catchy "pipeline" sarta pedaran sintaksis pikeun interaksi antara prosés nu Ken tungtungna exclaimed: "Kuring gé ngalakukeun eta!"
Jeung tuh. Hiji malem fateful, Ken robah kernel jeung cangkang, dibereskeun sababaraha program standar pikeun standarisasi kumaha aranjeunna nampi input (anu bisa datangna tina pipa a), sarta ogé robah ngaran file. Poé saterusna, pipelines mimiti dipaké pisan lega dina aplikasi. Nepi ka tungtun taun saminggu, sekretaris ngagunakeun éta pikeun ngirim dokumén ti pangolah kecap ka printer. A saeutik engké, Ken ngaganti API aslina tur sintaksis pikeun wrapping pamakéan pipelines kalawan Konvénsi cleaner, nu geus dipaké kantos saprak.
Hanjakal, kodeu sumber pikeun kernel Unix édisi katilu geus leungit. Sareng sanaos urang gaduh kode sumber kernel anu ditulis dina C
Simkuring gaduh dokuméntasi téks pikeun pipe(2)
ti duanana release, jadi Anjeun bisa ngamimitian ku néangan dokuméntasi pipe(2)
ditulis dina basa assembly sarta mulih ngan hiji deskriptor file, tapi geus nyadiakeun fungsionalitas inti ekspektasi:
Telepon sistem pipah nyiptakeun mékanisme input / output disebut pipa. Deskriptor file anu dipulangkeun tiasa dianggo pikeun operasi maca sareng nyerat. Nalika aya anu diserat dina saluran pipa, dugi ka 504 bait data disanggakeun, saatos éta prosés nyerat ditunda. Nalika maca tina pipa, data buffered dicandak.
Ku taun saterusna kernel geus ditulis ulang dina C, jeung pipe(fildes)
»:
Telepon sistem pipah nyiptakeun mékanisme input / output disebut pipa. Deskriptor file anu dipulangkeun tiasa dianggo dina operasi maca sareng nyerat. Lamun hal ieu ditulis kana pipa nu, cecekelan balik di r1 (resp. fildes [1]) dipaké, buffered ka 4096 bait data, nu satutasna prosés nulis ditunda. Nalika maca tina pipa, cecekelan balik ka r0 (resp. fildes [0]) nyokot data.
Hal ieu dianggap yén sakali pipa didefinisikeun, dua (atawa leuwih) prosés komunikasi (dijieun ku panggero saterusna pikeun garpuh) bakal nransper data tina pipa nganggo telepon maca и nulis.
Cangkang boga sintaksis pikeun nangtukeun susunan linier prosés disambungkeun ku pipa.
Nelepon maca tina hiji pipa kosong (ngandung euweuh data buffered) nu boga ngan hiji tungtung (sadayana descriptors file tulisan ditutup) balik "tungtung file". Telepon nulis dina kaayaan sarupa teu dipaliré.
Pangpangna
Édisi kagenep Unix (1975)
Hayu urang mimitian maca kode sumber Unix
Mangtaun-taun buku singa éta hiji-hijina dokumén dina kernel Unix sadia di luar Bell Labs. Sanajan lisénsi édisi kagenep diwenangkeun guru ngagunakeun kode sumber na, lisénsi édisi katujuh ngaluarkeun kamungkinan ieu, jadi buku ieu disebarkeun dina bentuk salinan ilegal typewritten.
Dinten anjeun tiasa mésér reprint tina buku, panutup nu nembongkeun siswa dina mesin salinan. Sareng hatur nuhun ka Warren Toomey (anu ngamimitian proyék TUHS) anjeun tiasa unduh
Langkung ti 15 sababaraha taun ka pengker, kuring ngetik salinan kode sumber anu dipasihkeun singa, sabab kuring henteu resep kualitas salinan kuring tina jumlah salinan anu teu dipikanyaho. TUHS henteu acan aya sareng kuring henteu ngagaduhan aksés kana sumber anu lami. Tapi dina 1988, kuring manggihan hiji pita heubeul 9-lagu nu ngandung cadangan ti komputer PDP11. Hésé pikeun ngabéjaan yén éta jalan, tapi aya tangkal /usr/src/ anu gembleng dimana seueur file anu dilabélan taun 1979, anu sanaos katingali kuno. Ieu édisi katujuh atawa turunan na PWB, sakumaha kuring yakin.
Kuring nyokot manggihan salaku dadasar sarta sacara manual diédit sumber ka édisi kagenep. Sababaraha kode tetep sarua, tapi sababaraha kudu rada diédit, ngarobah modern += token ka tinggaleun jaman =+. Sababaraha hal anu saukur dihapus, sarta sababaraha kudu sagemblengna ditulis ulang, tapi ulah teuing.
Sareng dinten ayeuna urang tiasa maca online dina TUHS kode sumber édisi kagenep tina
Ku jalan kitu, dina glance kahiji, fitur utama C-kode saméméh periode Kernighan na Ritchie nyaeta na. singgetan. Teu sering abdi tiasa nyelapkeun potongan kode tanpa éditan éksténsif pikeun nyocogkeun ka daérah tampilan anu kawilang sempit dina situs abdi.
Dina awal
/*
* 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
Ukuran panyangga teu robah saprak édisi kaopat. Tapi di dieu urang ningali, tanpa aya dokuméntasi umum, yén pipelines sakali dipaké file salaku gudang cadangan!
Sedengkeun pikeun file LARG, aranjeunna pakait sareng
Di dieu nyaeta panggero sistem nyata 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;
}
Koméntar jelas ngajelaskeun naon anu lumangsung di dieu. Tapi ngartos kode éta henteu gampang, sabagéan kusabab jalanna "R0
и R1
Parameter panggero sistem sareng nilai mulang disalurkeun.
Hayu urang coba kalawan
pipe()
kudu ngaliwatan R0
и R1
mulangkeun angka deskriptor file pikeun maca jeung nulis. falloc()
mulih pointer kana struktur file, tapi ogé "mulih" via u.u_ar0[R0]
sareng deskriptor file. Hartina, kodeu disimpen dina r
file descriptor pikeun bacaan sarta nangtukeun file descriptor pikeun nulis langsung ti u.u_ar0[R0]
sanggeus panggero kadua falloc()
.
bandera FPIPE
, anu kami setel nalika nyiptakeun pipa, ngatur paripolah fungsina
/*
* 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);
}
/* … */
}
Lajeng fungsi readp()
в pipe.c
maca data tina pipa. Tapi éta hadé pikeun ngalacak palaksanaan mimitian ti writep()
. Sakali deui, kodeu parantos janten langkung rumit kusabab konvénsi ngaliwat argumen, tapi sababaraha detil tiasa dileungitkeun.
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;
}
Kami hoyong nyerat bait kana input pipa u.u_count
. Mimiti urang kedah ngonci inode (tingali di handap plock
/prele
).
Teras we pariksa counter rujukan inode. Salami duanana tungtung pipa tetep kabuka, counter kudu sarua jeung 2. Urang tahan hiji link (tina rp->f_inode
), janten upami counter kirang ti 2, éta kedah hartosna yén prosés maca parantos ditutup tungtung pipa na. Kalayan kecap séjén, urang nyobian nulis ka pipa ditutup, sarta ieu kasalahan. Kode kasalahan munggaran EPIPE
jeung sinyal SIGPIPE
muncul dina édisi kagenep Unix.
Tapi sanajan conveyor dibuka, bisa jadi pinuh. Dina hal ieu, urang ngaleupaskeun konci na buka saré dina harepan yén prosés sejen bakal maca tina pipa jeung ngosongkeun cukup spasi dina eta. Saatos hudang, urang uih deui ka awal, ngagantung konci deui sareng ngamimitian siklus rekaman énggal.
Upami aya cukup rohangan bébas dina pipa, teras urang nyerat data nganggo éta i_size1
inode (lamun pipa kosong bisa sarua jeung 0) nunjukkeun tungtung data nu geus ngandung. Lamun aya cukup spasi rekaman, urang bisa ngeusian pipa ti i_size1
ka PIPESIZ
. Teras we ngaleupaskeun konci sareng nyobian hudang prosés anu ngantosan dibaca tina pipa. Urang balik deui ka awal ningali lamun urang bisa nulis saloba bait sakumaha urang diperlukeun. Upami gagal, teras urang ngamimitian siklus ngarékam énggal.
Biasana parameter i_mode
inode dipaké pikeun nyimpen idin r
, w
и x
. Tapi dina kasus pipelines, urang sinyal yén sababaraha prosés ngantosan hiji nulis atawa maca ngagunakeun bit IREAD
и IWRITE
masing-masing. Prosésna nyetél bandéra sareng nelepon sleep()
, sarta eta diperkirakeun yén sababaraha prosés séjén dina mangsa nu bakal datang bakal ngabalukarkeun wakeup()
.
The magic nyata lumangsung dina sleep()
и wakeup()
. Aranjeunna dilaksanakeun di
/*
* 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) /* … */
Prosés anu ngabalukarkeun sleep()
pikeun saluran tinangtu, bisa engké jadi woken up ku prosés sejen, nu bakal ngabalukarkeun wakeup()
pikeun saluran anu sarua. writep()
и readp()
koordinat lampah maranéhanana ngaliwatan telepon dipasangkeun misalna. Catet éta pipe.c
salawasna méré prioritas PPIPE
lamun disebut sleep()
, tah kitu sleep()
bisa diganggu ku sinyal.
Ayeuna urang gaduh sadayana ngartos fungsina 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);
}
Anjeun tiasa mendakan langkung gampang maca fungsi ieu ti handap ka luhur. Cabang "baca sareng uih deui" biasana dianggo nalika aya sababaraha data dina jalur pipa. Dina hal ieu, urang ngagunakeun f_offset
bacaan, lajeng ngapdet nilai offset pakait.
Dina bacaan saterusna, pipa bakal kosong lamun maca offset geus ngahontal i_size1
di inode. Urang ngareset posisi ka 0 sarta nyoba hudang prosés nu mana wae nu hayang nulis kana pipa nu. Urang terang yén nalika conveyor pinuh, writep()
bakal saré dina ip+1
. Sareng ayeuna yén pipana kosong, urang tiasa hudang pikeun neruskeun siklus nyeratna.
Lamun teu boga nanaon maca, teras readp()
bisa nyetél bandéra IREAD
tur saré dina ip+2
. Urang terang naon anu bakal ngahudangkeun anjeunna writep()
, nalika nyerat sababaraha data kana pipa.
Koméntar kana u
"Urang tiasa ngubaran aranjeunna sapertos fungsi I / O normal anu nyandak file, posisi, panyangga dina mémori, sareng ngitung jumlah bait anu dibaca atanapi ditulis.
/*
* 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;
/* … */
Sedengkeun pikeun blocking "konservatif", lajeng readp()
и writep()
meungpeuk inode nepi ka rengse pagawean maranéhanana atawa narima hasil (nyaéta, nelepon wakeup
). plock()
и prele()
dianggo saukur: ngagunakeun set béda tina panggero sleep
и wakeup
Ngidinan urang hudang prosés naon waé anu peryogi konci anu nembé dileupaskeun:
/*
* 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);
}
}
Mimitina kuring teu ngarti naha readp()
henteu ngabalukarkeun prele(ip)
saméméh nelepon wakeup(ip+1)
. Hal kahiji nyaéta writep()
ngabalukarkeun dina siklus na, ieu plock(ip)
, nu ngabalukarkeun deadlock lamun readp()
henteu acan ngaleungitkeun blok kuring, janten kumaha waé kodeu kedah dianggo leres. Lamun nempo wakeup()
, teras janten écés yén éta ngan ukur nandaan prosés saré siap dieksekusi, ku kituna dina mangsa nu bakal datang. sched()
bener ngaluncurkeunana. Janten readp()
nyababkeun wakeup()
, ngaluarkeun konci, susunan IREAD
jeung nelepon sleep(ip+2)
- sadayana ieu sateuacan writep()
neruskeun siklus.
Ieu ngalengkepan pedaran conveyors dina édisi kagenep. Kode basajan, konsékuansi jauh-ngahontal.
Xv6, kernel basajan kawas Unix
Pikeun nyieun kernel
Kode ngandung palaksanaan jelas tur wijaksana 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()
nangtukeun kaayaan sesa palaksanaan, nu ngawengku fungsi piperead()
, pipewrite()
и pipeclose()
. Telepon sistem sabenerna sys_pipe
nyaeta wrapper dilaksanakeun dina
Linux Ubuntu 0.01
Kode sumber Linux 0.01 tiasa dipendakan. Ieu bakal instructive mun diajar palaksanaan pipelines di na fs
/pipe.c
. Ieu ngagunakeun inode pikeun ngagambarkeun pipa, tapi pipa sorangan ditulis dina C modern. Ieu naon fungsi kasampak kawas 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;
}
Tanpa ningali definisi struktur, anjeun tiasa terang kumaha jumlah rujukan inode dianggo pikeun mariksa naha operasi nulis ngahasilkeun SIGPIPE
. Salian dianggo bait-demi-bait, fungsi ieu gampang dibandingkeun jeung gagasan ditétélakeun di luhur. Komo logika sleep_on
/wake_up
teu kasampak jadi alien.
Kernel Linux modern, FreeBSD, NetBSD, OpenBSD
Kuring gancang lumpat ngaliwatan sababaraha kernels modern. Euweuh sahijina boga palaksanaan disk deui (teu heran). Linux boga palaksanaan sorangan. Sanajan tilu kernels BSD modern ngandung palaksanaan dumasar kana kode anu ditulis ku John Dyson, leuwih taun aranjeunna geus jadi béda teuing ti unggal lianna.
Pikeun maca fs
/pipe.c
(dina Linux) atawa sys
/kern
/sys_pipe.c
(dina *BSD), butuh dedikasi anu nyata. Kodeu dinten ieu ngeunaan kinerja sareng dukungan pikeun fitur sapertos vektor sareng I/O asinkron. Sareng detil alokasi mémori, konci sareng konfigurasi kernel sadayana béda-béda pisan. Ieu sanés anu diperyogikeun ku akademi pikeun kursus sistem operasi perkenalan.
Atoh, kuring resep ngagali sababaraha pola kuno (sapertos ngahasilkeun SIGPIPE
jeung mulang EPIPE
nalika nyerat ka pipa katutup) dina sadaya kernel modern anu béda ieu. Kuring sigana moal pernah ningali komputer PDP-11 dina kahirupan nyata, tapi masih seueur anu diajar tina kode anu ditulis sababaraha taun sateuacan kuring lahir.
Artikel anu ditulis ku Divi Kapoor taun 2011:
sumber: www.habr.com