Momwe mapaipi amagwiritsidwira ntchito ku Unix

Momwe mapaipi amagwiritsidwira ntchito ku Unix
Nkhaniyi ikufotokoza kukhazikitsidwa kwa mapaipi mu Unix kernel. Ndinakhumudwa pang'ono ndi nkhani yaposachedwa yamutu wakuti "Kodi mapaipi amagwira ntchito bwanji ku Unix?"zinatheka osati za kapangidwe ka mkati. Ndinachita chidwi kwambiri ndi kufufuza zinthu zakale kuti ndipeze yankho.

Kodi tikukamba za chiyani?

Mapaipi, "mwina chinthu chofunikira kwambiri ku Unix," ndi chizindikiritso cha filosofi ya Unix yolumikiza mapulogalamu ang'onoang'ono pamodzi, komanso chizindikiro chodziwika pamzere wolamula:

$ echo hello | wc -c
6

Kuchita uku kumatengera kuyimba komwe kumaperekedwa ndi kernel pipe, zomwe zafotokozedwa pamasamba olembedwa pipa (7) ΠΈ pipa (2):

Mapaipi amapereka njira imodzi yokha yolumikizirana. Chitolirocho chimakhala ndi zolowetsa (lemba kumapeto) ndi zotuluka (werengani kumapeto). Deta yolembedwa polowetsa payipi imatha kuwerengedwa pazotulutsa.

Njirayi imapangidwa pogwiritsa ntchito kuyimba pipe(2), yomwe imabweretsanso zofotokozera ziwiri za fayilo: imodzi ikunena za kulowetsa kwa payipi, yachiwiri ku zotsatira zake.

Zomwe zimatuluka kuchokera ku lamulo ili pamwambazi zikuwonetsa kupangidwa kwa payipi ndi kutuluka kwa deta kudzera mu njira imodzi kupita ku ina:

$ 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

Njira ya makolo imayimba pipe()kuti mupeze zofotokozera za fayilo. Njira imodzi ya mwana imalembera ku chogwirira chimodzi, ndipo njira ina imawerengera zomwezo kuchokera ku chogwirira china. Chipolopolocho chimagwiritsa ntchito dup2 "kutchulanso" zofotokozera 3 ndi 4 kuti zigwirizane ndi stdin ndi stdout.

Popanda mapaipi, chipolopolocho chiyenera kulemba zotsatira za ndondomeko imodzi ku fayilo ndikuyipereka ku ndondomeko ina kuti muwerenge zomwe zili mu fayilo. Zotsatira zake, titha kutaya zinthu zambiri komanso malo a disk. Komabe, mapaipi ndi abwino osati chifukwa amakulolani kupewa kugwiritsa ntchito mafayilo osakhalitsa:

Ngati ndondomeko ikuyesera kuwerenga kuchokera paipi yopanda kanthu ndiye read(2) adzatsekereza mpaka deta ipezeke. Ngati ndondomeko ikuyesera kulembera payipi yonse, ndiye write(2) adzatsekereza mpaka deta yokwanira yawerengedwa kuchokera paipi kuti ilembe.

Monga chofunikira cha POSIX, ichi ndi chinthu chofunikira: kulembera mapaipi mpaka PIPE_BUF ma byte (osachepera 512) ayenera kukhala atomiki kuti njira zizitha kulumikizana wina ndi mnzake kudzera papaipi momwe mafayilo okhazikika (omwe sapereka zitsimikizo) sangathe.

Mukamagwiritsa ntchito fayilo yokhazikika, njira imatha kulemba zonse zomwe zatulutsidwa ndikuzipereka kunjira ina. Kapena njira zimatha kugwira ntchito mofanana kwambiri, pogwiritsa ntchito njira yowonetsera kunja (monga semaphore) kuti azidziwitsana pamene kulemba kapena kuwerenga kwatha. Ma conveyor amatipulumutsa ku zovuta zonsezi.

Kodi tikuyang'ana chiyani?

Ndikufotokozerani m'mawu osavuta kuti zikhale zosavuta kuti muganizire momwe conveyor angagwire ntchito. Muyenera kugawa buffer ndi malo ena kukumbukira. Mudzafunika ntchito kuti muwonjezere ndi kuchotsa deta mu buffer. Mudzafunika njira zina zoyimbira ntchito panthawi yowerenga ndi kulemba pamafayilo ofotokozera. Ndipo mudzafunika maloko kuti mugwiritse ntchito njira yapadera yomwe tafotokozayi.

