Mafambisirwo anoitwa mapaipi muUnix

Mafambisirwo anoitwa mapaipi muUnix
Ichi chinyorwa chinotsanangura kushandiswa kwemapaipi muUnix kernel. Ndakanzwa kuodzwa mwoyo kuti chinyorwa chazvino chine musoro unoti "Mapaipi anoshanda sei muUnix?"zvakazoitika kwete nezvechimiro chemukati. Ndakava nechido ndokuchera mumanyuko ekare kuti ndiwane mhinduro.

Tiri kutaura nezvei?

Mapaipi, "zvichida chinonyanya kukosha muUnix," inotsanangura hunhu hweiyo Unix huzivi hwekubatanidza zvirongwa zvidiki pamwechete, pamwe nechiratidzo chakajairika pamutsetse wekuraira:

$ echo hello | wc -c
6

Kushanda uku kunoenderana neiyo kernel-yakapihwa system call pipe, iyo inotsanangurwa pamapeji ezvinyorwa pombi(7) ΠΈ pombi(2):

Mapaipi anopa unidirectional chiteshi chekudyidzana kutaurirana. Iyo pombi ine yekupinda (nyora magumo) uye inobuda (verenga kupera). Dhiyabhorosi yakanyorwa kune kuiswa kwepombi inogona kuverengwa pane zvakabuda.

Iyo pombi inogadzirwa uchishandisa kufona pipe(2), iyo inodzosa zvinyorwa zviviri zvefaira: imwe inoreva kupinza kwepombi, yechipiri kune yakabuda.

Iyo yekuteedzera inobuda kubva pamurairo wepamusoro inoratidza kusikwa kwepombi uye kuyerera kwedata kuburikidza nayo kubva kune imwe nzira kuenda kune imwe:

$ 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

Maitiro evabereki anofona pipe()kuti uwane akakwidzwa faira descriptors. Imwe nzira yemwana inonyora kune imwe mubato, uye imwe nzira inoverenga yakafanana data kubva kune imwe mubato. Iyo goko rinoshandisa dup2 ku "rename" zvinotsanangurwa 3 uye 4 kuti ienderane stdin uye stdout.

Pasina mapaipi, goko raizofanira kunyora mhedzisiro yeimwe nzira kufaira uye kuipfuudza kune imwe nzira yekuverenga iyo data kubva mufaira. Nekuda kweizvozvo, taizopambadza zvimwe zviwanikwa uye disk nzvimbo. Nekudaro, mapaipi akanaka kwete chete nekuti anobvumidza iwe kudzivirira kushandiswa kwemafaira enguva pfupi:

Kana maitiro ari kuedza kuverenga kubva paipi isina chinhu ipapo read(2) ichavhara kusvika data yave kuwanikwa. Kana nzira ichiedza kunyora kune yakazara pombi, saka write(2) ichavhara kusvika data yakakwana yaverengwa kubva pombi kuti iite kunyora.

Kufanana nezvinodiwa zvePOSIX, ichi chinhu chakakosha: kunyora kune pombi kusvika PIPE_BUF mabhayiti (angangoita 512) anofanira kunge ari atomu kuitira kuti maitirwo agone kutaurirana kuburikidza nepombi nenzira iyo mafaira enguva dzose (asingapi zvivimbiso zvakadaro) haakwanise.

Paunenge uchishandisa faira renguva dzose, maitiro anogona kunyora zvese zvawaburitsa kwairi uye ozvipfuudza kune imwe maitiro. Kana kuti maitirwo anogona kushanda nenzira yakanyatsoenderana, uchishandisa nzira yekusaina yekunze (semaphore) kuzivisana kana kunyora kana kuverenga kwapera. Conveyors tiponese kubva kune zvese izvi zvinonetsa.

Tiri kutsvagei?

Ini ndichaitsanangura mumashoko akareruka kuitira kuti zvive nyore kwauri kufungidzira kuti mutakuri anogona kushanda sei. Iwe unozofanirwa kugovera buffer uye imwe nyika mundangariro. Iwe unozoda mabasa ekuwedzera uye kubvisa data kubva mubuffer. Iwe unozoda dzimwe nzira dzekudaidza mabasa panguva yekuverenga nekunyora mashandiro pane zvinotsanangurwa zvefaira. Uye iwe unozoda makiyi kuita iyo yakakosha maitiro atsanangurwa pamusoro.

