Me pehea te whakatinanatanga o nga paipa ki Unix

Me pehea te whakatinanatanga o nga paipa ki Unix
Ko tenei tuhinga e whakaatu ana i te whakatinanatanga o nga paipa i roto i te kernel Unix. I ahua pouri ahau mo tetahi tuhinga tata nei ko "Me pehea te mahi paipa i Unix?"ka puta e kore mo te hanganga o roto. Ka pakiki ahau, ka keri ahau ki nga puna tawhito kia kitea te whakautu.

He aha ta tatou e korero nei?

Ko nga Pipelines, "te mea te mea tino nui rawa atu i Unix," he tohu tohu o te kaupapa o Unix mo te hono tahi i nga kaupapa iti, me tetahi tohu mohio ki te raina whakahau:

$ echo hello | wc -c
6

Ko tenei mahi e whakawhirinaki ana ki te waea punaha ka tukuna mai pipe, e whakaahuatia ana i nga wharangi tuhinga paipa(7) и paipa(2):

Ko nga Pipelines he hongere kotahi mo te whakawhitiwhitinga whakawhiti. Ko te paipa he whakaurunga (tuhia te mutunga) me te putanga (te panui mutunga). Ko nga raraunga kua tuhia ki te whakauru o te paipa ka taea te panui i te putanga.

Ka hangaia te paipa ma te waea pipe(2), e whakahoki ana i nga whakaahua e rua o nga konae: kotahi e tohu ana ki te whakaurunga o te paipa, te tuarua ki te putanga.

Ko te putanga tohu mai i te whakahau i runga ake nei e whakaatu ana i te hanganga o te pipeline me te rere o nga raraunga mai i tetahi tukanga ki tetahi atu:

$ 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

Ka karanga te tukanga matua pipe()ki te tiki i nga kaiwhakaahua konae. Ka tuhi tetahi tukanga tamaiti ki tetahi kakau, ko tetahi atu tukanga ka panui i nga raraunga ano mai i tetahi atu kakau. Ka whakamahia e te anga te dup2 ki te "whakaingoa ano" nga kaiwhakaahua 3 me te 4 kia taurite ki te stdin me te stdout.

Ki te kore he paipa, me tuhi te anga i te putanga o tetahi tukanga ki tetahi konae ka tuku ki tetahi atu tukanga hei panui i nga raraunga mai i te konae. Ko te mutunga mai, ka moumou tatou i nga rauemi me te mokowā kōpae. Heoi, he pai nga paipa kore noa na te mea ka taea e koe te karo i te whakamahi i nga konae rangitahi:

Mena kei te ngana tetahi tukanga ki te panui mai i te paipa korepu katahi read(2) ka aukati kia watea mai nga raraunga. Mena ka ngana tetahi tukanga ki te tuhi ki te paipa katoa, na write(2) ka aukati kia nui ra ano nga raraunga ka panuihia mai i te paipa hei mahi i te tuhi.

Pērā i te whakaritenga POSIX, he taonga nui tenei: te tuhi ki te paipa tae noa ki PIPE_BUF paita (i te iti rawa 512) me noho ngota kia taea ai e nga tukanga te whakawhiti korero ki a raua ano ma te paipa kia kore e taea e nga konae (kaore i te whakarato i nga taurangi pera).

I te wa e whakamahi ana i te konae, ka taea e te tukanga te tuhi i ona putanga katoa ki a ia ka tuku atu ki tetahi atu tukanga. Ka taea ranei e nga tukanga te mahi i roto i te aratau tino whakarara, ma te whakamahi i tetahi tohu tohu o waho (penei i te semaphore) hei whakamohio tetahi ki tetahi ka oti te tuhi, te panui ranei. Ko nga kaikorero ka whakaora i a maatau mai i enei raru katoa.

He aha ta tatou e rapu ana?

