Otu esi etinye pipeline na Unix

Otu esi etinye pipeline na Unix
Edemede a na-akọwa mmejuputa pipeline na kernel Unix. Enwere m nkụda mmụọ na otu akụkọ na nso nso a nke isiokwu ya bụ "Kedu ka pipeline si arụ ọrụ na Unix?"tụgharịrị bụghị banyere ime Ọdịdị. Abịara m ịchọ ịmata ihe ma gwuo ala n'ebe ochie ka m chọta azịza ya.

Kedu ihe anyị na-ekwu?

Pipeline, "ma eleghị anya, ihe kachasị mkpa mepụtara na Unix," bụ njirimara na-akọwapụta nkà ihe ọmụma Unix dị n'okpuru nke ijikọta obere mmemme ọnụ, yana akara ama ama na ahịrị iwu:

$ echo hello | wc -c
6

Ọrụ a dabere na oku sistemu kernel nyere pipe, nke a kọwara na ibe akwụkwọ ọkpọkọ (7) и ọkpọkọ (2):

Pipeline na-enye ọwa unidirectional maka nkwurịta okwu interprocess. Pipeline nwere ntinye (njedebe dee) na mmepụta (ngwụcha agụ). Enwere ike ịgụ data edere na ntinye nke pipeline na mmepụta.

A na-emepụta ọkpọkọ site na iji oku pipe(2), nke na-eweghachi ihe ndekọ faịlụ abụọ: otu na-ezo aka na ntinye nke pipeline, nke abụọ na mmepụta.

Nsonaazụ nsonaazụ sitere na iwu dị n'elu na-egosi okike nke pipeline na ntinye data site na ya site n'otu usoro gaa na nke ọzọ:

$ 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

Usoro nne na nna na-akpọ pipe()iji nweta ndị na-akọwa faịlụ agbakwunyere. Otu usoro nwatakịrị na-ede n'otu aka, usoro ọzọ na-agụkwa otu data site na aka ọzọ. Shei ahụ na-eji dup2 mee ka “nyegharịa aha” nkọwa 3 na 4 iji kwekọọ stdin na stdout.

Enweghị ọkpọkọ, shei ahụ ga-edepụta mmepụta nke otu usoro na faịlụ ma nyefee ya na usoro ọzọ iji gụọ data sitere na faịlụ ahụ. N'ihi ya, anyị ga-emefusị ihe onwunwe na ohere diski. Otú ọ dị, pipeline dị mma ọ bụghị nanị n'ihi na ha na-enye gị ohere izere iji faịlụ nwa oge:

Ọ bụrụ na usoro na-agbalị ịgụ site na pipeline efu mgbe ahụ read(2) ga-egbochi ruo mgbe data ga-adị. Ọ bụrụ na usoro na-agbalị ịdegara pipeline zuru ezu, mgbe ahụ write(2) ga-egbochi ruo mgbe agụchara data zuru oke site na pipeline iji dee ya.

Dị ka POSIX chọrọ, nke a bụ ihe dị mkpa: na-ede na pipeline ruo PIPE_BUF bytes (opekata mpe 512) ga-abụrịrị atomic ka usoro wee nwee ike ịkparịta ụka n'etiti ibe ha site na pipeline n'ụzọ faịlụ mgbe niile (nke na-enyeghị nkwa dị otú ahụ) enweghị ike.

Mgbe ị na-eji faịlụ oge niile, usoro nwere ike idepụta ihe niile na ya ma nyefee ya na usoro ọzọ. Ma ọ bụ usoro nwere ike ịrụ ọrụ n'ụdị ihe yiri ya nke ukwuu, na-eji usoro nrịbama mpụga (dị ka semaphore) iji mee ka ibe ha mara mgbe ederede ma ọ bụ gụchara. Ndị na-ebufe na-azọpụta anyị na nsogbu a niile.

Kedu ihe anyị na-achọ?