Tsopano ndife okonzeka kufunsa kachidindo kochokera ku kernel pansi pa nyali yowala kuti titsimikizire kapena kutsutsa chitsanzo chathu chosamveka bwino chamalingaliro. Koma nthawi zonse khalani okonzeka kukumana ndi zomwe simukuziyembekezera.

Tikuyang'ana kuti?

Sindikudziwa komwe buku langa lodziwika bwino liri "Lions buku"ndi Unix 6 code code, koma chifukwa Unix Heritage Society mukhoza kufufuza pa intaneti pa source kodi ngakhale mitundu yakale ya Unix.

Kuyendayenda m'malo osungiramo zakale a TUHS kuli ngati kuyendera nyumba yosungiramo zinthu zakale. Titha kuyang'ana mbiri yathu yomwe tagawana, ndipo ndikulemekeza zaka zambiri zoyesayesa kuti ndipezenso zinthu zonsezi pang'onopang'ono kuchokera pamatepi akale ndi zisindikizo. Ndipo ndikudziwa bwino za zidutswa zomwe zikusowabe.

Popeza takhutitsa chidwi chathu chofuna kudziwa mbiri yakale ya ma conveyor, titha kuyang'ana maso amakono kuti tiyerekeze.

Mwa njira, pipe ndi system call number 42 patebulo sysent[]. Mwangozi?

Nkhokwe Zachikhalidwe za Unix (1970-1974)

Sindinapeze zotsatila pipe(2) ngakhale mu PDP-7 Unix (Januware 1970), kapena mu kope loyamba la Unix (November 1971), kapena mu code yosakwanira kope lachiwiri (June 1972).

TUHS ikunena kuti kope lachitatu la Unix (February 1973) idakhala mtundu woyamba wokhala ndi ma conveyors:

Unix 1973rd Edition inali mtundu womaliza wokhala ndi kernel yolembedwa m'chilankhulo cha msonkhano, komanso mtundu woyamba wokhala ndi mapaipi. M'chaka cha XNUMX, ntchito yokonza kope lachitatu lidachitika, kernel inalembedwanso mu C, ndipo kope lachinayi la Unix linawonekera.

Wowerenga wina adapeza jambulani chikalata chomwe Doug McIlroy adapereka lingaliro la "kulumikiza mapulogalamu ngati payipi yamunda."

Momwe mapaipi amagwiritsidwira ntchito ku Unix
M'buku la Brian KernighanUnix: Mbiri ndi Memoir", m'mbiri ya kutuluka kwa ma conveyors, chikalata ichi chimatchulidwanso: "... chinapachikidwa pakhoma muofesi yanga ku Bell Labs kwa zaka 30." Pano kuyankhulana ndi McIlroy, ndi nkhani ina yochokera Ntchito ya McIlroy, yolembedwa mu 2014:

Unix itatuluka, chidwi changa ndi ma coroutines chinandichititsa kufunsa wolemba OS, Ken Thompson, kuti alole deta yolembedwa ku ndondomeko kuti ipite osati ku chipangizo chokha, komanso kuti itulutse njira ina. Ken anaganiza kuti n’zotheka. Komabe, monga minimalist, adafuna kuti machitidwe aliwonse azigwira ntchito yayikulu. Kodi kulemba mwachindunji pakati pa njira ndi mwayi waukulu polembera fayilo yapakatikati? Ndipamene ndinapanga lingaliro lachindunji ndi dzina lochititsa chidwi la "paipi" ndi kufotokoza kwa mawu ogwirizana pakati pa njira zomwe Ken potsiriza anafuula kuti: "Ndichita!"

Ndipo anatero. Usiku wina watsoka, Ken anasintha kernel ndi chipolopolo, anakonza mapulogalamu angapo okhazikika kuti agwirizane ndi momwe amavomerezera kulowetsa (zomwe zingabwere kuchokera ku pipeline), komanso kusintha mayina a mafayilo. Tsiku lotsatira, mapaipi anayamba kugwiritsidwa ntchito mofala kwambiri pa ntchito. Pofika kumapeto kwa mlunguwo, alembi anali kuwagwiritsa ntchito potumiza zikalata kuchokera ku makina osindikizira mawu kupita ku makina osindikizira. Patapita nthawi, Ken anasintha API ndi syntax yoyambirira kuti atseke kugwiritsa ntchito mapaipi ndi misonkhano yoyeretsa, yomwe yakhala ikugwiritsidwa ntchito kuyambira pamenepo.