Ikozvino tagadzirira kubvunzurudza iyo kernel sosi kodhi pasi pemwenje wakajeka kuratidza kana kuramba maitiro edu asina kujeka epfungwa. Asi gara wakagadzirira pane zvisingatarisirwi.

Tiri kutarisa kupi?

Handizive kuti kopi yangu yebhuku rine mukurumbira iripi"Shumba bhuku"neUnix 6 sosi kodhi, asi nekuda kwe Iyo Unix Heritage Society unogona kutsvaga online pa source code kunyangwe shanduro dzekare dzeUnix.

Kufamba-famba nemunzvimbo dzakachengetwa dzeTUHS kwakafanana nekushanyira museum. Tinogona kutarisa nhoroondo yedu yakagovaniswa, uye ndine ruremekedzo kwemakore mazhinji ekuedza kudzoreredza zvese izvi zvishoma zvishoma kubva pamatepi ekare uye akadhinda. Uye ini ndinonyatsoziva nezve izvo zvimedu zvichiri kushaikwa.

Tagutsa kuda kwedu kuziva nezvenhoroondo yekare yezvinotakura zvinhu, tinogona kutarisa kernels dzemazuva ano kuti tizvienzanise.

Nenzira, pipe ndiyo system yekufona nhamba 42 patafura sysent[]. Sangana?

Traditional Unix kernels (1970-1974)

Handina kuwana anoronda pipe(2) kana mukati PDP-7 Unix (Ndira 1970), kana mu yekutanga edition yeUnix (November 1971), kana mune isina kukwana sosi kodhi edition yechipiri (Chikumi 1972).

TUHS inotaura izvozvo chinyorwa chechitatu cheUnix (Kukadzi 1973) yakava yekutanga vhezheni ine conveyors:

Unix 1973rd Edition yaive vhezheni yekupedzisira ine kernel yakanyorwa mumutauro wegungano, asiwo yekutanga vhezheni ine mapaipi. Muna XNUMX, basa rakaitwa kuvandudza chinyorwa chechitatu, kernel yakanyorwa patsva muC, uye saka chinyorwa chechina cheUnix chakaonekwa.

Mumwe muverengi akawana scan yegwaro umo Doug McIlroy akakurudzira zano re "kubatanidza zvirongwa senge hose yebindu."

Mafambisirwo anoitwa mapaipi muUnix
Mubhuku raBrian KernighanUnix: Nhoroondo uye Memoir", munhoroondo yekubuda kwevanotakura, gwaro iri rinotaurwawo: "... rakarembera pamadziro muhofisi yangu kuBell Labs kwemakore makumi matatu." Here kubvunzurudzwa naMcIlroy, uye imwe nyaya kubva Basa raMcIlroy, rakanyorwa muna 2014:

Unix payakabuda, kunakidzwa kwangu nema coroutines kwakaita kuti ndibvunze munyori weOS, Ken Thompson, kuti abvumire data yakanyorwa kune imwe nzira kuti iende kwete kumudziyo chete, asiwo kuburitsa kune imwe nzira. Ken akasarudza kuti zvaibvira. Nekudaro, se minimalist, aida kuti system yese iite basa rakakosha. Kunyora zvakanangana pakati pemaitiro ibasa guru pane kunyora kune yepakati faira? Pakanga pangove pandakaita chirevo chakananga nezita rinobata "pombi" uye tsananguro yesyntax yekudyidzana pakati pemaitiro izvo Ken akazodaidzira kuti: "Ndichazviita!"