M ga-akọwa ya n'ụzọ dị mfe ka ọ dịrị gị mfe iche n'echiche ka ebufe nwere ike isi rụọ ọrụ. Ị ga-achọ ikenye ihe nchekwa na ụfọdụ steeti na ebe nchekwa. Ị ga-achọ ọrụ iji gbakwunye na wepụ data na nchekwa. Ị ga-achọ ụzọ ụfọdụ iji kpọọ ọrụ n'oge a na-agụ na ide ọrụ na nkọwa faịlụ. Na ị ga-achọ mkpọchi iji mejuputa omume pụrụ iche akọwara n'elu.

Ugbu a, anyị adịla njikere ịjụ koodu isi mmalite kernel n'okpuru oriọna na-egbuke egbuke iji kwado ma ọ bụ gọnarị ụdị echiche anyị na-edoghị anya. Ma na-adị njikere mgbe niile maka ihe a na-atụghị anya ya.

Ebee ka anyị na-achọ?

Amaghị m ebe akwụkwọ akụkọ a ma ama dị "Akwụkwọ ọdụm"ya na koodu isi Unix 6, mana ekele Otu Unix Heritage Society ị nwere ike ịchọ online na koodu isi mmalite ọbụna ụdị Unix ochie.

Ịgagharị na ebe nchekwa TUHS dị ka ịga ụlọ ngosi ihe mgbe ochie. Anyị nwere ike ileba anya n'akụkọ ihe mere eme anyị na-ekekọrịta, enwere m nkwanye ùgwù maka mgbalị ọtụtụ afọ agbagoro iji weghachi ihe a niile ntakịrị ntakịrị site na teepu na mbipụta ochie. Amakwa m nke ọma iberibe iberibe ihe ndị ahụ ka na-efu.

N'ịbụ onye mejuworo ọchịchọ anyị nwere banyere akụkọ ihe mere eme ochie nke ndị na-ebufe ebu, anyị nwere ike ileba anya n'ọgbọ a maka ntụnyere.

Site n'ụzọ, pipe bụ oku usoro nọmba 42 na tebụl sysent[]. Ọ dabara?

Ọdịnala Unix kernel (1970–1974)

Ahụghị m akara ọ bụla pipe(2) ọbụghị na PDP-7 Unix (Jenụwarị 1970), ma ọ bụ n'ime mbipụta mbụ nke Unix (November 1971), ma ọ bụ na koodu isi mmalite ezughị ezu mbipụta nke abụọ (June 1972).

TUHS kwuru na mbipụta nke atọ nke Unix (February 1973) ghọrọ ụdị nke mbụ nwere ndị ebu:

Unix 1973rd Edition bụ ụdị ikpeazụ nwere kernel edere n'asụsụ mgbakọ, mana ọ bụkwa ụdị nke mbụ nwere pipeline. N'ime XNUMX, a rụrụ ọrụ iji melite mbipụta nke atọ, e degharịrị kernel na C, ya mere mbipụta nke anọ nke Unix pụtara.

Otu onye na-agụ hụrụ nyocha nke akwụkwọ nke Doug McIlroy tụpụtara echiche nke "ijikọ mmemme dị ka eriri ubi."

Otu esi etinye pipeline na Unix
N'akwụkwọ Brian KernighanUnix: Akụkọ ihe mere eme na ihe ncheta", na akụkọ ihe mere eme nke mpụta nke ndị na-ebugharị, a na-akpọkwa akwụkwọ a: "... ọ kwụsịrị n'elu mgbidi n'ọfịs m na Bell Labs maka afọ 30." Ebe a ajụjụ ọnụ McIlroy, na akụkọ ọzọ si Ọrụ McIlroy, nke edere na 2014:

