Quomodo pipelines perficiantur in Unix?

Quomodo pipelines perficiantur in Unix?
Hic articulus describit exsecutionem fistularum in nucleo Unix. Nonnihil fefellit me articulus recens inscriptus "Quomodo pipelines operantur in Unix?"Evenit non de structura interna. curiosus factus sum et in antiquis fontibus defossus sum ut respondeam.

Quid ergo dicemus?

Pipelines, "verisimile maximum inventum in Unix", proprietas definitiva philosophiae Unix subiectae coniungendi libellos parvos simul ac notum signum in linea praecepti sunt:

$ echo hello | wc -c
6

Haec functionality pendet in nucleo, dummodo ratio vocationis pipequae descripta est in paginis documentis pipe (7) ΠΈ pipe (2):

Pipelines canalem unidirectionem praebent ad communicationem interprocessus. Pipeline input (scribe finem) et output habet (lege finem). Data scripta ad initus pipeline legi possunt in output.

The pipeline is created using the call pipe(2)quae reddit duo fasciculi descriptores: unum referendo ad inputum fistulae, alterum ad output.

Vestigium output ex mandato praedicto ostendit creationem pipeline et profluvium notitiae per ipsum ab uno in alium;

$ 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

Parentis processus vocat pipe()ut descriptores mounted file. Unus puer processus uni manubrio scribit, et alius processus ex alio manubrio eandem datam legit. Testa dup2 ad "rename" descriptores 3 et 4 inserere stdin et stdout utitur.

Sine tibiis, putamen unum processum ad limam scribere debebit et illum in alium processum mittere ut notitias e tabella legas. Quam ob rem plures facultates et spatium orbis terere volumus. Tibiae tamen bonae sunt non solum quia usum imaginum temporalium vitare te permittunt;

Si processus quaerit inani pipeline ergo legere read(2) erit angustos usque ad notitia praesto erit. Si processus plena pipeline conatur scribere, tum write(2) obstruet usque dum satis data a pipelino lectae sunt ad scribendum perficiendum.

Sicut POSIX postulatio, haec proprietas magni momenti est: scribens ad pipelineum usque ad PIPE_BUF bytes (saltem 512) atomici esse debent ut processus per pipelinum inter se communicare possint ita ut regulares fasciculi (quae huiusmodi cautiones non praebent) nequeant.

Cum file regulari utens, processus omnia sua output ad eam scribere potest et ad alium processum transire. Vel processus operari possunt in modum valde paralleli, adhibito mechanismo externo significante (sicut semaphore) ad notificandum se cum completo scripto vel lege. Ab omni hac hassle nos liberate.

Quid quaerimus?

Id verbis simplicibus exponam ut facilius tibi putes quomodo vector operari possit. Opus erit tibi quiddam et aliquid in memoria collocare. Munera debes addere et notitia ex quiddam removere. Munus aliquod opus erit ut operas in tabella descriptoribus legere et scribere. Et opus erit tibi crines ad speciales mores deducendos, de quibus supra.

Nunc parati sumus percontari nucleum fontem codicem sub luce claritatis ad confirmandum vel improbandum nostrum vagum exemplar mentis. Sed semper inopinato paratur.

Ubi quaerimus?

Nescio ubi exemplum mei libri celebris sit "Leones libri"cum Unix 6 source code, at gratias Societas Unix Heritage potes quaerere online at source code etiam in vetustis codicibus Unix.

Per TUHS archiva pervagatus est quasi museum visitans. Conspicere possumus historiam nostram communem, et observamus multos annos laboris ad totam hanc materiam per partes ab antiquis infulis et clauis recuperare. Neque me latet eorum fragmenta, quae adhuc desunt.

Satisfacientes curiositati nostrae de antiquae historiae transvectionum historia, possumus videre nucleos recentiores ad comparationem.

Per viam, pipe est ratio vocationis numerum XLII in mensa sysent[]. Accidit?

Traditional Unix nuclei (1970-1974)

Vestigia non invenio pipe(2) neque in PDP-7 Unix (Jan. 1970), neque in Editio prima Unix (Nov. 1971), neque in codice manco secunda editio (June 1972).