Uye akaita. Mamwe manheru aityisa, Ken akachinja kernel negoko, akagadzirisa zvirongwa zvakati wandei kuti amisikidze mabatiro avakaita mapindiro (anogona kubva papombi), uye akachinja mazita emafaira. Zuva rakatevera, mapaipi akatanga kushandiswa zvakanyanya mukushandiswa. Pakazopera vhiki, vanyori vakanga vava kuashandisa kutumira magwaro kubva kumagadzirirwo emashoko kuenda kumudhindi. Mushure mechinguva chidiki, Ken akatsiva iyo yekutanga API uye syntax yekuputira kushandiswa kwepombi nemakonisheni akachenesa, ayo ave achishandiswa kubva ipapo.

Nehurombo, iyo kodhi kodhi yechitatu edition Unix kernel yarasika. Uye kunyangwe isu tine kernel sosi kodhi yakanyorwa muC chinyorwa chechina, yakaburitswa muna Mbudzi 1973, asi yakabuda mwedzi yakati wandei isati yaburitswa zviri pamutemo uye haina mashandisirwo epombi. Zvinonyadzisa kuti iyo kodhi kodhi yeiyi ine mukurumbira Unix basa yakarasika, pamwe zvachose.

Tine zvinyorwa zvinyorwa zve pipe(2) kubva pane zvese zvaburitswa, saka unogona kutanga nekutsvaga zvinyorwa chinyorwa chechitatu (kune mamwe mazwi, akadhindwa β€œnemaoko”, tambo yezvinoreva ^H, ichiteverwa neine underscore!). Ichi chiratidzo-pipe(2) yakanyorwa mumutauro wegungano uye inongodzosera faira rimwe chete rinotsanangura, asi rinotopa iro rinotarisirwa basa rekutanga:

System call pipe inogadzira nzira yekupinza/inoburitsa inonzi pipeline. Iyo yakadzoserwa faira descriptor inogona kushandiswa kuverenga nekunyora mashandiro. Kana chimwe chinhu chichinyorwa kune pombi, inosvika 504 bytes yedata inovharwa, mushure mezvo maitiro ekunyora anomiswa. Paunenge uchiverenga kubva papombi, iyo buffer data inotorwa.

Pakazosvika gore rakatevera kernel yakanga yanyorwazve muC, uye pombi(2) muchinyorwa chechina yakawana chimiro chayo chemazuva ano neiyo prototype "pipe(fildes)Β»:

System call pipe inogadzira nzira yekupinza/inoburitsa inonzi pipeline. Iyo yakadzoserwa faira tsananguro inogona kushandiswa mukuverenga nekunyora mashandiro. Kana chimwe chinhu chichinyorwa kune pombi, mubato wakadzoserwa mu r1 (resp. fildes[1]) unoshandiswa, wakavharirwa ku4096 bytes yedata, mushure mezvo kunyora kunomiswa. Paunenge uchiverenga kubva pombi, mubato wakadzokera ku r0 (resp. fildes[0]) unotora data.

Zvinofungidzirwa kuti kana pombi yatsanangurwa, maviri (kana kupfuura) nzira dzekutaurirana (dzakagadzirwa nefoni dzinotevera Fork) ichaendesa data kubva pombi uchishandisa mafoni verenga ΠΈ nyora.

Iyo shell ine syntax yekutsanangura mutsara mutsara wemaitiro akabatanidzwa nepombi.

Mafoni ekuverenga kubva papombi isina chinhu (isina data yakavharwa) ine mugumo mumwe chete (zvese zvinyorwa zvefaira zvekunyora zvakavharwa) dzorera "kupera kwefaira". Mafoni ekunyora mumamiriro ezvinhu akafanana anofuratirwa.

Earliest kushandiswa kwepombi yakachengetedzwa inotsanangura kusvika kuchikamu chechishanu cheUnix (Chikumi 1974), asi yakada kufanana neyakaonekwa mukuburitswa kunotevera. Mhinduro dzichangowedzerwa, saka unogona kusvetuka chinyorwa chechishanu.

Gwaro rechitanhatu reUnix (1975)

Ngatitange kuverenga Unix source code yechitanhatu edition (Chivabvu 1975). Zvikuru thanks to shumba zviri nyore kuwana pane kwakabva mavhezheni ekutanga:

Kwemakore akawanda bhuku racho shumba ndiro chete gwaro paUnix kernel inowanikwa kunze kweBell Labs. Kunyange zvazvo rezinesi rechitanhatu raibvumira vadzidzisi kushandisa kodhi yaro, rezenisi reshanduro yechinomwe rakanga risingabatanidzi mukana uyu, saka bhuku racho rakaparadzirwa semakopi akanyorwa zvisiri pamutemo.

Nhasi unogona kutenga kudhindwazve kwebhuku, kavha iyo inoratidza vadzidzi pamushini wekukopa. Uye nekuda kweWarren Toomey (uyo akatanga chirongwa cheTUHS) unogona kudhawunirodha PDF file ine source code yeichitanhatu edition. Ndinoda kukupa pfungwa yekuti kwakawanda sei kuedza kwakaenda mukugadzira faira:

Anopfuura makore gumi nemashanu apfuura, ndakataipa kopi yekodhi kodhi yakapihwa mukati shumba, nokuti ndakanga ndisingadi kunaka kwekopi yangu kubva kune nhamba isingazivikanwi yemamwe makopi. TUHS yanga isati yavepo uye ini ndakanga ndisingakwanise kuwana zvekare zvinyorwa. Asi muna 1988, ndakawana tepi yekare ye9-track yaive ne backup kubva pakombuta yePDP11. Zvakanga zvakaoma kutaura kana yaishanda, asi pakanga paine intact / usr/src/ muti umo mafaera mazhinji aive akanyorwa negore 1979, iro rakatotaridzika rekare. Yakanga iri chinyorwa chechinomwe kana chirevo chayo chePWB, sezvandaitenda.

Ndakatora iyo yakawana sehwaro uye nemaoko ndakagadzirisa masosi kune yechitanhatu edition. Imwe kodhi yakaramba yakafanana, asi imwe yaifanirwa kugadziridzwa zvishoma, ichichinja yemazuva ano += tokeni kune yechinyakare =+. Zvimwe zvinhu zvakangodzimwa, uye zvimwe zvaifanira kunyorwazve, asi kwete zvakanyanya.

Uye nhasi tinogona kuverenga online paTUHS iyo kodhi kodhi yechitanhatu edition kubva archive, iyo Dennis Ritchie aive neruoko.

Nenzira, pakutanga kutarisa, chinhu chikuru cheC-code nguva isati yasvika yeKernighan naRitchie ndiyo yayo. pfupi. Haisi kazhinji kuti ini ndinokwanisa kuisa zvidimbu zvekodhi pasina kurongeka kwakawanda kuti ikwane nzvimbo yakamanikana yekuratidzira pane yangu saiti.

Pakutanga /usr/sys/ken/pipe.c pane tsanangudzo inotsanangura (uye hongu, pane zvimwe /usr/sys/dmr):

/*
 * 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

Saizi yebhafa haina kushanduka kubva pashanduro yechina. Asi pano tinoona, pasina chero zvinyorwa zveveruzhinji, kuti mapaipi akamboshandisa mafaera sekuchengetedza kuchengetedza!

Kana ari LARG mafaera, anowirirana ne inode mureza LARG, iyo inoshandiswa ne "hombe addressing algorithm" kugadzirisa indirect blocks kutsigira mafaira makuru. Sezvo Ken akati zviri nani kusazvishandisa, ndichagamuchira shoko rake nokuda kwayo nomufaro.

Heino chaiyo system call 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;
}

Mhinduro yacho inotsanangura zvakajeka zviri kuitika pano. Asi kunzwisisa kodhi hakusi nyore, chikamu nekuda kwenzira "gadzira mushandisi uΒ»uye mabhuku R0 ΠΈ R1 system call parameters uye kudzoka kukosha kunopfuudzwa.

Ngatiedze ne ialloc() kuisa pa diski inode (index handle), uye nerubatsiro falloc () - isa mbiri mundangariro faira. Kana zvese zvikafamba zvakanaka, tichaseta mireza yekuona mafaera aya semigumo miviri yepombi, toanongedzera kune imwechete inode (iyo nhamba yereferensi ichaiswa ku2), womaka iyo inode seyakagadziridzwa uye mukushandiswa. Chenjerera kune zvikumbiro kune iput() munzira dzekukanganisa kudzikisa nhamba yereferensi mune itsva inode.

pipe() anofanira kuburikidza R0 ΠΈ R1 dzosa nhamba dzetsananguro dzefaira dzekuverenga nekunyora. falloc() inodzosera chinongedzo kune iyo faira chimiro, asi zvakare "inodzoka" kuburikidza u.u_ar0[R0] uye faira descriptor. Ndiko kuti, kodhi inochengetedza mukati r faira descriptor yekuverenga uye inopa tsananguro yefaira yekunyora zvakananga kubva u.u_ar0[R0] mushure mekufona kwechipiri falloc().

Flag FPIPE, iyo yatinoisa pakugadzira pombi, inodzora maitiro ebasa racho rdwr() mu sys2.ckudaidza maitiro eI/O chaiwo:

/*
 * 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);
    }
        /* … */
}