Ka whakamāramahia e au i roto i nga kupu ngawari kia maamaa ake ki a koe te whakaaro me pehea te mahi a te kaikawe. Ka hiahia koe ki te toha i tetahi papaa me etahi ahuatanga kei roto i te mahara. Ka hiahia koe ki te taapiri me te tango i nga raraunga mai i te papaa. Ka hiahia koe ki etahi tikanga ki te karanga i nga mahi i te waa panui me te tuhi i nga mahi i runga i nga kaiwhakaahua konae. A ka hiahia koe ki nga raka hei whakatinana i te whanonga motuhake kua whakaahuatia i runga ake nei.

Inaianei kua reri matou ki te uiui i te waehere puna kernel i raro i te rama maramara hei whakaū, hei whakahē ranei i to maatau tauira hinengaro koretake. Engari kia rite tonu mo nga mea ohorere.

Kei hea tatou e titiro ana?

Kaore au i te mohio kei hea taku kape o te pukapuka rongonui "pukapuka Raiona"me te waehere puna Unix 6, engari he mihi ki Te Unix Heritage Society ka taea e koe te rapu ipurangi i waehere puna ara nga putanga tawhito o Unix.

Ko te haereere i roto i nga purongo TUHS he rite ki te toro ki te whare taonga. Ka taea e tatou te titiro ki o maatau korero hitori, a ka whakanui ahau i nga tau maha o te whakapau kaha ki te whakahoki mai i enei mea katoa mai i nga riipene me nga taarua tawhito. A e tino mohio ana ahau ki aua kongakonga kei te ngaro tonu.

I te makona i to maatau hiahia mo nga korero tawhito o nga kaikawe, ka taea e tatou te titiro ki nga kakano hou hei whakataurite.

I te ara, pipe ko te nama waea 42 kei te ripanga sysent[]. He tupono noa?

Nga kakano Unix tuku iho (1970–1974)

Kaore au i kitea he tohu pipe(2) kaore ano i roto PDP-7 Unix (Hanuere 1970), kaore ano i roto putanga tuatahi o Unix (Noema 1971), kaore ano i roto i te waehere puna kore oti putanga tuarua (Pipiri 1972).

E kii ana a TUHS putanga tuatoru o Unix Ko (Pepuere 1973) te putanga tuatahi me nga kaikawe:

Ko te Unix 1973rd Edition te putanga whakamutunga me te pata i tuhia ki te reo huihuinga, engari ko te putanga tuatahi me nga paipa. I te tau XNUMX, i mahia nga mahi ki te whakapai ake i te putanga tuatoru, i tuhia ano te kernel ki te C, no reira ka puta te putanga tuawha o Unix.

I kitea e tetahi kaipanui he karapa o tetahi tuhinga i kii a Doug McIlroy i te whakaaro mo te "hononga kaupapa penei i te ngongo kari."

Me pehea te whakatinanatanga o nga paipa ki Unix
I roto i te pukapuka a Brian KernighanUnix: He History and a Memoir", i roto i te hitori o te putanga o nga kaikawe, kua whakahuahia ano tenei tuhinga: "... i whakairihia ki runga i te pakitara o taku tari i Bell Labs mo nga tau 30." I konei uiui me McIlroy, me tetahi atu korero mai i Ko nga mahi a McIlroy, i tuhia i te tau 2014:

I te putanga mai o Unix, na taku whakapoipo ki nga coroutines i patai ahau ki te kaituhi o te OS, a Ken Thompson, kia tukua nga raraunga kua tuhia ki tetahi tukanga kia haere ki te taputapu anake, engari ki te whakaputa ki tetahi atu tukanga. I whakatau a Ken ka taea. Heoi, i te mea he iti, i hiahia ia kia whai waahi nui nga mahi katoa o te punaha. Ko te tuhi tika i waenga i nga tukanga he painga nui ki te tuhi ki te konae takawaenga? I te wa i hanga e au tetahi tono motuhake me te ingoa hopu "pipeline" me te whakaahuatanga mo te syntax mo te taunekeneke i waenga i nga mahi katahi ano ka kii a Ken: "Ka mahia e au!"

