9 ms·
Am I the only one who doesn't get excited about the idea of absolutely everything being a file? People seem to like the idea of being able to say things like "
by haberman 15y ago
Am I the only one who doesn't get excited about the idea of absolutely everything being a file?
People seem to like the idea of being able to say things like "cat file.wav > /dev/dsp". But a sound card is a complex thing that can be configured in umpteen different ways; what if the file has a different sample rate than the card is currently running at? Even if you gerry-rigged a kernel driver that could handle this case (by, for example, noticing when the file had been open()'d and expecting the next bytes to be a WAV header, which it uses to reconfigure the card), you're left with something that doesn't have even the most basic functionality that you'd expect from a sound player; for example, "pause."
So what has representing /dev/dsp as a file really bought you? It doesn't help you know what devices are available, because there's tons of crap in /dev that doesn't necessarily have a kernel driver loaded for it. It's not that useful as an end-user interface for selecting a sound card, because users don't want to choose between /dev/dsp and /dev/dsp2, they want to see nice names like "Internal Speaker" or "Apogee Duet."
Files give you a simple API for lots of common operations, which is nice, but the fact that all files are not created equal means that operations sometimes don't work like you expect. For example, how would you guess that "tail -f" is implemented? If you're like me, you would have expected that it works by calling poll/select/etc. and waiting for the file to become read-ready. But this approach doesn't actually work for monitoring growing files; the select() will just return immediately with read-ready even if you're at EOF. So what "tail -f" actually does is a loop that alternates between sleep() and fstat(). I'm serious! http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/tail.c;h=29ddabd62c650c4b0c9ed9b52bb3270e25f1bb90;hb=02551d8a62d84b8788a8793de121c2f1e5212d63#l1071 http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f...
- strictfp 15y agoYou could configure it by doing something like echo "22050" > /dev/dsp/config/sample_rate_hz echo "lanczos" > /dev/dsp/config/resample_algorithm You could then search for configs by using find, back them up by using tar, be able to easily replicate settings between computers using rsync etc. The idea is not to have one unconfigurable binary reciever, but rather to expose the interface as a hierarchy of rw files instead of a number of C functions, because the C functions have no easy shell representation, and most command-line tools fail using them. It's very reminiscent of REST.
- adobriyan 15y ago> The idea is not to have one unconfigurable binary reciever, It _is_ configurable, why do you think it is not? This idea that somehow one can fit any interaction with hardware into a filesystem ends when hardware becomes complex enough to simply NOT fit (like modern GPU). How do you guarantee atomicity when saving configuration with tar(1)? Linux recently deprecated textual conntracking data interface in favour of shipping binary data over netlink socket. Reason -- read() speed in real life high load scenarios. What could Plan9 do here?
- strictfp 15y agoI actually tried to point out that configurability _is_ very possible with such an API. Your complexity argument does not hold. If I can control something with a C API, why not with a file API? Take atomicity as an example. C has no inherent concept of atomicity. Yet you can acheive atomicity by using C. So why not with a REST or file-based interface? You also mention speed. Interesting since complexity and performance worries are the two roots to premature optimization if you ask me. Since this solution is still on a concept level I am of the opinion that one should avoid such discussions at this stage. But I see no _inherent_ speed limitations in a file-based API. Send binary data if you want. Text is only for readability.
- adobriyan 15y ago> Take atomicity as an example. C has no inherent concept of atomicity. Yet you can acheive atomicity by using C. So why not with a REST or file-based interface? You achieve atomicity because inside kernel handler of relevant imaginary ioctl(2) which dumps all hardware configuration there is synchronization primitive which provides necessary guarantees, so this imaginary ioctl(HW_GET_STATE) writes coherent state to userspace. If you merely expose individual hw config into flat files, POSIX directory semantics does not guarantee you atomicity. So, you have to invent something instead, like additional file which kinda sorta provides locking. But if you invented it, you have implicitly mandated that ALL users must be nice and go through locking API/file, whatever. At this point, nothing prevents rogue (and more importantly) buggy userspace from messing with well-behaving users. At this point, you've failed to provide something another developer is asking you to provide, namely, a guarantee that hw state will be coherent.
- pmarin 15y agohttp://plan9.bell-labs.com/magic/man2html/3/audio http://plan9.bell-labs.com/magic/man2html/3/audio
- djnliung 15y agoI'm not sure that really contradicts his point, that's a terribly limited API. Stereo only, no way to specify channel layout, 16bit only, no way to change the device buffer sizes, no way to tell if the device is in use, no way to tell the device latency, seemingly no way to examine what sample rates or bit depths the device supports, seemingly no way to subscribe to any kind of notification when the device has actually changed sample rate (or other properties) or when playback has stopped etc, no ability to lock the device to prevent other processes changing the sample rate or other properties, no ability to get device time or determine if the device is synchronised with system time. Some of these missing things can be added fairly easily to the existing API of course, but I don't know enough about plan9 to suggest how, for example, notifications for device property changes could be added. As it stands this interface is almost useless even for casual home users who just want to play back audio: multiple channel support is a basic requirement these days. Serious audio work is not even possible at all.
- rbanffy 15y ago> As it stands this interface is almost useless even for casual home users who just want to play back audio: multiple channel support is a basic requirement these days. Really? I must therefore, be somehow a less than casual music listener - I am perfectly happy with my stereo.
- djnliung 15y agoI wasn't suggesting that all users require it, merely that a non-trivial number do; more for watching video with multichannel soundtracks than listening to music.
- Erwin 15y agoThat calls for an obscure ioctl with an impossible name. Simply use SNDGTDVCLTNC to query the device's latency. Like the actual TIOCSLCKTRMIOS which can be used to lock the termios: http://www.kernel.org/doc/man-pages/online/pages/man4/tty_ioctl.4.html http://www.kernel.org/doc/man-pages/online/pages/man4/tty_io...
- beagle3 15y agoSome files are different. So? Do you have the same qualms with stdin/stdout not being seekable because they are often connected to a terminal? The "everything is a file" abstraction is mostly helpful and rarely gets in the way in practice; I don't know how plan9 exposes sound, but it is probably a directory, with multiple files - one you write to to set sampling rate; another gets data, and the third is stop/go/cancel. The most useful feature, though, is network transparency that really works. You don't need Vnc/rdp; just mount the remote display in your file system. You don't need special ip forwarding - just mount the remote network in your local file system. You don't need a network aware server for anything - it all is. That's the reason to get excited.
- vidarh 15y agoYou can do cat file.au >/dev/audio on a lot of Unix-y OS's. For wav, the problems you mention are solved with "sox" which converts the wav file to raw data with suitable options. All of the problems you mention are problems of the interfaces exposed by the files, not problems with the "everything as a file" idea in itself. Look at /proc on linux. /proc/[pid] represents a running process, but it's a directory, not a file, all the information about that process are inside. A hypothetical filesystem API for audio designed to be friendly might expose a /proc/sound/[device]/name file containing a user friendly description and a /proc/sound/[device]/output file that a converter gets mounted at that you can just copy files to, and a /proc/sound/[device]/control that accepts commands like "pause" or "play". You also seem to also be assuming that these interfaces are meant for ordinary end-users. While some of the functionality does make it easier for end-users to interact directly with the lower levels of the system, nothing precludes friendlier interfaces being put on top of it. What it gives you is an interface that has a bunch of standard tools you can use to operate on them, either because they're simple enough to use directly, or to make building the user friendly interfaces more easily, and that which is at the same time reasonably explorable if it's well designed. /proc is a good example of this - you can poke around in it and learn a lot about your system with just a standard shell without having the faintest idea about how it's structured initially. Meanwhile, the non-file-related system calls require you to write code to test them out - they're far more opaque. > But this approach doesn't actually work for monitoring growing files; the select() will just return immediately with read-ready even if you're at EOF. This really shouldn't be surprising. select() specifically tells you if the filedescriptor is read for read. A filedescriptor is ready to read from if there is more data or you're at the end of the stream. The behavior is entirely consistent. Perhaps a way of requesting notification only if there is more data to read, rather than if there's more data or end of the stream, would be useful, but that is not what select() provides. It illustrates some of the flaws in the Unix system calls, not an inherent problem with a filesystem interface.
- deleted 15y ago[deleted]
- wslh 15y ago> But a sound card is a complex thing that can be configured in umpteen different ways; what if the file has a different sample rate than the card is currently running at? That's what ioctl does: http://www.manpagez.com/man/2/ioctl/ http://www.manpagez.com/man/2/ioctl/
- bluetech 15y agoWell, just below the Plan 9 sections comes this: http://catb.org/~esr/writings/taoup/html/ch20s03.html#id3016155 http://catb.org/~esr/writings/taoup/html/ch20s03.html#id3016... And he's right, ioctl's can be quite tricky to operate sometimes.
- haberman 15y agoSure, you can use an ioctl for this. You could use some combination of ioctl()s to tunnel absolutely any API, just like you can wrap any text string in pointy brackets and call it XML. The question is whether this is useful. In particular, once your interface requires ioctl(), you lose the benefit of easy interoperability with UNIX command-line tools.
- clord 15y agoThe advantage of "everything-is-a-file" is that every process gains thread-safe access to some API without having to pull in the headers, link, and manage a foreign memory management regimen. But the real boon is that each process can conceivably be linked with any 'file'. I liken this practice to the STL library's iterator pattern: algorithms are the processes, and files are the iterators (although I bet STL was inspired by unix). You can redirect your tty through an ssh tunnel, you can scp a regular file, or you can ssh tunnel your soundcard or mouse. And of course 'ssh tunnel' is only one such kind of glue. There are pipes, devices, fifos, etc. In the end it works out that there are O(n*m) possibilities for only O(n+m) implementation cost. But remember that with STL, not all algorithms will work with all iterators, and vice versa. And likewise, not all processes can work with all files, and vice versa. The benefit comes from the significant overlapping portion.
- ori_b 15y ago>Am I the only one who doesn't get excited about the idea of absolutely everything being a file? Don't think of it as everything being a file. Think of it as accessing everything including file data through an RPC system.
- andrewflnr 15y agoIt's been a while since I looked at 9P. Is it really that much like an RPC system?
- ori_b 15y agoIt lets you name resources and open communications channels to them, yes. It even preserves message boundaries, as I recall.
- jdthomas 15y agoThe HUGE advantage of "everything is a file" is that if you make a tool that works on one "thing" and then want to use it on another "thing" it is quit possible that it will just work. For instance, on OSX, one of the things I sorely miss is the sysfs from Linux. Sure, OSX has the ioreg, but I cannot use the tools I am used to (find, grep, cat, echo, sed, awk, ...). To put it in terms the web programmers can understand, it is like REST, you have a GET (read), and a POST (write), and I suppose a DELETE (unlink), and with that you can implement all you need. Everything fits into a very few syscalls (open, read, write, close).