Zvadaro basa readp() Π² pipe.c inoverenga data kubva pombi. Asi zviri nani kuronda kuitisa kutanga kubva writep(). Zvekare, iyo kodhi yawedzera kuomarara nekuda kwezvibvumirano zvekupfuura nharo, asi mamwe madeti anogona kusiiwa.

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;
}

Tinoda kunyora mabhaiti kune pombi yekupinda u.u_count. Kutanga isu tinoda kukiya iyo inode (ona pazasi plock/prele).

Zvadaro tinotarisa inode reference counter. Chero bedzi migumo yese yepombi ichiramba yakavhurika, counter inofanira kuenzana ne 2. Tinobata imwe link (kubva rp->f_inode), saka kana counter iri pasi pe2, inofanira kureva kuti kuverenga kwakavhara kupera kwayo kwepombi. Mune mamwe mazwi, tiri kuedza kunyorera pombi yakavharwa, uye ichi chikanganiso. Kekutanga kukanganisa kodhi EPIPE uye chiratidzo SIGPIPE yakabuda muchikamu chechitanhatu cheUnix.

Asi kunyange kana conveyor yakazaruka, inogona kunge yakazara. Muchiitiko ichi, tinosunungura kuvhara uye tinoenda kunorara mune tariro yokuti imwe nzira ichaverenga kubva pombi uye kusunungura nzvimbo yakakwana mairi. Tamuka, tinodzokera pakutanga, sungirira kukiya zvakare uye wotanga kutenderera kutsva kwekurekodha.

Kana pane nzvimbo yakakwana yemahara mupombi, saka tinonyora data kwairi tichishandisa kunyora (). Parameter i_size1 inode (kana pombi isina chinhu, inogona kuenzana ne0) inoratidza kupera kwe data iyo yatove nayo. Kana paine nzvimbo yekurekodha yakakwana, tinogona kuzadza pombi kubva i_size1 up to PIPESIZ. Zvadaro tinosunungura kuvhara uye edza kumutsa chero maitiro akamirira kuverenga kubva pombi. Tinodzokera kumashure kuti tione kana takakwanisa kunyora mabhaiti akawanda sezvataida. Kana ikatadza, saka tinotanga kutenderera kutsva kwekurekodha.

Kazhinji parameter i_mode inode inoshandiswa kuchengetedza mvumo r, w ΠΈ x. Asi panyaya yemapaipi, tinoratidza kuti mamwe maitiro akamirira kunyora kana kuverenga uchishandisa mabits IREAD ΠΈ IWRITE zvichiteerana. Iyo nzira inoisa mureza uye inofona sleep(), uye zvinotarisirwa kuti imwe nzira mune ramangwana ichakonzera wakeup().

Mashiripiti chaiwo anoitika mukati sleep() ΠΈ wakeup(). Zvinoitwa mukati slp.c, kunobva kune yakakurumbira "Hautarisirwe kunzwisisa izvi" chirevo. Neraki, isu hatifanirwe kunzwisisa iyo kodhi, ingotarisa mamwe mazwi:

/*
 * 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) /* … */