TUHS asserit Editio tertia Unix (Febr. 1973) prima versio facta est cum transportatoribus:

Unix 1973rd Editio postrema versio cum nucleo in lingua conventu scripta, sed etiam prima versio cum tibiis. Durante XNUMX, opus elaboratum est ut editio tertia emendaretur, acinum rescriptum in C, et sic editio quarta Unix apparuit.

Unus lector invenit scan documenti in quo Doug McIlroy ideam "coniungendi programmata sicut hortus caligarum" proposuit.

Quomodo pipelines perficiantur in Unix?
In libro Brian KernighanUnix: Historia et Memoir"in historia evectium traditorum, hoc documentum etiam memoratur: "... pependit in muro in officio meo apud Bell Labs per 30 annos." Hic colloquium cum McIlroyEt alia fabula e McIlroy opus, scriptum anno MMXIV:

Cum Unix exivit, fascinatio mea cum coroutinis me perduxit ut quaererem auctorem OS Ken Thompson, ut permitteret notitias scriptas ad processum ire non solum ad fabricam, sed etiam ad alium processum extrahendum. Ken placuit fieri posse. Tamen, ut minimalist, voluit singulas rationes munus significantes partes agere. Scribitne directe inter processuum vere magnum commodum scribendo ad fasciculum medium? Solus erat cum certam propositionem nomine cantes "pipeline" feci et descriptionem syntaxis pro commercio inter processuum quos Ken tandem exclamavit: "Faciam!"

ET FECIT. Fatalis vespere Ken unum nucleum et corticem mutavit, aliquot programmata vexillum fixa ad modum initus (qui ex pipelino venire potuit), et etiam nomina fasciculorum mutavit. Postero die fistulae latissime in medicamentis uti coeperunt. Fine hebdomadis, secretarii utebantur ut documenta e verbo processoribus ad typographum mitterent. Paulo post Ken originale API substituit et syntaxin involvit usum fistularum cum conventiculis mundioribus, quae ab hoc tempore adhibitae sunt.

Dolendum est, fons codicis tertiae editionis Unix acinum deperditum est. Et quamquam habemus nucleum codicis fontem in C . scriptum quarta editioNovembri 1973 emissus est, sed pluribus mensibus ante emissionem officialem exivit et exsecutiones pipeline non continet. Indignum est quod fons codicis huius munere legendarii Unix deperditus est, fortasse in aeternum.

Habemus textum documentum pro pipe(2) ab utroque emissione, sic incipere potes per inquisitionem documentorum tertia editio (verba quaedam sublineata "manualiter", filo literalis ^H, sequitur underscore!). hoc proto-pipe(2) scriptum in lingua conventu et recurrit tantum unum descriptor, sed iam praebet expectata fundamentalis functionis;

Systema vocationis pipe creates an input/output mechanism called a pipeline. Descriptor tabellae redditus adhiberi potest ad operationes legere et scribere. Cum aliquid scriptum est ad pipelineum, usque ad 504 bytes notitiarum buffered sunt, post quem processus scripturae suspenditur. Cum e pipelino leget, notitia buffered aufertur.

Anno sequenti nucleus revocetur in C, et c pipe (2) in quarta editione suam modernam speciem cum prototypo acquisivit "pipe(fildes)Β»:

Systema vocationis pipe creates an input/output mechanism called a pipeline. Descriptores fasciculi redditus in operationibus legere et scribere possunt. Cum aliquid ad pipelineum scribitur, manubrium in r1 (resp. fildi[1] redditum) adhibetur, obsignatum 4096 bytes notitiarum, post quam processus scribe suspensus est. Cum e pipelino legeret, manubrium ad r0 (resp. fila[0]) reversum sumit.

Supponitur quod semel definitur pipeline, duos (vel plures) processus communicantes (sequentibus vocatus creatis furca) Dabit data a pipeline usura vocat read ΠΈ scribo.

Testa syntaxin habet ad definiendum lineares processus processuum a pipelino connexos.

Vocat legere e pipelino inani (nota buffered data) quae unum tantum finem habet (omnes fasciculi descriptores scripti clausi sunt) return "ultimum documenti". Vo- scere in re simili neglecta sunt.