Mgbe Unix pụtara, mmasị m nwere na coroutines mere ka m jụọ onye odee OS, Ken Thompson, ka o kwe ka data edere na usoro ka ọ bụghị naanị na ngwaọrụ ahụ, kamakwa ịmepụta na usoro ọzọ. Ken kpebiri na ọ ga-ekwe omume. Otú ọ dị, dị ka minimalist, ọ chọrọ ka usoro ọ bụla na-arụ ọrụ na-arụ ọrụ dị mkpa. Ide ihe ozugbo n'etiti usoro ọ bụ nnukwu uru karịa ide na faịlụ etiti? Ọ bụ naanị mgbe m mere atụmatụ a kapịrị ọnụ nke nwere aha na-adọrọ adọrọ "payline" na nkọwa nke syntax maka mmekọrịta n'etiti usoro ka Ken mechara kwuo, sị: "M ga-eme ya!"

Ma mee ya. Otu mgbede dị egwu, Ken gbanwere kernel na shei, dozie ọtụtụ mmemme ọkọlọtọ iji hazie ka ha si anabata ntinye (nke nwere ike isi na pipeline), ma gbanwee aha faịlụ. N'echi ya, a malitere iji pipeline eme ihe na ngwa ngwa. Ka ọ na-erule ngwụsị izu, ndị odeakwụkwọ na-eji ha ezipụ akwụkwọ sitere na ndị na-emepụta okwu na ndị na-ebi akwụkwọ. Obere oge ka e mesịrị, Ken dochie API mbụ na syntax maka iji ọkpọkọ eme ihe na mgbakọ dị ọcha, bụ nke e jiworo mee ihe kemgbe ahụ.

N'ụzọ dị mwute, koodu isi mmalite maka mbipụta Unix kernel nke atọ efuola. Na agbanyeghị na anyị nwere koodu isi mmalite kernel edere na C mbipụta nke anọ, ewepụtara na Nọvemba 1973, mana ọ pụtara ọtụtụ ọnwa tupu mwepụta gọọmentị na enweghị mmejuputa pipeline. Ọ bụ ihe ihere na koodu isi mmalite maka ọrụ Unix a ma ama na-efunahụ ya, ikekwe ruo mgbe ebighị ebi.

Anyị nwere akwụkwọ ederede maka pipe(2) site na ntọhapụ abụọ ahụ, yabụ ị nwere ike ịmalite site na ịchọ akwụkwọ ahụ mbipụta nke atọ (maka ụfọdụ mkpụrụokwu, nke etinyere n'okpuru "iji aka", eriri nkịtị ^H, na-esochi ya!). Nke a proto-pipe(2) edere ya n'asụsụ mgbakọ wee weghachi naanị otu nkọwa faịlụ, mana enyelarị ọrụ isi a tụrụ anya ya:

Oku sistemu ọkpọkọ na-emepụta usoro ntinye/mpụta nke a na-akpọ pipeline. Enwere ike iji nkọwa faịlụ eweghachitere maka ịrụ ọrụ ọgụgụ na ide. Mgbe edere ihe na pipeline, a na-echekwa ihe ruru 504 bytes nke data, mgbe nke ahụ gasịrị, a kwụsịrị usoro ide ihe. Mgbe ị na-agụ site na pipeline, a na-ewepụ data echekwara.

Ka ọ na-erule afọ na-esote kernel ahụ edegharịrị na C, na ọkpọkọ (2) na mbipụta nke anọ nwetara ọdịdị ya nke oge a na prototype "pipe(fildes)»:

Oku sistemu ọkpọkọ na-emepụta usoro ntinye/mpụta nke a na-akpọ pipeline. Enwere ike iji nkọwa faịlụ eweghachite n'ọrụ ịgụ na ide. Mgbe a na-ede ihe na pipeline, a na-eji aka ahụ laghachi na r1 (resp. fildes [1]), na-etinye ya na 4096 bytes nke data, mgbe nke ahụ gasịrị, a kwụsịrị usoro ide ihe. Mgbe ị na-agụ site na pipeline, aka ahụ laghachiri na r0 (resp. fildes[0]) na-ewe data ahụ.

A na-eche na ozugbo a kọwapụtara pipeline, usoro nkwurịta okwu abụọ (ma ọ bụ karịa) (nke a na-akpọ oku na-esote). ndụdụ) ga-ebufe data site na pipeline site na iji oku agụ и dee.