Tsoka ilo, code code ya mtundu wachitatu wa Unix kernel yatayika. Ndipo ngakhale tili ndi kernel source code yolembedwa mu C kope lachinayi, yomwe idatulutsidwa mu Novembala 1973, koma idatuluka miyezi ingapo isanatulutsidwe ndipo ilibe kukhazikitsa mapaipi. Ndizochititsa manyazi kuti gwero lachidziwitso cha ntchito yodziwika bwino ya Unix yatayika, mwina kwamuyaya.

Tili ndi zolemba za pipe(2) kuchokera ku zotulutsidwa zonse ziwiri, kotero mutha kuyamba ndikusaka zolembazo kope lachitatu (m'mawu ena, olembedwa pansi "pamanja", mndandanda wa zilembo zenizeni ^H, zotsatiridwa ndi msindi!). Izi proto-pipe(2) imalembedwa m'chinenero chophatikizira ndipo imabweretsanso fayilo imodzi yokha yofotokozera, koma imapereka kale zofunikira zomwe zikuyembekezeredwa:

Kuitana kwadongosolo chitoliro imapanga njira yolowera/zotulutsa yotchedwa pipeline. Mafotokozedwe a fayilo omwe abwezedwa angagwiritsidwe ntchito powerenga ndi kulemba. Chinachake chikalembedwa pamapaipi, mpaka ma byte 504 a data amasungidwa, kenako ntchito yolemba imayimitsidwa. Powerenga paipi, deta yosungidwa imachotsedwa.

Pofika chaka chotsatira kernel inali italembedwanso mu C, ndipo chitoliro(2) m’kope lachinayi adapeza mawonekedwe ake amakono ndi prototype "pipe(fildes)Β»:

Kuitana kwadongosolo chitoliro imapanga njira yolowera/zotulutsa yotchedwa pipeline. Zofotokozera za fayilo zomwe zabwezedwa zitha kugwiritsidwa ntchito powerenga ndi kulemba. Chinachake chikalembedwa ku payipi, chogwiririra chomwe chabwezedwa mu r1 (resp. fildes[1]) chimagwiritsidwa ntchito, chosungidwa mpaka ma 4096 bytes a data, pambuyo pake kulembako kuyimitsidwa. Powerenga kuchokera papaipi, chogwiriracho chinabwerera ku r0 (resp. fildes[0]) chimatenga deta.

Zimaganiziridwa kuti payipi ikafotokozedwa, njira ziwiri (kapena zochulukirapo) zoyankhulirana (zopangidwa ndi kuyitana kotsatira Foloko) adzasamutsa deta kuchokera paipiyo pogwiritsa ntchito mafoni werengani ΠΈ kulemba.

Chigobacho chili ndi mawu ofotokozera mizere yolumikizana ndi mapaipi.

Mafoni oti muwerenge kuchokera papaipi yopanda kanthu (yopanda deta yosungidwa) yomwe ili ndi mapeto amodzi (zofotokozera zonse zolembera zatsekedwa) bweretsani "mapeto a fayilo". Maitanidwe olembera mumkhalidwe wofananawo amanyalanyazidwa.

Poyamba kusungidwa kwa mapaipi zimagwira mpaka ku mtundu wachisanu wa Unix (June 1974), koma ili pafupifupi yofanana ndi yomwe inatuluka m’chitsanzo chotsatira. Ndemanga zawonjezedwa kumene, kotero mutha kudumpha kusindikiza kwachisanu.

Kusindikiza kwachisanu ndi chimodzi kwa Unix (1975)

Tiyeni tiyambe kuwerenga Unix source code kope lachisanu ndi chimodzi (May 1975). Zikomo kwambiri chifukwa Mikango ndikosavuta kupeza kuposa magwero amitundu yakale:

Kwa zaka zambiri bukuli Mikango chinali chikalata chokhacho pa Unix kernel yomwe ikupezeka kunja kwa Bell Labs. Ngakhale kuti laisensi ya kope lachisanu ndi chimodzi inalola aphunzitsi kugwiritsira ntchito code code yake, laisensi ya kope lachisanu ndi chiwiri silinaphatikizepo zimenezi, motero bukulo linagaΕ΅iridwa m’makope olembedwa mwachisawawa.

Lero mutha kugula kusindikizidwanso kwa bukhuli, chikuto chake chomwe chikuwonetsa ophunzira pamakina amakope. Ndipo chifukwa cha Warren Toomey (yemwe adayambitsa pulojekiti ya TUHS) mutha kutsitsa Fayilo ya PDF yokhala ndi code source ya kope lachisanu ndi chimodzi. Ndikufuna ndikupatseni lingaliro la kuchuluka kwa zomwe zidachitika popanga fayilo:

Zaka zoposa 15 zapitazo, ndinalemba kopi ya code code yomwe inaperekedwa Mikango, chifukwa sindinakonde mtundu wa kope langa kuchokera ku nambala yosadziwika ya makope ena. TUHS panalibe pano ndipo ndinalibe mwayi wopeza magwero akale. Koma mu 1988, ndinapeza tepi yakale ya 9-track yomwe inali ndi zosunga zobwezeretsera kuchokera pa kompyuta ya PDP11. Zinali zovuta kudziwa ngati zikugwira ntchito, koma panali mtengo / usr / src/ mtengo womwe mafayilo ambiri adalembedwa ndi chaka cha 1979, chomwe chinkawoneka ngati chakale. Linali kope lachisanu ndi chiwiri kapena lochokera ku PWB, monga ndimakhulupirira.

Ndinatenga zopezazo ngati maziko ndikusintha pamanja magwero a kope lachisanu ndi chimodzi. Ma code ena adakhalabe ofanana, koma ena adayenera kusinthidwa pang'ono, kusintha chizindikiro chamakono += kukhala chachikale =+. Zinthu zina zidangochotsedwa, ndipo zina zidayenera kulembedwanso, koma osati mochulukira.

Ndipo lero titha kuwerenga pa intaneti pa TUHS code source ya kope lachisanu ndi chimodzi kuchokera archive, pomwe Dennis Ritchie anali ndi dzanja.

Mwa njira, poyang'ana koyamba, mbali yayikulu ya C-code isanafike nthawi ya Kernighan ndi Ritchie ndi yake. mwachidule. Sikuti nthawi zambiri ndimatha kuyika zidutswa za code popanda kusintha kwambiri kuti zigwirizane ndi malo ocheperako patsamba langa.

Kumayambiriro /usr/sys/ken/pipe.c pali ndemanga yofotokozera (ndipo inde, pali zambiri /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

Kukula kwa bafa sikunasinthe kuyambira kusindikiza kwachinayi. Koma apa tikuwona, popanda zolemba zapagulu, kuti mapaipi adagwiritsapo ntchito mafayilo ngati zosunga zobwezeretsera!

Ponena za mafayilo a LARG, amafanana ndi inode mbendera LARG, yomwe imagwiritsidwa ntchito ndi "algorithm yayikulu yolumikizira" kukonza midadada yosalunjika kuthandizira ma fayilo akuluakulu. Popeza kuti Ken ananena kuti ndi bwino kusawagwiritsa ntchito, ndimvera mawu ake mosangalala.

Nayi kuyimba kwadongosolo kwenikweni 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;
}

Ndemangayi ikufotokoza momveka bwino zomwe zikuchitika pano. Koma kumvetsetsa kachidindo sikophweka, mwa zina chifukwa cha njira "khazikitsa wogwiritsa uΒ»ndi zolembetsa R0 ΠΈ R1 ma parameters oyimba dongosolo ndi zobwerera zimadutsa.

Tiyeni tiyese ndi zonse () kuyika pa disk inode (index handle), ndi chithandizo falloc () - ikani awiri mu kukumbukira fayilo. Ngati zonse zikuyenda bwino, tidzayika mbendera kuti tizindikire mafayilowa ngati malekezero awiri a payipi, kuwalozera ku inode yomweyi (yomwe chiwerengero chake chidzakhazikitsidwa ku 2), ndikuyika chizindikiro kuti chasinthidwa ndikugwiritsidwa ntchito. Samalani zopempha ipe () m'njira zolakwika kuti muchepetse chiwerengero cha zolembera mu inode yatsopano.

pipe() ayenera kudutsa R0 ΠΈ R1 bweretsani manambala ofotokozera mafayilo kuti muwerenge ndi kulemba. falloc() imabweretsanso cholozera pamafayilo, komanso "kubwerera" kudzera u.u_ar0[R0] ndi fayilo yofotokozera. Ndiye kuti, code imasunga mkati r chofotokozera fayilo kuti muwerenge ndikugawa fayilo yofotokozera kuti mulembe mwachindunji kuchokera u.u_ar0[R0] itayitananso kachiwiri falloc().

Sakanizani FPIPE, zomwe timayika popanga payipi, zimayendetsa khalidwe la ntchitoyo rdwr () mu sys2.ckuyitanira machitidwe a I/O:

/*
 * common code for read and write calls:
 * check permissions, set base, count, and offset,
 * and switch out to readi, writei, or pipe code.
 */
rdwr(mode)
{
    register *fp, m;

    m = mode;
    fp = getf(u.u_ar0[R0]);
        /* … */

    if(fp->f_flag&FPIPE) {
        if(m==FREAD)
            readp(fp); else
            writep(fp);
    }
        /* … */
}

Ndiye ntchito readp() Π² pipe.c amawerenga deta kuchokera ku pipeline. Koma ndi bwino kutsatira ndondomeko kuyambira pachiyambi writep(). Apanso, codeyo yakhala yovuta kwambiri chifukwa cha mikangano yodutsana, koma zina zikhoza kuchotsedwa.

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

Tikufuna kulemba ma byte kuti alowetse mapaipi u.u_count. Choyamba tiyenera kutseka inode (onani pansipa plock/prele).

Kenako timayang'ana kauntala ya inode. Malingana ngati malekezero onse a payipi amakhala otseguka, kauntala iyenera kukhala yofanana ndi 2. Timagwira ulalo umodzi (kuchokera rp->f_inode), kotero ngati kauntala ndi yocheperapo 2, ziyenera kutanthauza kuti ndondomeko yowerengera yatseka mapeto ake a payipi. Mwa kuyankhula kwina, tikuyesera kulembera payipi yotsekedwa, ndipo izi ndi zolakwika. Kodi yolakwika koyamba EPIPE ndi chizindikiro SIGPIPE adawonekera mu kope lachisanu ndi chimodzi la Unix.

Koma ngakhale chotengeracho chili chotsegula, chikhoza kukhala chodzaza. Pankhaniyi, timamasula loko ndikupita kukagona ndi chiyembekezo kuti njira ina idzawerenga paipi ndikumasula malo okwanira mmenemo. Titadzuka, timabwerera koyambira, ndikuyikanso loko ndikuyamba kujambula kwatsopano.

Ngati pali malo okwanira aulere mu payipi, ndiye timalemba deta kwa izo pogwiritsa ntchito kulemba (). Parameter i_size1 pa inode (ngati payipi ilibe kanthu ikhoza kukhala yofanana ndi 0) imasonyeza kutha kwa deta yomwe ili nayo kale. Ngati pali malo okwanira kujambula, tikhoza kudzaza payipi kuchokera i_size1 mpaka PIPESIZ. Kenako timamasula loko ndikuyesera kudzutsa njira iliyonse yomwe ikuyembekezera kuwerenga kuchokera paipi. Timabwereranso kumayambiriro kuti tiwone ngati tinatha kulemba ma byte ambiri momwe timafunikira. Ngati sichikanika, ndiye kuti timayamba kujambula kwatsopano.

Kawirikawiri parameter i_mode inode imagwiritsidwa ntchito kusunga zilolezo r, w ΠΈ x. Koma pankhani ya mapaipi, timawonetsa kuti njira ina ikudikirira kulemba kapena kuwerenga pogwiritsa ntchito ma bits IREAD ΠΈ IWRITE motsatana. Njirayi imayika mbendera ndi kuyitana sleep(), ndipo zikuyembekezeredwa kuti njira ina mtsogolo idzayambitsa wakeup().

Matsenga enieni amachitika mkati sleep() ΠΈ wakeup(). Amakhazikitsidwa mu slp.c, gwero la ndemanga yodziwika bwino yakuti "Simukuyenera kumvetsa izi". Mwamwayi, sitiyenera kumvetsetsa kachidindo, ingowonani ndemanga zina:

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

Njira zomwe zimayambitsa sleep() pa njira inayake, ikhoza kudzutsidwa pambuyo pake ndi njira ina, yomwe ingayambitse wakeup() pa njira yomweyo. writep() ΠΈ readp() kugwirizanitsa zochita zawo kudzera mu mafoni awiriwa. Zindikirani kuti pipe.c nthawi zonse amaika patsogolo PPIPE ataitanidwa sleep(), ndi choncho sleep() akhoza kusokonezedwa ndi chizindikiro.

Tsopano tili ndi zonse kuti timvetsetse ntchitoyi 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);
}