Na ka mahi. I tetahi ahiahi tino kino, ka huri a Ken i te pata me te anga, ka whakatikahia etahi kaupapa paerewa hei whakataurite i te ahua o ta ratou whakaae ki te whakaurunga (ka puta mai i te paipa), me te whakarereke i nga ingoa konae. I te ra i muri mai, ka timata nga paipa ki te whakamahi tino whanui ki nga tono. I te mutunga o te wiki, i whakamahia e nga hekeretari ki te tuku tuhinga mai i nga kaihanga kupu ki te kaituhi. I muri tata mai, ka whakakapi a Ken i te API taketake me te wetereo mo te takai i te whakamahi o nga paipa me nga tikanga horoi, kua whakamahia mai i tera wa.

Kia aroha mai, kua ngaro te waehere puna mo te putanga tuatoru Unix kernel. A ahakoa kei a maatau te waehere puna kernel i tuhia ki C putanga tuawha, i tukuna i te Whiringa-a-rangi 1973, engari i puta mai i etahi marama i mua i te tukunga mana me te kore he whakaurunga paipa. He mea whakama kua ngaro te waehere puna mo tenei mahi rongonui rongonui a Unix, mo ake tonu atu.

Kei a matou nga tuhinga tuhinga mo pipe(2) mai i nga putanga e rua, na ka taea e koe te timata ma te rapu i nga tuhinga putanga tuatoru (mō ētahi kupu, kua tārarohia “ma-ā-ringa”, he aho kupu ^H, whai muri i te tohu raro!). Tenei proto-pipe(2) kua tuhia ki te reo huihuinga me te whakahoki kotahi anake te kaiwhakaahua konae, engari kua whakaratohia te mahi matua e tumanakohia ana:

Waea punaha pipe ka hangaia he tikanga whakauru/puta e kiia nei he paipa. Ka taea te whakamahi i te whakaahuatanga konae kua whakahokia mai mo nga mahi panui me te tuhi. Ina tuhia tetahi mea ki te paipa, ka tae atu ki te 504 paita o nga raraunga ka parea, ka mutu ka whakatarewahia te mahi tuhi. I te wa e panui ana mai i te paipa, ka tangohia nga raraunga kua parea.

I te tau i muri mai kua tuhia ano te kakano ki te C, a paipa(2) i te putanga tuawha kua whiwhi tona ahua hou me te tauira "pipe(fildes)"

Waea punaha pipe ka hangaia he tikanga whakauru/puta e kiia nei he paipa. Ka taea te whakamahi i nga kaiwhakaahua konae kua whakahokia mai ki nga mahi panui me te tuhi. Ina tuhia tetahi mea ki te paipa, ka whakamahia te kakau i whakahokia i roto i te r1 (resp. fildes[1]), ka panaia ki te 4096 paita o nga raraunga, ka mutu ka whakatarewahia te mahi tuhi. I te panui mai i te paipa, ka hoki te kakau ki te r0 (resp. fildes[0]) ka tango i nga raraunga.

E kiia ana ka whakatauhia he paipa, e rua (neke atu ranei) nga tukanga whakawhitiwhiti (i hangaia e nga waea o muri mai ki Toka) ka whakawhiti raraunga mai i te paipa ma te whakamahi waea te pānui i и tuhituhi.

He wetereo ta te anga mo te tautuhi i te rarangi rarangi o nga tukanga e honoa ana e te paipa.

Ko nga waea ki te panui mai i te paipa putua (kaore he raraunga parepare) kotahi anake te pito (kua kati nga kaiwhakaahua tuhinga tuhi) ka whakahoki "mutunga o te konae". Kare e arohia nga waea ki te tuhi i tetahi ahuatanga penei.

Matamua te whakatinana i te paipa paipa tohutoro ki te putanga tuarima o Unix (Pipiri 1974), engari he rite tonu ki tera i puta i te whakaputanga i muri mai. Katahi ano ka taapirihia nga korero, na reira ka taea e koe te peke i te putanga tuarima.