Shei ahụ nwere syntax maka ịkọwapụta usoro ahịrị ahịrị nke usoro ejikọrọ na pipeline.

Oku ka ịgụọ site na pipeline efu (enweghị data echekwara) nke nwere naanị otu njedebe (emechiri ihe nkọwa faịlụ ederede niile) weghachi "njedebe faịlụ". A na-eleghara oku iji dee n'ọnọdụ yiri nke ahụ.

Nke mbụ mmejuputa pipeline echekwara akọ ruo mbipụta nke ise nke Unix (June 1974), mana ọ fọrọ nke nta ka ọ dị ka nke pụtara na ntọhapụ na-esote. Agbakwunyela nkọwa, yabụ ị nwere ike ịwụpụ mbipụta nke ise.

mbipụta nke isii nke Unix (1975)

Ka anyị malite ịgụ koodu isi mmalite Unix mbipụta nke isii (Mee 1975). Ọtụtụ ekele maka ọdum ọ dị mfe ịchọta karịa isi mmalite nke nsụgharị mbụ:

Ọtụtụ afọ akwụkwọ ọdum bụ naanị akwụkwọ dị na Unix kernel dị na mpụga Bell Labs. Ọ bụ ezie na akwụkwọ ikike mbipụta nke isii nyere ndị nkụzi ohere iji koodu isi mmalite ya, akwụkwọ ikike mbipụta nke asaa wepụrụ ohere a, n'ihi ya, a na-ekesa akwụkwọ ahụ n'ụdị mpempe akwụkwọ na-akwadoghị.

Taa ị nwere ike ịzụta mbipụta nke akwụkwọ ahụ, nke mkpuchi ya na-egosi ụmụ akwụkwọ na igwe oyiri. Na ekele Warren Toomey (onye malitere ọrụ TUHS) ị nwere ike ibudata PDF faịlụ nwere koodu isi mmalite maka mbipụta nke isii. Achọrọ m ịnye gị echiche nke mgbalị siri ike na ịmepụta faịlụ ahụ:

Ihe karịrị afọ 15 gara aga, pịnyere m otu koodu isi mmalite enyere ọdum, n'ihi na àgwà nke mbipụta m enweghị mmasị na ọnụọgụ ndị ọzọ amaghị. TUHS adịbeghị ma enweghị m ohere ịnweta isi mmalite ochie. Mana na 1988, ahụrụ m teepu ochie nke nwere ihe ndabere sitere na kọmputa PDP9. O siri ike ịmata ma ọ na-arụ ọrụ, ma e nwere osisi / usr / src / osisi na-adịghị emebi emebi nke a na-akpọ ọtụtụ faịlụ na afọ 11, nke ọbụna dị ka oge ochie. Ọ bụ mbipụta nke asaa ma ọ bụ PWB ewepụtara ya, dịka m kwenyere.

Eji m nchọta ahụ dị ka ntọala wee jiri aka dezie isi mmalite na mbipụta nke isii. Ụfọdụ n'ime koodu ahụ ka dị otu, mana ụfọdụ kwesịrị idezi ntakịrị, na-agbanwe akara ngosi += ọgbara ọhụrụ ka ọ bụrụ nke ochie =+. Ụfọdụ ihe ka ehichapụrụ, ma ụfọdụ ga-edegharị ya kpamkpam, mana ọ bụghị nke ukwuu.

Ma taa, anyị nwere ike ịgụ online na TUHS koodu isi iyi nke mbipụta nke isii si Archive, nke Dennis Ritchie nwere aka.