Mutha kupeza mosavuta kuwerenga ntchitoyi kuchokera pansi mpaka pamwamba. Nthambi ya "kuwerenga ndi kubwerera" nthawi zambiri imagwiritsidwa ntchito ngati pali data paipi. Pankhaniyi, ife ntchito kuwerenga () timawerenga zambiri zomwe zilipo kuyambira pano f_offset kuwerenga, ndiyeno sinthani mtengo wofananira nawo.

Pakuwerenga kotsatira, payipi idzakhala yopanda kanthu ngati zowerengera zafika i_size1 ku inode. Timakhazikitsanso malo ku 0 ndikuyesera kudzutsa njira iliyonse yomwe ikufuna kulembera mapaipi. Tikudziwa kuti conveyor ikadzadza. writep() adzagona tulo ip+1. Ndipo tsopano payipi ilibe, titha kuidzutsa kuti tiyambirenso kulemba.

Ngati mulibe chowerenga, ndiye readp() akhoza kuika mbendera IREAD ndi kugona tulo ip+2. Tikudziwa zomwe zidzamudzutse writep(), pamene ikulemba deta ku pipeline.

Ndemanga kwa readi() and writei() zikuthandizani kumvetsetsa kuti m'malo modutsa magawo "u"Titha kuwatenga ngati ntchito zanthawi zonse za I / O zomwe zimatenga fayilo, malo, chosungira kukumbukira, ndikuwerengera kuchuluka kwa ma byte oti muwerenge kapena kulemba.

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

