From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Tue, 6 Jan 2009 23:00:03 -0800 From: Roman Shaposhnik In-reply-to: To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net> Message-id: <95AD9E5A-E9CF-41DF-ABE3-3DF414B86793@sun.com> MIME-version: 1.0 Content-type: text/plain; format=flowed; charset=US-ASCII Content-transfer-encoding: 7BIT References: <1231045486.11463.245.camel@goose.sun.com> <1231130372.11463.433.camel@goose.sun.com> Subject: Re: [9fans] Why do we need syspipe() ? Topicbox-Message-UUID: 7b670720-ead4-11e9-9d60-3106f5b1d025 On Jan 4, 2009, at 10:20 PM, Russ Cox wrote: >>> I don't believe you can write a race-free implementation of >>> the pipe system call using #|. >> >> Could you, please, elaborate on what particular race do you have >> in mind? Indeed, I ran into a problem with devpipe implementation, >> but it isn't a race, its a dreaded implicit ->attach that namec() >> does when it evaluates names with the first character being #. > > The closest you can come in user space to implementing pipe is: > > int > pipe(int *fd) > { > bind("#|", "/mnt", MREPL); > fd[0] = open("/mnt/data", ORDWR); > fd[1] = open("/mnt/data1", ORDWR); > unmount("/mnt"); > return 0; > } > > but if there are multiple processes running pipe() > in the same name space, the binds will step > on each other and the pipes might get crossed. > Even if not, maybe something else was already > mounted on /mnt (or whatever mount point you > choose), and now there's nothing there. Well, strictly speaking, there's another possibility: int pipe(int *fd) { chdir("#|"); fd[0] = open("data", ORDWR); fd[1] = open("data1", ORDWR); return 0; } which avoids a race, but trashes your current directory. On related note: it is a bit sad, though, that I can't stash a channel to the current directory away in a file descriptor and use it instead of a symbolic name in a call similar to chdir. I can amost do it: int stash_cwd = open(".", ORDWR); but not quite :-( >>> > There are some devices in Plan 9 that simply don't "virtualize", > because at a deep level they are tied to process state that > doesn't go through the file system. Agreed. I think it would be fair to call them drivers for the kernel services. As opposed to drivers for physical devices. > Dup manipulates the file descriptor table, not files themselves. > Pipe accesses files that have no name in the file system. I have always thought of pipes as in-kernel buffers. That's a service the kernel provides. #| is just a driver for that service. > For example, suppose a process wants to know . If getpid read > from /dev/pid > instead of #c/pid, then running "iostats rc -c 'echo $pid'" > would show iostats's pid, not rc's. What then if rc wants to send > itself (or, more likely, its note group) a note, or fiddle with > one of its /proc files? It would be manipulating iostats, not > itself. This is a very good point. Thank you for bringing it up. I now see how being able to *always* go directly to the #c/pid makes things easier implementation-wise. And may be it is a good-enough justification for #X. But before I agree 100% and shut up ;-) here's one though: isn't the situation here, to quote Charles, rather simple: you asked for fish; you get fish? If iostats tries to interpose on everything in the filesystem -- well, may be that should be *everything*. Not ifs or buts. And yes it would mean the weird behaviour of rc you've alluded to. Because it *is* everything. > A write to devsrv is even more magical: when you write "23" > to #s/newfile, your process's fd 23 gets taken over by the > kernel. For this reason you can't use iostats on any program > that writes to /srv/newfile instead of #s/newfile--when the program > writes "23", the kernel sees the request come from iostats > instead of the original program, and it takes over the wrong fd. > (Most of those programs are 9P servers that fork into the > background, and iostats isn't too useful on those anyway, > so no one has bothered to address this.) Right. But its not that the problem is insurmountable. Its just that, literally, nobody bothered to complicate the implementation of iostats. > The # device syntax is very useful to mean the kernel device > and none other in these situations. There's definitely > something unsatisfactory about it, but it works. Once again -- thanks a million for a very clear post. It is now obvious that #X has more, how shall I put it, capabilities than a pure namespace-based approach. It really wasn't obvious to me before. Thanks, Roman.