Prima servavit pipeline implementation refers ad quintam editionem Unix (June 1974), sed fere idem cum illo qui in altera emissione apparuit. Commentationes modo additae sunt, ut quintam editionem omittere possis.

Sexta editio Unix (1975)

Incipiamus legere Unix source code sexta editio (May 1975). Gratias agere leones multo facilius est invenire quam fontes priorum versionum;

Ad multos annos liber leones unicum documentum in Unix nucleo praesto fuit extra Bell Labs. Etsi licentia sexta editionis magistris uti codice suo fonte permisit, septima editio licentiam hanc facultatem exclusit, ita liber in forma exemplarium exemplarium illegalium distributus est.

Hodiernae editionem libri emere potes, cuius tegumento discipulos ad exemplar apparatus ostendit. Et gratias Warren Toomey (qui TUHS consilium incepit) download potes Documentum PDF cum source codice pro editione sexta. Cupio tibi dare ideam quanti laboris in tabella creandis iverunt;

Plus quam abhinc XV annos, exemplar fontis codici dedi in typum leonesquia ex ignoto numero aliorum exemplarium qualitatem exemplarium non amo. TUHS nondum exsistebat nec ad fontes antiquos accessi. Sed anno 1988, veterem 9-tabulam vestimentorum inveni quae tergum ex computatro PDP11 continebat. Difficile erat narrare si laborabat, sed erat arbor integra /usr/src/ in qua pleraeque tabellae cum anno 1979 intitulatae sunt, quae etiam tum antiqua spectabantur. Septima editio vel eius derivatio PWB, ut ego credidi.

Fundamenta invenio et editos fontes ad editionem sextam manuale cepi. Nonnulli e codice eodem manserunt, sed nonnulla leviter ediderunt, mutato recentiori signo ad outdated =+. Quaedam simpliciter deleta sunt, quaedam omnino revocetur, sed non nimis.

Et hodie legere online in TUHS codice fons editionis sextae e archivum, ad quod manum habuit Velleius Ritchie.

Viam primo intuitu praecipua linea C-code ante periodum Kernighan et Ritchie eius est. brevitas. Non saepe non possum fragmenta codicis inserere sine ampla emendatione, ut comparationem stricte ostentationis areae in situ meo aptare possit.

In principio /usr/sys/ken/pipe.c commentarium explanatorium est (et sic, est plus /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

Magnitudo quiddam non mutatur ab editione quarta. Sed hic videmus, sine ulla publica documenta, fistulas olim pro tergum repositione adhibitas esse!

Quantum ad LARG files, correspondent inode vexillum LARG, quod adhibetur "algorithmus magnus appellans" ad processum indirecta, caudices support ampliores systematis fasciculi. Cum Ken dixit satius esse illis uti non, ego pro eo verbum eius laetus sumam.

Hic est realis ratio vocationis 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;
}

Commentarium clare describit quid hic agatur. Sed intelligendum codicem non est ita facile, partim propter viam”;struere user u *Β» et registra R0 ΠΈ R1 systema vocant ambitum et valores reditus transeunt.

Sit scriptor experiri cum ialloc () ad induendum orbis inode (indicem manubrium)et ope falloc () - ponere duas in memoria file. Si omnia bene se habent, vexilla ponemus ut has fasciculos duos fines pipelini cognoscamus, ea eidem inodo (cuius relatio numerabilis ad 2 apponetur), et inodis sicut modificatum et in usu notamus. Attende ad petitiones posui() in erroris semitas reducere narrationem narrationem in nova inode.

pipe() oportet per R0 ΠΈ R1 descriptor numerus lima pro legere et scribere. falloc() monstratorem tabellae compages refert, sed etiam "redit" per u.u_ar0[R0] et fasciculus descriptorum. Id est, codicem servat in r file descriptor ad legendi et assignat lima descriptor ad scribendum directe ex u.u_ar0[R0] post secundam vocationem falloc().

vexillum FPIPEquam constituimus cum tibia creando, mores officii moderatur rdwr() in sys2.cvocant specifica EGO / O consuetudines:

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