Ponena za kutsekereza kwa "Conservative", ndiye readp() ΠΈ writep() letsani inode mpaka atamaliza ntchito yawo kapena kulandira zotsatira (ndiko kuti, kuyimba wakeup). plock() ΠΈ prele() imagwira ntchito mophweka: kugwiritsa ntchito mafoni osiyanasiyana sleep ΠΈ wakeup tiloleni kudzutsa njira iliyonse yomwe ikufunika loko yomwe tangotulutsa kumene:

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

Poyamba sindinkamvetsa chifukwa chake readp() sichimayambitsa prele(ip) asanayambe kuyitana wakeup(ip+1). Chinthu choyamba ndi writep() zimayambitsa mkombero wake, izi plock(ip), zomwe zimatsogolera ku deadlock ngati readp() sindinachotse chipika changa, ndiye mwanjira ina code iyenera kugwira ntchito moyenera. Ngati muyang'ana wakeup(), ndiye zikuwonekeratu kuti zimangowonetsa njira yogona ngati yokonzeka kuphedwa, kotero kuti m'tsogolomu sched() anayambitsadi. Choncho readp() zoyambitsa wakeup(), amachotsa loko, amaika IREAD ndi mafoni sleep(ip+2)- zonsezi kale writep() ikuyambiranso kuzungulira.