Nzira inokonzera sleep() kune imwe nzira, inogona kuzomutswa neimwe nzira, inozokonzera wakeup() kune imwe chiteshi. writep() ΠΈ readp() kurongedza zviito zvavo kuburikidza nemafoni maviri akadai. cherechedza kuti pipe.c nguva dzose inopa pakutanga PPIPE kana adanwa sleep(), saka ndizvozvo sleep() inogona kuvhiringwa nechiratidzo.

Iye zvino tine zvose kuti tinzwisise basa racho 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);
}

Unogona kuwana zviri nyore kuverenga basa iri kubva pasi kusvika kumusoro. Iro "kuverenga nekudzoka" bazi rinowanzo shandiswa kana paine imwe data mupombi. Muchiitiko ichi, tinoshandisa kuverenga () tinoverenga data rakawanda sezviripo kutanga kubva kune yazvino f_offset kuverenga, uye wobva wavandudza kukosha kweiyo inoenderana offset.

Pakuverenga kunotevera, pombi ichange isina chinhu kana iyo yekuverenga offset yasvika i_size1 pa inode. Isu tinogadzirisa nzvimbo yacho ku0 uye edza kumutsa chero maitiro anoda kunyora kune pombi. Tinoziva kuti kana conveyor yazara, writep() achakotsira ip+1. Uye zvino sezvo pombi isina chinhu, tinogona kuimutsa kuti itangezve kutenderera kwayo kwekunyora.

Kana usina chekuverenga, saka readp() anogona kuseta mureza IREAD ndokuvata ip+2. Tinoziva zvichamumutsa writep(), painonyora imwe data kune pombi.

Comments to kuverenga () uye kunyora () ichakubatsira kuti unzwisise kuti pane kupfuudza parameter kuburikidza ne "u"Tinogona kuvabata senge zvakajairika I / O mabasa anotora faira, chinzvimbo, buffer mundangariro, uye kuverenga nhamba yemabhaiti kuverenga kana kunyora.

/*
 * 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;
/* … */

Kana iri "inochengetedza" kuvharira, saka readp() ΠΈ writep() vhara iyo inode kusvika vapedza basa ravo kana kugamuchira mhedzisiro (kureva, kufona wakeup). plock() ΠΈ prele() shanda zviri nyore: kushandisa akasiyana seti yekufona sleep ΠΈ wakeup tibvumire kumutsa chero maitiro anoda kukiyiwa kwatichangobva kuburitsa:

/*
 * 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);
    }
}

Pakutanga ndakatadza kunzwisisa chikonzero nei readp() haina kukonzera prele(ip) tisati tafona wakeup(ip+1). Chinhu chekutanga ndechekuti writep() zvinokonzera mukutenderera kwayo, izvi plock(ip), izvo zvinotungamira kune deadlock kana readp() handisati ndabvisa block yangu, saka neimwe nzira kodhi inofanira kushanda nemazvo. Kana iwe ukatarisa wakeup(), zvino zvinova pachena kuti inongoratidzira nzira yekurara seyakagadzirira kuita, kuitira kuti mune ramangwana sched() zvaitanga chaizvo. Saka readp() chinokonzera wakeup(), inobvisa kukiya, inoisa IREAD uye kufona sleep(ip+2)- zvese izvi zvisati zvaitika writep() inotangazve kutenderera.

Izvi zvinopedzisa tsananguro yemaconveyors muchikamu chechitanhatu. Nyore kodhi, mhedzisiro inosvika kure.

Edition yechinomwe yeUnix (Ndira 1979) yaive nyowani huru kuburitswa (makore mana gare gare) yakaunza akawanda matsva ekushandisa uye kernel maficha. Yakavewo neshanduko dzakakosha maererano nekushandiswa kwemhando yekukanda, mibatanidzwa uye mataipi anonongedzera kune zvimiro. Zvisinei conveyor code inenge isina kushanduka. Tinogona kusvetuka chinyorwa ichi.

Xv6, iri nyore Unix-yakafanana kernel

Kugadzira kernel Xv6 inofurirwa neiyo yechitanhatu edition yeUnix, asi yakanyorwa mune yazvino C kuti imhanye pa x86 processors. Kodhi iri nyore kuverenga uye inonzwisisika. Uyezve, kusiyana neUnix masosi ane TUHS, unogona kuiunganidza, kuigadzirisa, uye kuimhanyisa pane chimwe chinhu kunze kwePDP 11/70. Naizvozvo, iyi kernel inoshandiswa zvakanyanya mumayunivhesiti sezvinhu zvekudzidzisa pane anoshanda masisitimu. Sources vari paGithub.

Iyo kodhi ine yakajeka uye inofungisisa kuita pipe.c, inotsigirwa nebhafa mundangariro panzvimbo peinode pa diski. Pano ini ndinopa chete tsananguro ye "structural pipeline" uye basa 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() inogadzirisa mamiriro ezvimwe zvekushandiswa, izvo zvinosanganisira mabasa piperead(), pipewrite() ΠΈ pipeclose(). Actual system call sys_pipe iri wrapper inoshandiswa mukati sysfile.c. Ndinokurudzira kuverenga kodhi yake yese. Iyo yakaoma iri pamwero weiyo kodhi kodhi yechitanhatu edition, asi zviri nyore uye zvakanyanya kunakidza kuverenga.

Linux 0.01

Linux 0.01 source code inogona kuwanikwa. Zvichava kudzidzisa kudzidza kushandiswa kwepombi mune yake fs/pipe.c. Izvi zvinoshandisa inode kumiririra pombi, asi pombi pachayo yakanyorwa nemazuva ano C. Kana iwe wakashanda nzira yako kuburikidza neXNUMXth edition code, hauzove nedambudziko pano. Izvi ndizvo zvinoita basa racho 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;
}

Pasina kana kutarisa kune tsananguro yechimiro, unogona kuona kuti inode reference count inoshandiswa sei kutarisa kana basa rekunyora rinoguma SIGPIPE. Pamusoro pekushanda byte-by-byte, basa iri riri nyore kuenzanisa nemazano anotsanangurwa pamusoro. Kunyange pfungwa sleep_on/wake_up hazviratidzike semutorwa.

Mazuva ano Linux kernels, FreeBSD, NetBSD, OpenBSD

Ndakabva ndamhanya nemu tsanga dzemazuvano. Hapana kana mumwe wavo ane dhisiki kuita zvakare (hazvishamise). Linux ine kwayo kuita kwayo. Kunyangwe iwo matatu emazuva ano BSD kernels aine mashandisirwo akavakirwa pakodhi yakanyorwa naJohn Dyson, nekufamba kwemakore vakave vakasiyana zvakanyanya kubva kune mumwe nemumwe.

Kuverenga fs/pipe.c (paLinux) kana sys/kern/sys_pipe.c (pa * BSD), zvinoda kuzvipira chaiko. Kodhi yanhasi ndeyekuita uye kutsigirwa kwezvinhu zvakaita sevector uye asynchronous I/O. Uye ruzivo rwekugoverwa kwendangariro, makiyi uye kernel kumisikidzwa zvese zvinosiyana zvakanyanya. Izvi hazvisi izvo izvo makoreji anoda kune yekutanga masisitimu ekushandisa kosi.

Zvakadaro, ndaifarira kuchera mamwe mapatani ekare (sekugadzira SIGPIPE uye kudzoka EPIPE pakunyorera pombi yakavharwa) mune idzi kernels dzakasiyana dzemazuva ano. Ini handifi ndakamboona PDP-11 komputa muhupenyu chaihwo, asi pachine zvakawanda zvekudzidza kubva kukodhi yakanyorwa makore ndisati ndazvarwa.

Chinyorwa chakanyorwa naDivi Kapoor muna 2011:Iyo Linux Kernel Implementation yeMapombi uye FIFOs" inopa tarisiro yekuti mapaipi (achiri) anoshanda sei muLinux. A yazvino kuita muLinux inoratidzira pombi yemhando yekudyidzana, ine masimba anopfuura ayo emafaira enguva pfupi; uye zvakare inoratidza kuti mapaipi abva kure sei kubva "kunochengetedza kukiya" kwechitanhatu edition Unix kernel.

Source: www.habr.com

Voeg