Putanga tuaono o Unix (1975)

Me timata taatau ki te panui i te waehere puna Unix putanga tuaono (Mei 1975). Nga mihi nui ki raiona he maamaa ake te kimi i nga puna o nga putanga o mua:

Mo nga tau maha te pukapuka raiona Ko te tuhinga anake kei runga i te pata Unix kei waho o Bell Labs. Ahakoa te raihana o te putanga tuaono i taea e nga kaiako te whakamahi i tana waehere puna, i whakakorehia e te raihana putanga tuawhitu tenei tupono, na reira i tohatohahia te pukapuka ki te ahua o nga kape tuhi kore ture.

I tenei ra ka taea e koe te hoko i tetahi tuhinga o te pukapuka, ko te uhi e whakaatu ana i nga akonga kei te miihini kape. Na ka mihi ki a Warren Toomey (nona i timata te kaupapa TUHS) ka taea e koe te tango Kōnae PDF me te waehere puna mo te putanga tuaono. E hiahia ana ahau ki te tuku whakaaro ki a koe mo te nui o te kaha ki te hanga i te konae:

Neke atu i te 15 tau ki muri, ka pato ahau i tetahi kape o te waehere puna kua hoatu ki roto raiona, na te mea kaore au i pai ki te kounga o taku kape mai i etahi atu kape kaore e mohiotia. Kare ano a TUHS i te noho, kaore au i whai waahi ki nga puna tawhito. Engari i te tau 1988, i kitea e ahau he riipene 9-ara tawhito kei roto he taapiri mai i te rorohiko PDP11. He uaua ki te kii mena kei te mahi, engari he rakau tonu /usr/src/ i tapaina te nuinga o nga konae ki te tau 1979, he ahua tawhito tonu. Koia te putanga tuawhitu, ko tana whakaputanga PWB ranei, ki taku i whakapono ai.

I tangohia e au te kitenga hei putake me te whakatika a ringa i nga puna ki te putanga tuaono. He rite tonu etahi o te waehere, engari ko etahi me whakarereke paku, ka huri i te tohu += hou ki te =+ tawhito. Ko etahi mea i mukua noa, ko etahi me tino tuhi ano, engari kaua e nui rawa.

Na i tenei ra ka taea e taatau te panui ipurangi i runga i te TUHS te waehere puna o te putanga tuaono mai puranga, he ringa to Dennis Ritchie.

Ma te ara, i te wa tuatahi, ko te waahanga nui o te C-code i mua i te wa o Kernighan me Ritchie ko tana poto. Ehara i te nuinga o nga wa ka taea e au te whakauru i nga waahanga o te waehere me te kore e whakatika nui kia uru ki tetahi waahi whakaatu ahua whaiti ki taku pae.

I te timatanga /usr/sys/ken/pipe.c he korero whakamarama (ae, he maha atu ano /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

Kaore i rereke te rahi o te papaa mai i te putanga tuawha. Engari i konei ka kite tatou, kaore he tuhinga a te iwi, i whakamahia e nga pipeline nga konae hei rokiroki taapiri!

Mo nga konae LARG, he rite ki haki inode LARG, e whakamahia ana e te "algorithm korero nui" ki te tukatuka poraka autaki hei tautoko i nga punaha konae nui ake. I te mea i kii a Ken he pai ake kia kaua e whakamahia, ka harikoa ahau ki tana kupu.

Anei te tino waea punaha 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;
}

E whakamarama ana te korero i nga mea kei konei. Engari ko te mohio ki te waehere ehara i te mea ngawari, na te huarahi "kaiwhakamahi hanganga u» me nga rehita R0 и R1 kua paahitia nga tawhā waea punaha me nga uara whakahoki.