Site n'ụzọ, na nlele mbụ, akụkụ bụ isi nke koodu C tupu oge Kernighan na Ritchie bụ ya. nkenke. Ọ bụghị mgbe niile ka m na-enwe ike itinye mpempe koodu na-enweghị nnukwu edezi ka ọ dabara ebe ngosi dị warara na saịtị m.

Na mbido /usr/sys/ken/pipe.c enwere nkọwa nkọwa (na ee, enwere karịa /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

Ogo nchekwa ahụ agbanwebeghị kemgbe mbipụta nke anọ. Mana ebe a, anyị na-ahụ, na-enweghị akwụkwọ ọhaneze ọ bụla, na pipeline otu oge ejiri faịlụ dịka nchekwa nchekwa!

Maka faịlụ LARG, ha na-edekọrịta ọkọlọtọ inode LARG, nke "nnukwu okwu algọridim" na-eji hazie blocks na-apụtaghị ìhè iji kwado sistemụ faịlụ buru ibu. Ebe Ken kwuru na ọ ka mma ịghara iji ha mee ihe, m ga-eji obi ụtọ were okwu ya mee ihe.

Nke a bụ ezigbo oku sistemụ 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;
}

Nkwupụta ahụ na-akọwa nke ọma ihe na-eme ebe a. Mana ịghọta koodu ahụ adịghị mfe, akụkụ ụfọdụ n'ihi ụzọ ahụ "struct onye ọrụ u» na ndekọ R0 и R1 Sistemu oku parampat na nloghachi ụkpụrụ na-agafere.

Ka anyị nwaa ya ialloc() tinye diski inode (aka index), na site n'enyemaka falloc() - tinye abụọ na ebe nchekwa faịlụ. Ọ bụrụ na ihe niile na-aga nke ọma, anyị ga-edobe ọkọlọtọ iji mata faịlụ ndị a dị ka nsọtụ abụọ nke pipeline, tụọ ha n'otu inode (nke a ga-edobe ọnụ ọgụgụ ntụaka ya na 2), ma kaa inode dị ka gbanwetụrụ na iji ya. Lezienụ anya na arịrịọ ike () n'ụzọ njehie iji belata ọnụ ọgụgụ ntụaka na inode ọhụrụ.

pipe() ga-esi na ya R0 и R1 laghachi nọmba nkọwa faịlụ maka ịgụ na ide. falloc() weghachi ihe ntụnye aka na nhazi faịlụ, mana ọ na-alaghachikwa site na u.u_ar0[R0] na onye na-akọwa faịlụ. Ya bụ, koodu na-echekwa na r onye na-akọwa faịlụ maka ịgụ ma nyefee onye na-akọwa faịlụ maka ide ozugbo site na u.u_ar0[R0] mgbe oku nke abụọ gachara falloc().

Flag FPIPE, nke anyị na-edozi mgbe ị na-emepụta pipeline, na-achịkwa omume nke ọrụ ahụ rdwr () na sys2.cịkpọ usoro I/O kpọmkwem:

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

Mgbe ahụ ọrụ readp() в pipe.c na-agụ data sitere na pipeline. Ma ọ ka mma ịchọta mmejuputa iwu na-amalite writep(). Ọzọ, koodu ahụ aghọwo ihe mgbagwoju anya n'ihi nkwekọrịta nke arụmụka na-agafe agafe, mana enwere ike ịhapụ nkọwa ụfọdụ.

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