Tum munus readp() Π² pipe.c notitia legit a pipeline. Sed melius est exsequendam ex writep(). Rursum in codice factus est magis implicatior conventibus ob transeundi argumenta, sed nonnulla singularia omitti possunt.

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

Volumus scribere bytes ad pipeline initus u.u_count. Primum opus est inode claudere (vide infra plock/prele).

Tunc refellimus inode referentia calculi. Quamdiu utraque pars pipelini aperta manent, calculus debet esse aequalis 2. Vinculum unum tenemus (a rp->f_inode) ita, si calculus minus quam 2, intelligendus est processus legendi finem fistulae occlusum esse. Aliis verbis, pipeline clausa scribere conamur, et hic error est. Primum errorem codice EPIPE et signum SIGPIPE prodiit in editione sexta Unix.

Sed et si TRADUCTOR apertum sit, plenum esse potest. Hoc in casu, seram solvimus et obdormimus in spe quod alius processus e pipelino leget et satis spatii in eo absolvet. Evigilati, ad initium revertamur, seram iterum suspende et novam cycli memoriam incipe.

Si spatium vacuum in pipeline satis est, notitias ei scribimus utendo writei (). Parameter i_size1 at inode (si pipelinea vacua est 0 aequari potest) indicat finem notitiae quae iam continet. Si spatium spatium memorare satis est, fistulam implere possumus i_size1 ad PIPESIZ. Tunc seram solvimus et processum aliquem excitare temptamus qui ex pipelineo legere exspectat. Regredimur ad initium videndi si tot bytes scribere potuimus quot opus erat. Si deficit, incipimus a cyclo novo memorando.

Plerumque modularis i_mode inode adhibetur copia permissionum r, w ΠΈ x. In fistulis vero, significamus processum aliquem exspectare scribendo vel legendo utendi frenis IREAD ΠΈ IWRITE condiderunt. Processus ponit vexillum et vocat sleep()et expectatur aliquem alium processum in futurum causare wakeup().

Quod realis magicae fit in sleep() ΠΈ wakeup(). They are implemented in slp.c, fons ille celebris "Non expectatur hoc intelligere" comment. Feliciter codicem intellegere non debemus, at aliquas glossas intuere:

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

Processus qui causas sleep() pro certo canali, alio processu postea excitatus, qui faciet wakeup() pro eodem alveo. writep() ΠΈ readp() actus suos per tales paribus vocat coordinare. nota quod pipe.c semper dat prioritatem PPIPE cum dicitur sleep()Ut 'eam' sleep() ut signo interrumpatur.

Nunc habemus omnia ad munus intelligendum 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);
}

Facilius invenies hoc munus ab imo ad summum legere. Ramus "lectus et reditus" dici solet cum in pipeline aliqua notitia est. In hoc casu utimur readi () legitur ut notitia quantum est available incipiens a current unum f_offset legens, deinde renova valorem offset respondentis.

In sequentibus legit, pipelineum vacuum erit si lectu pervenerit i_size1 at inode. Nos positionem ad 0 reponimus et aliquem processum excitare conamur qui ad pipelineum scribere velit. Scimus quod cum plena sit TRADUCTOR; writep() et obdormiam in ip+1. Nunc quod inanis est pipeline, possumus excitare ad cyclum scribendi.

Si nihil habes, lege ergo readp() potest posuit vexillum IREAD et obdormiam in ip+2. Scimus quid eum excitare writep()scribens nonnulla ad pipelinem.

Comments on readi () et writei () adiuvabit ut intelligas pro parametris per transitum "u"Potest illas tractare sicut normales I/O functiones quae fasciculum, positionem, quiddam in memoria capiunt, et numerum bytes legere vel scribere possumus.

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

Quod "conservativa" interclusio, tum readp() ΠΈ writep() dum opus finiunt vel obstruunt inode consequitur (id est, vocant wakeup). plock() ΠΈ prele() opus simpliciter: per alium paro of vocat sleep ΠΈ wakeup permittite nos excitare aliquem processum qui lock indiget quo nos modo dimissi sumus;

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