Kia tamata tatou me ialloc() hoatu ki runga kōpae inode (te kakau taupū), me te awhina falloc() - waiho kia rua ki te mahara konae. Mena ka pai nga mea katoa, ka whakatauhia e matou nga haki hei tohu i enei konae hei pito e rua o te paipa, tohuhia ki te inode kotahi (ko te kaute tohutoro ka tohua ki te 2), ka tohu i te inode kua whakarereketia me te whakamahi. Kia tupato ki nga tono iput() i nga ara hapa hei whakaiti i te tatauranga tohutoro i roto i te inode hou.

pipe() me puta R0 и R1 whakahokia nga nama whakaahua mo te panui me te tuhi. falloc() ka whakahoki i te atatohu ki te hanganga o te konae, engari ka "hoki" ma te u.u_ar0[R0] me tetahi tuhinga whakaahua. Arā, ka penapena te waehere ki roto r he kaiwhakaahua konae mo te panui me te tautapa he kaiwhakaahua konae hei tuhi tika mai u.u_ar0[R0] i muri i te karanga tuarua falloc().

Kara FPIPE, ka whakaturia e matou i te wa e hanga ana i te pipeline, e whakahaere ana i te whanonga o te mahi rdwr() i te sys2.cte karanga i nga mahinga I/O motuhake:

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

Katahi te mahi readp() в pipe.c panui raraunga mai i te paipa. Engari he pai ake te whai i te whakatinanatanga mai i writep(). Ano, kua uaua ake te waehere na runga i nga tikanga o te tuku tohenga, engari ka taea te waiho etahi korero.

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

E hiahia ana matou ki te tuhi paita ki te whakaurunga paipa u.u_count. Tuatahi me maukati te inode (tirohia i raro nei plock/prele).

Na ka tirohia e matou te kaute tohutoro inode. I te mea ka tuwhera tonu nga pito e rua o te paipa paipa, me rite te porotiti ki te 2. Kotahi te hononga (mai i rp->f_inode), na, ki te iti iho te porotiti i te 2, ko te tikanga kua katia e te tukanga panui tona pito o te paipa. I etahi atu kupu, kei te ngana matou ki te tuhi ki te paipa kati, a he he tenei. Waehere hapa tuatahi EPIPE me te tohu SIGPIPE i puta i te putanga tuaono o Unix.

Engari ahakoa kua tuwhera te kaikawe, kua ki tonu. I tenei keehi, ka tukuna e matou te raka ka haere ki te moe i runga i te tumanako ka panui tetahi atu tukanga mai i te paipa me te watea i te waahi ki roto. Ka oho ake, ka hoki ano ki te timatanga, ka whakairihia ano te raka ka timata i te huringa rekoata hou.

Mena he nui te mokowhiti i roto i te paipa, ka tuhia e matou nga raraunga ki a ia ma te whakamahi tuhi(). Tawhā i_size1 i te inode (mehemea kei te putua te paipa ka taea te rite ki te 0) ka tohu te mutunga o nga raraunga kei roto. Mena he nui te waahi tuhi, ka taea e taatau te whakakii i te paipa mai i_size1 ki PIPESIZ. Na ka tukuna e matou te raka me te ngana ki te whakaoho i nga mahi e tatari ana ki te panui mai i te paipa. Ka hoki ano ki te timatanga ki te kite mena ka taea e matou te tuhi i te maha o nga paita e hiahiatia ana. Ki te rahua, katahi ka timata tatou i te huringa rekoata hou.

Ko te tikanga te tawhā i_mode Ka whakamahia te inode ki te penapena whakaaetanga r, w и x. Engari mo nga raina paipa, ka tohu maatau kei te tatari etahi mahi mo te tuhi, panui ranei ma te whakamahi i nga paraka IREAD и IWRITE ia. Ko te tukanga e whakatakoto ana i te haki me nga waea sleep(), a ko te tumanako ka puta mai etahi atu mahi a muri ake nei wakeup().

Ko te tino makutu ka tupu i roto sleep() и wakeup(). Ka whakatinanahia i roto slp.c, te puna o te korero rongonui "Kaore koe e tika kia mohio koe ki tenei". Waimarie, karekau e marama ki te waehere, titiro noa ki etahi korero:

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