Izi zikumaliza kufotokoza za zotengera m'kope lachisanu ndi chimodzi. Code yosavuta, zotsatira zofika patali.

Kusindikiza kwachisanu ndi chiwiri kwa Unix (Januwale 1979) inali kutulutsidwa kwakukulu kwatsopano (zaka zinayi pambuyo pake) komwe kunayambitsa mapulogalamu ambiri atsopano ndi mawonekedwe a kernel. Zinasinthanso kwambiri pokhudzana ndi kugwiritsa ntchito mitundu yoponyera, migwirizano ndi zolozera zojambulidwa kumapangidwe. Komabe conveyor kodi pafupifupi zosasinthika. Titha kulumpha kope ili.

Xv6, kernel yosavuta ngati Unix

Kupanga kernel Xv6 kutengera kope lachisanu ndi chimodzi la Unix, koma lalembedwa mu C yamakono kuti liziyenda pa mapurosesa a x86. Khodiyo ndi yosavuta kuwerenga komanso yomveka. Kuphatikiza apo, mosiyana ndi magwero a Unix omwe ali ndi TUHS, mutha kuyiphatikiza, kuyisintha, ndikuyiyendetsa pazinthu zina osati PDP 11/70. Chifukwa chake, kernel iyi imagwiritsidwa ntchito kwambiri m'mayunivesite ngati zida zophunzitsira pamakina ogwiritsira ntchito. Magwero zili pa Github.