Anyị chọrọ ide bytes na ntinye pipeline u.u_count. Mbụ anyị kwesịrị igbachi inode (lee n'okpuru plock/prele).

Mgbe ahụ, anyị na-elele counter inode. Ọ bụrụhaala na njedebe abụọ nke pipeline na-emeghe, counter kwesịrị ịdị nhata 2. Anyị na-ejide otu njikọ (site na rp->f_inode), ya mere, ọ bụrụ na counter na-erughị 2, ọ ghaghị ịpụta na usoro ọgụgụ ahụ emechiwo njedebe nke pipeline. N'ikwu ya n'ụzọ ọzọ, anyị na-agbalị ịdegara pipeline mechiri emechi, nke a bụkwa njehie. Koodu njehie oge mbụ EPIPE na mgbama SIGPIPE pụtara na mbipụta nke isii nke Unix.

Mana ọ bụrụgodị na ebufe emeghere, ọ nwere ike ju. N'okwu a, anyị na-ahapụ mkpọchi ahụ wee hie ụra na-atụ anya na usoro ọzọ ga-agụ site na pipeline ma hapụ ohere zuru ezu na ya. Mgbe anyị tetara n'ụra, anyị na-alaghachi na mmalite, kwụgidere mkpọchi ọzọ wee malite usoro ndekọ ọhụrụ.

Ọ bụrụ na enwere ohere zuru oke na pipeline, mgbe ahụ, anyị na-eji ya ede data na ya dere()... Oke i_size1 inode (ọ bụrụ na ọkpọkọ ahụ tọgbọ chakoo, ọ nwere ike ha nhata 0) na-egosi njedebe nke data nke o nwere. Ọ bụrụ na enwere ohere ndekọ zuru oke, anyị nwere ike mejupụta pipeline site na i_size1 ka PIPESIZ. Mgbe ahụ, anyị na-ahapụ mkpọchi ahụ ma gbalịa ịkpọte usoro ọ bụla na-echere ịgụ site na pipeline. Anyị na-alaghachi na mmalite iji hụ ma anyị nwere ike ide ọtụtụ bytes dị ka anyị chọrọ. Ọ bụrụ na ọ daa, mgbe ahụ anyị na-amalite usoro ndekọ ndekọ ọhụrụ.

Na-emekarị oke i_mode a na-eji inode chekwaa ikike r, w и x. Ma n'ihe gbasara pipeline, anyị na-egosi na ụfọdụ usoro na-echere ka e dee ma ọ bụ gụọ site na iji bits IREAD и IWRITE n'otu n'otu. Usoro na-esetịpụ ọkọlọtọ na oku sleep(), na a na-atụ anya na ụfọdụ usoro ọzọ n'ọdịnihu ga-akpata wakeup().

Ezi anwansi na-eme na sleep() и wakeup(). A na-emejuputa ha na slp.c, isi iyi nke okwu a ma ama "Ị naghị atụ anya ịghọta nke a". Ọ dabara nke ọma, anyị agaghị aghọta koodu ahụ, lelee ụfọdụ okwu:

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

Usoro nke na-akpata sleep() maka otu ọwa, enwere ike ịkpọte ya site na usoro ọzọ, nke ga-akpata wakeup() maka otu ọwa. writep() и readp() hazie omume ha site na oku ejikọtara ọnụ. rụba nke ahụ ama pipe.c mgbe niile na-enye ụzọ PPIPE mgbe a na-akpọ ya sleep(), yabụ ọ bụ ya sleep() enwere ike ịkwụsị site na mgbama.

Ugbu a, anyị nwere ihe niile iji ghọta ọrụ ahụ 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);
}

Ị nwere ike ịhụ na ọ dịrị gị mfe ịgụ ọrụ a site na ala ruo n'elu. A na-ejikarị ngalaba "gụọ na nloghachi" mgbe enwere ụfọdụ data na pipeline. N'okwu a, anyị na-eji readi() anyị na-agụ ọtụtụ data dị na-amalite site na nke ugbu a f_offset ịgụ, wee melite uru nke nkwụghachi kwekọrọ.