Ko te tukanga e puta ai sleep() mo tetahi hongere, tera pea ka whakaohohia e tetahi atu tukanga, ka puta wakeup() mo te hongere ano. writep() и readp() ruruku i a raatau mahi ma enei waea takirua. maharatia tena pipe.c ka hoatu te kaupapa matua i nga wa katoa PPIPE ina karangahia sleep(), koia tena sleep() ka haukotia pea e te tohu.

Inaianei kei a maatau nga mea katoa kia maarama ai te mahi 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);
}

He maamaa ake pea te panui i tenei mahi mai i raro ki runga. Ko te peka "panui me te hoki mai" ka whakamahia ina he raraunga kei roto i te paipa. I tenei take, ka whakamahia e matou panui() ka panuihia e matou te nui o nga raraunga e waatea ana mai i te waa o naianei f_offset panui, ka whakahōu i te uara o te whakawhiwhinga e rite ana.

I runga i nga panui ka whai ake, ka noho kau te paipa mena kua tae te utu panui i_size1 i te inode. Ka tautuhia e matou te tuunga ki te 0 ka ngana ki te whakaoho i nga mahi e hiahia ana ki te tuhi ki te paipa. E mohio ana tatou ka ki tonu te kaikawe, writep() ka moe i runga ip+1. Inaianei kua putua te paipa, ka taea e tatou te whakaara ki te whakaara ano i tana huringa tuhi.

Mena kaore he mea hei panui, na readp() ka taea te whakarite haki IREAD a ka moe i runga ip+2. E mohio ana tatou he aha ia ka ara ake writep(), ka tuhia e ia etahi raraunga ki te paipa.

Nga korero ki readi() and writei() ka awhina koe ki te mohio ko te kore e tuku i nga tawhā ma te "u"Ka taea e taatau ki a raatau kia rite ki nga mahi I/O noa e tango ana i te konae, i te tuunga, i te putunga mahara, me te tatau i te maha o nga paita hei panui, hei tuhi ranei.

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

Mo te aukati "conservative", na readp() и writep() aukatihia te inode kia oti ra ano a raatau mahi, ka whiwhi hua ranei (ara, waea wakeup). plock() и prele() mahi noa: te whakamahi i tetahi huinga waea rereke sleep и wakeup tukua matou ki te ara ake i nga mahi e hiahia ana ki te raka i tukuna e matou:

/*
 * 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 te tuatahi kaore au i te marama he aha readp() e kore e meinga prele(ip) i mua i te karanga wakeup(ip+1). Ko te mea tuatahi writep() te take i roto i tona huringa, tenei plock(ip), e arai ana ki te kati mena readp() kaore ano kia tangohia taku poraka, no reira me mahi tika te waehere. Ki te titiro koe ki wakeup(), katahi ka maarama ko te tohu anake i te mahi moe kua reri ki te mahi, na a meake nei sched() tino whakarewahia. Na readp() nga take wakeup(), ka tango i te raka, ka tautuhi IREAD me nga waea sleep(ip+2)- enei katoa i mua writep() ka timata ano te huringa.

Ka oti te whakamaarama mo nga kaikawe i te putanga tuaono. Waehere ngawari, nga putanga tawhiti.

Putanga tuawhitu o Unix (Hanuere 1979) he whakaputanga nui hou (e wha tau i muri mai) he maha nga tono hou me nga ahuatanga kernel. He nui ano nga huringa e pa ana ki te whakamahi i te momo whakarewa, nga uniana me nga tohu tohu ki nga hanganga. Heoi ano waehere kawe tata tonu te rereke. Ka taea e tatou te peke i tenei putanga.

Xv6, he kakano rite Unix ngawari

Hei hanga i te kakano Xv6 i awehia e te putanga tuaono o Unix, engari kua tuhia ki te C hou hei whakahaere i runga i nga tukatuka x86. He ngawari te panui me te maarama te waehere. I tua atu, kaore i rite ki nga puna Unix me TUHS, ka taea e koe te whakahiato, te whakarereke, me te whakahaere i runga i tetahi mea ke atu i te PDP 11/70. No reira, e whakamahia nuitia ana tenei pata ki nga whare wananga hei rauemi ako mo nga punaha whakahaere. Nga puna kei runga i Github.

Kei roto i te waehere he whakatinanatanga maamaa me te whai whakaaro paipa.c, e tautokohia ana e te putunga i roto i te mahara hei utu mo te inode i runga i te kōpae. I konei ka tukuna e au te whakamaramatanga o te "paipa hangahanga" me te mahi 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() ka whakatakoto i te ahua o te toenga o te whakatinanatanga, kei roto ko nga mahi piperead(), pipewrite() и pipeclose(). Waea pūnaha tūturu sys_pipe he takai kei roto sysfile.c. Ka tūtohu ahau ki te panui i tana waehere katoa. Ko te matatini kei te taumata o te waehere puna o te putanga tuaono, engari he maamaa ake, he pai ake te panui.

Linux 0.01

Ka kitea te waehere puna Linux 0.01. He mea ako ki te ako i te whakatinanatanga o nga paipa i roto i a ia fs/pipe.c. Ka whakamahia he inode hei tohu i te paipa, engari ko te paipa ano kua tuhia ki te reo C hou. Mena kua mahi koe i to huarahi i roto i te waehere putanga XNUMX, kaore koe e raru i konei. Koinei te ahua o te mahi 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;
}

Ma te kore e titiro ki nga whakamaramatanga hanganga, ka taea e koe te whakaaro me pehea te whakamahi i te tatau tohutoro inode hei tirotiro mena ka puta mai he mahi tuhi. SIGPIPE. I tua atu i te mahi paita-a-paita, he ngawari tenei mahi ki te whakataurite ki nga whakaaro kua whakaahuahia i runga ake nei. Ara arorau sleep_on/wake_up e kore e tino manene.

Nga kakano Linux hou, FreeBSD, NetBSD, OpenBSD

I oma tere ahau ki etahi kakano hou. Karekau he whakamahinga kōpae i muri mai (kaore i te miharo). Kei a Linux tana ake whakatinanatanga. Ahakoa kei roto i nga kakano BSD hou e toru nga whakatinanatanga i runga i te waehere i tuhia e John Dyson, i roto i nga tau kua tino rerekee tetahi ki tetahi.

Ki te panui fs/pipe.c (i runga i te Linux) ranei sys/kern/sys_pipe.c (i runga i *BSD), me whakapau kaha. Ko te waehere o tenei ra e pa ana ki te mahi me te tautoko mo nga ahuatanga penei i te vector me te I/O tukutahi. A ko nga korero mo te tohatoha mahara, raka me te whirihoranga kernel he rereke katoa. Ehara tenei i te mea e hiahiatia ana e nga kaareti mo te akoranga punaha whakahaere.

Heoi ano, i hiahia ahau ki te keri i etahi tauira tawhito (penei i te whakaputa SIGPIPE ka hoki mai EPIPE i te wa e tuhi ana ki te paipa kati) i roto i enei momo kakano hou. Kaore pea au e kite i tetahi rorohiko PDP-11 i roto i te ao, engari he maha tonu nga mea hei ako mai i nga waehere i tuhia i nga tau i mua i taku whanautanga.

He tuhinga i tuhia e Divi Kapoor i te tau 2011:Ko te Whakatinana Kernel Linux o nga Paipa me nga FIFO" Ka whakarato i te tirohanga whanui mo te mahi paipa (tonu) i Linux. A i mahi tata nei ki Linux e whakaatu ana i te tauira paipa o te tauwhitiwhitinga, ko ona kaha i tua atu i era o nga konae rangitahi; me te whakaatu hoki i te tawhiti o nga paipa i puta mai i te "rakau tino tiaki" o te putanga tuaono o te kernel Unix.

Source: will.com

Tāpiri i te kōrero