Code ili ndi kukhazikitsa momveka bwino komanso moganizira chitoliro.c, mothandizidwa ndi buffer mu kukumbukira m'malo mwa inode pa disk. Apa ndikupereka tanthauzo la "mapaipi omanga" ndi ntchitoyo 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() amakhazikitsa dziko lonse la kukhazikitsidwa, lomwe limaphatikizapo ntchito piperead(), pipewrite() ΠΈ pipeclose(). Kuitana kwenikweni kwadongosolo sys_pipe ndi wrapper yokhazikitsidwa mkati sysfile.c. Ndikupangira kuwerenga code yake yonse. Kuvuta kuli pamlingo wa code source ya kope lachisanu ndi chimodzi, koma ndikosavuta komanso kosangalatsa kuwerenga.

Linux 0.01

Linux 0.01 source code ikupezeka. Zidzakhala zophunzitsa kuphunzira kukhazikitsa mapaipi ake fs/pipe.c. Izi zimagwiritsa ntchito inode kuyimira mapaipi, koma payipi yokhayo imalembedwa mu C yamakono. Ngati mwadutsa khodi ya 6th edition, mulibe vuto pano. Izi ndi momwe ntchitoyi ikuwonekera 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;
}

Popanda kuyang'ananso matanthauzidwe ake, mutha kudziwa momwe mawerengedwe a inode amagwiritsidwira ntchito kuti muwone ngati ntchito yolemba imabweretsa SIGPIPE. Kuphatikiza pa kugwira ntchito byte-byte, ntchitoyi ndi yosavuta kufananiza ndi malingaliro omwe tafotokozawa. Ngakhale logic sleep_on/wake_up sizikuwoneka zachilendo.

Zingwe zamakono za Linux, FreeBSD, NetBSD, OpenBSD

Mwamsanga ndinadutsa maso amakono. Palibe aliyense wa iwo amene ali ndi kukhazikitsa kwa disk (zosadabwitsa). Linux ili ndi kukhazikitsa kwake. Ngakhale ma kernel atatu amakono a BSD ali ndi kukhazikitsa kutengera ma code omwe adalembedwa ndi John Dyson, pazaka zambiri akhala osiyana kwambiri wina ndi mnzake.

Kuwerenga fs/pipe.c (pa Linux) kapena sys/kern/sys_pipe.c (pa * BSD), pamafunika kudzipereka kwenikweni. Khodi yamasiku ano ikukhudza magwiridwe antchito ndi kuthandizira pazinthu monga vekitala ndi asynchronous I/O. Ndipo tsatanetsatane wa kagawidwe ka kukumbukira, maloko ndi kasinthidwe ka kernel zimasiyana kwambiri. Izi sizomwe makoleji amafunikira pamaphunziro oyambira ogwiritsira ntchito.

Komabe, ndinali ndi chidwi chofuna kukumba machitidwe akale (monga kupanga SIGPIPE ndi kubwerera EPIPE polembera mapaipi otsekedwa) m'maso onse amakono osiyanasiyana. Mwina sindidzawona kompyuta ya PDP-11 m'moyo weniweni, koma pali zambiri zoti ndiphunzire kuchokera ku code yomwe inalembedwa zaka zambiri ndisanabadwe.

Nkhani yolembedwa ndi Divi Kapoor mu 2011:Linux Kernel Implementation of Mapaipi ndi FIFOs" imapereka chithunzithunzi cha momwe mapaipi (akadali) amagwirira ntchito ku Linux. A zomwe zachitika posachedwa ku Linux ikuwonetsa njira yolumikizirana mapaipi, yomwe mphamvu zake zimaposa mafayilo osakhalitsa; ndikuwonetsanso kutalika kwa mapaipi kuchokera ku "kutsekera kokhazikika" kwa mtundu wachisanu ndi chimodzi wa Unix kernel.

Source: www.habr.com

Kuwonjezera ndemanga