Na agụ ndị na-esote, pipeline ga-atọgbọ chakoo ma ọ bụrụ na nkwụghachi nke ọgụgụ eruola i_size1 na inode. Anyị na-edozi ọnọdụ ahụ na 0 ma gbalịa ịkpọte usoro ọ bụla chọrọ ide na pipeline. Anyị maara na mgbe ebufe zuru oke, writep() ga-ada n'ụra ip+1. Ma ugbu a na pipeline tọgbọrọ chakoo, anyị nwere ike ịkpọte ya ka ọ maliteghachi usoro ihe odide ya.

Ọ bụrụ na ị nweghị ihe ịgụ, mgbe ahụ readp() nwere ike ịtọ ọkọlọtọ IREAD ma daa n'ụra ip+2. Anyị maara ihe ga-akpọte ya writep(), mgbe ọ na-ede ụfọdụ data na pipeline.

Azịza nye readi () na writei() ga-enyere gị aka ịghọta na kama ịgafe parameters site na "u"Anyị nwere ike na-emeso ha dị ka ọrụ I/O nkịtị na-ewere faịlụ, ọnọdụ, ihe nchekwa na ebe nchekwa, ma gụọ ọnụọgụ bytes ka ịgụ ma ọ bụ dee.

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

N'ihe gbasara igbochi "conservative", mgbe ahụ readp() и writep() gbochie inode ruo mgbe ha rụchara ọrụ ha ma ọ bụ nweta nsonaazụ (ya bụ, kpọọ wakeup). plock() и prele() rụọ ọrụ nke ọma: iji usoro oku dị iche sleep и wakeup nye anyị ohere ịkpọte usoro ọ bụla chọrọ mkpọchi nke anyị wepụtara ugbu a:

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

Na mbụ, aghọtaghị m ihe kpatara ya readp() adịghị akpata prele(ip) tupu oku a wakeup(ip+1). Ihe mbụ bụ writep() na-akpata na okirikiri ya, nke a plock(ip), nke na-eduga n'ịkwụ ụgwọ ma ọ bụrụ readp() ewepụbeghị ngọngọ m, yabụ n'ụzọ ụfọdụ koodu ahụ ga-arụ ọrụ nke ọma. Ọ bụrụ na ị na-ele anya wakeup(), Mgbe ahụ, ọ ga-edo anya na ọ bụ naanị akara usoro ihi ụra dị njikere ime, nke mere na n'ọdịnihu sched() n'ezie ulo oru ya. Ya mere readp() akpata wakeup(), na-ewepu mkpọchi, setịpụ IREAD na oku sleep(ip+2)- ihe a niile tupu writep() maliteghachi okirikiri.

Nke a mezuru nkọwa nke ndị na-ebugharị na mbipụta nke isii. Koodu dị mfe, nsonaazụ dị oke egwu.

mbipụta nke asaa nke Unix (January 1979) bụ nnukwu mwepụta ọhụrụ (afọ anọ ka e mesịrị) nke webatara ọtụtụ ngwa ọhụrụ na njirimara kernel. Ọ mekwara mgbanwe dị ukwuu n'ihe gbasara iji ụdị nkedo, otu na ihe nrịbama pịnye n'ihe owuwu. Agbanyeghị nnyefe koodu ihe agbanwebeghị. Anyị nwere ike ịwụpụ mbipụta a.

Xv6, kernel dị mfe dịka Unix

Iji mepụta kernel Xv6 na-emetụta mbipụta nke isii nke Unix, mana edere ya na C ọgbara ọhụrụ ka ọ na-agba ọsọ na x86 processors. Koodu dị mfe ịgụ na nghọta. Na mgbakwunye, n'adịghị ka isi mmalite Unix nwere TUHS, ị nwere ike chịkọta ya, gbanwee ya, wee mee ya n'ihe na-abụghị PDP 11/70. Ya mere, a na-eji kernel a na mahadum dị ka ihe mmụta na sistemụ arụmọrụ. Isi mmalite dị na Github.