Primo non potui intelligere quare readp() non faciam prele(ip) ante vocationem wakeup(ip+1). Primum est writep() facit in suo cyclo, hoc plock(ip)quae ducit ad deadlock if readp() impedimentum meum nondum removimus, quo pacto codicem recte operari debet. Si intueri wakeup()tum demum manifestum fit processum dormientem notare tam paratum ad exsequi, ut in futurum sched() vere excussum est. Sic readp() causas wakeup()aufert seram, ponit IREAD et vocat sleep(ip+2)- Hoc ante omnia writep() repetit cursus.

Hanc descriptionem traditorum in sexta editione absolvit. Simplex codice, penitus consectaria.

Septima editio Unix (Jan. 1979) nova maior emissio (quatuor annis post) multas novas applicationes et lineamenta nucleos invexit. Etiam mutationes significantes subiit in nexu cum usu generis abiectionis, unionum et argumentorum typorum ad structuras. tamen TRADUCTOR codice fere immutata. Hanc editionem transilire possumus.

XV6, simplex Unix-similis nucleo

Ad creare nucleum XV6 Sexta editio Unix adductus est, sed in moderna C scriptum est, ut percurrat x86 processus. In codice facile lectu et intellectu est. Plus, dissimiles Fontes Unix cum TUHS, illud compilare, mutare, in aliud quam PDP 11/70 currere potes. Hoc ergo nucleus late in universitatibus pro materia institutionis in systematibus operandi adhibetur. Fontes sunt in Github.

In codice continet exsequendum claram et cogitationem pipe.csubnixum quiddam in memoria pro inodi in orbe. Hic solum definitionem pipelinei structurae ac functionis constituo 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() reliquas exsecutionis statum, quae includit functiones, ponit piperead(), pipewrite() ΠΈ pipeclose(). Ipsa ratio vocationis sys_pipe est fascia implemented in sysfile.c. Totum codicem suum lectioni commendo. Intricata est ad libellam fons codicis editionis sextae, sed multo facilius et jucundius est legere.

Linux 0.01

Linux 0.01 fons codicis inveniri potest. Instructio erit ad exsequendum fistularum studere in his fs/pipe.c. Hoc inodo utitur ad fistulam exprimendam, sed ipsa pipeline in hodierna C. Si opera tua per 6th editionem codicem iter feceris, hic nihil laboras. Hoc est quod munus spectat sicut 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;
}

Sine inspectione definitionum structurarum, exponere potes quomodo computatio referentiae inodis ad reprimendam adhibita sit an operatio scribentis sequatur in SIGPIPE. Praeter byte-byte, hoc munus facile est comparare cum ideis suprascriptis. Etiam logica sleep_on/wake_up non tam aliena.

Linux nuclei moderni, FreeBSD, NetBSD, OpenBSD

Cito per quosdam nucleos moderni cucurri. Horum nullum disci exsecutionem amplius habent (nec mirum). Linux suam exsecutionem habet. Etsi tres nuclei moderni BSD nuclei inserendas continent in codice qui a Ioanne Dyson scriptus est, per annos nimis inter se discrepat.

Legere fs/pipe.c (in Linux) or sys/kern/sys_pipe.c (on *BSD), realem dedicationem accipit. Hodiernae codicis notae de effectu et sustentatione pro vectore et asynchrono I/O. Singula autem memoriae prouinciis, cincinnis et nucleis figurae omnes valde variant. Non est hoc quod collegia opus est ad cursum operandi introductorium systematum.

Alioqui curabam in fodiendo aliqua exemplaria antiqua (sicut generans SIGPIPE et reditus EPIPE scribens ad pipelinem clausa) in omnibus his diversis nucleis recentioribus. Probabiliter numquam computatorium PDP-11 in vita reali vidi, sed multum adhuc discendum est ex codice qui ante annos natus sum scriptus est.

Articulus scriptus a Divi Kapoor in 2011:Linux Kernel exsequendam Pipes et FIFOs" Recognitionem praebet quomodo fistularum (etiamnum) in Linux operetur. A recens committere in Linux exemplar quoddam commercii pipelineum illustrat, cuius facultates illas temporalium fasciculorum excedunt; atque etiam ostendit quantum pipelines oriantur a "obfirmitate valde conservativa" sextae editionis Unix nuclei.

Source: www.habr.com