Koodu ahụ nwere mmejuputa doro anya na nke echebara echiche ọkpọkọ.c, kwadoro site na nchekwa nchekwa kama inode na diski. N'ebe a, m na-enye naanị nkọwa nke "pipeline" na ọrụ ahụ 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() na-esetịpụ ọnọdụ nke ndị ọzọ nke mmejuputa iwu, nke gụnyere ọrụ piperead(), pipewrite() и pipeclose(). Oku sistemu n'ezie sys_pipe bụ ihe mkpuchi etinyere na sysfile.c. Ana m akwado ịgụ koodu ya niile. Ihe mgbagwoju anya dị na ọkwa nke koodu isi mmalite nke mbipụta nke isii, ma ọ dị mfe ma na-atọ ụtọ karịa ịgụ.

Linux 0.01

Enwere ike ịchọta koodu isi iyi Linux 0.01. Ọ ga-abụ ihe mmụta iji mụọ mmejuputa pipelines na ya fs/pipe.c. Nke a na-eji inode na-anọchi anya pipeline, ma pipeline n'onwe ya ka edere na nke oge a C. Ọ bụrụ na ị na-arụ ọrụ gị site na koodu mbipụta nke 6, ị gaghị enwe nsogbu ebe a. Nke a bụ ihe ọrụ ahụ dị ka 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;
}

Ọbụlagodi na-elele nkọwa nhazi, ị nwere ike ịchọpụta ka esi eji ọnụ ọgụgụ inode iji lelee ma ọrụ ide ọ rụpụtara. SIGPIPE. Na mgbakwunye na ịrụ ọrụ byte-byte, ọrụ a dị mfe iji tụnyere echiche ndị akọwapụtara n'elu. Ọbụna mgbagha sleep_on/wake_up adịghị anya otú ọbịa.

Mkpụrụ ndụ Linux ọgbara ọhụrụ, FreeBSD, NetBSD, OpenBSD

M ngwa ngwa gafere ụfọdụ kernel ọgbara ọhụrụ. Ọ dịghị nke ọ bụla n'ime ha nwere mmejuputa diski ọzọ (ọ bụghị ihe ijuanya). Linux nwere mmejuputa ya. Ọ bụ ezie na mkpụrụ ndụ BSD atọ nke ọgbara ọhụrụ nwere mmejuputa iwu dabere na koodu nke John Dyson dere, n'ime afọ ha adịla iche na ibe ha.

Ịgụ fs/pipe.c (na Linux) ma ọ bụ sys/kern/sys_pipe.c (na *BSD), ọ na-achọ ezigbo nraranye. Koodu nke taa bụ maka arụmọrụ yana nkwado maka njirimara dịka vector na I/O asynchronous. Na nkọwa nke oke ebe nchekwa, mkpọchi na nhazi kernel niile dịgasị iche iche. Nke a abụghị ihe kọleji chọrọ maka nkuzi sistemụ arụmọrụ mmalite.

Agbanyeghị, enwere m mmasị igwupụta ụfọdụ ụkpụrụ ochie (dị ka imepụta SIGPIPE ma laghachi EPIPE mgbe ị na-ede na pipeline mechiri emechi) n'ime kernel ndị a niile dị iche iche nke oge a. Agaghị m ahụ kọmputa PDP-11 na ndụ n'ezie, mana a ka nwere ọtụtụ ihe m ga-amụta na koodu e dere ọtụtụ afọ tupu a mụọ m.

Edemede nke Divi Kapoor dere na 2011:Ntinye Linux Kernel nke Pipes na FIFOs" na-enye nkọwa nke ka pipeline (ka) si arụ ọrụ na Linux. A emere n'oge na-adịbeghị anya na Linux na-egosipụta ụdị pipeline nke mmekọrịta, nke ike ya karịrị nke faịlụ nwa oge; ma gosikwa etu pipeline siri bịa na "mkpọchi nke ukwuu" nke mbipụta Unix kernel nke isii.

isi: www.habr.com

Tinye a comment