6 ms·
I don't understand how the "everything is a file" could apply for everything in practice. For example, Linux has ioctl(), which in practice are like a side chan
by MyrtleTook 6y ago
I don't understand how the "everything is a file" could apply for everything in practice. For example, Linux has ioctl(), which in practice are like a side channel. Granted, Linux doesn't apply this API philosophy too thoroughly.
I guess the "everything is a file" might have multiple meanings. For example:
(1) Everything is represented by a (file) descriptor
(2) Same as (1) and the descriptor has a file-like API (think read(), seek(), write(), etc.)
(3) Everything is an "byte addressable blob of bytes"
Meaning (1) is OK. But it doesn't tell nothing about the API the (file) descriptor itself would use. It could be a fixed set (like meaning (2)), or be variable depending on something else (like the (file) descriptor type).
Meaning (2) looks like too restrictive and inefficient to me and is the one I really have trouble accepting as a general OS primitive.
Meaning (3) surely can't be used for everything in practice, right? It's just to generic like "every computer architecture can be emulated by a universal turing machine." And it also seems too inefficient. But it could be very useful if the blob of bytes had an API like (2) or any other, including having an API depending of the "file type".
Is option (3) that folks are meaning when talking about "everything is/should be a file"?
EDIT: formatted the meaning list correctly.
- yiyus 6y agoIt's basically your second option. In Plan 9, everything is a file server that presents a file system interface that speaks the 9P protocol.
- Isamu 6y agoI agree with you. A type amounts to the sum of operations that are valid on an object conforming to that type. A file object is a very basic, general type, that allows open, read bytes, write bytes, close, maybe seek, maybe some ops are restricted (read-only, write-only) etc. I don’t think it is generally appreciated how far it gets you to have a unifying simple interface. You can always add a complex one, you know?
- bogomipz 6y agoIt's interesting both of you had different answers. I realize that the streams interface was a Sys V thing but would the Unix's "everything is a file" generally be option (2) in the OPs comment then? I feel like I've heard the phrase so much and just always assumed it was (2.)
- throwaway823882 6y agoIf Unix is "everything is a file", then Plan 9 is "everything is a network filesystem". If you have a laptop and a desktop, and your desktop has a printer attached, can your laptop just print to it? In Linux, you have to set up CUPS, open network ports, download drivers, and generally set up both machines to be able to "talk printers". In Plan 9, your laptop just opens the desktop's printer file over the network, and prints.
- nine_k 6y agoThe latter does not prevent the laptop from the need of a "printer driver" to actually render something. But the driver can be unified (TTY or PostScript), and the printer object (not exactly like a file) has, well, methods to report options and set options, like the paper tray to use. Or so I understand. If we could imagine a network filesystem (spanning many hosts) full of Erlang objects which can receive and send data, it would be somehow similar.
- maxxk 6y agoI think, in Plan9 philosophy, if the desktop has a driver and it is started in the current namespace, it is represented as a file too (like /dev/my-printer/print-pdf). But it quickly becomes confusing for me: 1. Nowadays we can represent the essence of this approach with FUSE and SSH/SSHFS. Sadly, nobody does: local servers (i3, dbus, ..., vscode) use domain sockets and client executables, probably due to the lack of private namespace support by default. 2. The difference between hypothetical "/dev/my-printer/print-pdf" and almost-like-real-world "my-printer-print-pdf /dev/my-printer" looks similar to binding the first argument in OOP-style vs the explicit C-like call syntax.
- discreteevent 6y agoIt's more or less 3. Not everything is a blob but everything is a stream of bytes. It think the confusion for most of us (me) initially is that a file means a blob that you read in, change and then write out more or less atomically. But the Unix originaters understood files as streams. So, for example, the input stream from your mouse is a file. Everything is a file really means everything is a stream.
- jacobvosmaer 6y agoI think "everything is a file" also means: everything is addressable by a file path. Per-process namespaces are part of what makes this possible. In a way it's similar to HTTP REST, which is also organized by file paths, except instead of the HTTP verbs GET, POST etc. you get open, read, write as your verbs. A side channel is then just a directory entry.
- kragen 6y agoIt's more like #2, but without ioctl() and similar brain-damaged abortions. If you open /dev/mouse, for example, you get a stream of events (encoded as blobs of bytes), which you can get by read(), not a byte-addressable blob of bytes. But lots of things in Plan9 present an interface that isn't just a single file. The 8½ window system, for example, presents not only /dev/mouse but also /dev/cons (character-oriented I/O), /dev/bitblt (to which you write requests for 2-D accelerated drawing operations), /dev/rcons (keystroke-oriented character I/O), and /dev/screen (the contents of the window—which is just a byte-addressable blob of bytes). http://doc.cat-v.org/plan_9/4th_edition/papers/812/ http://doc.cat-v.org/plan_9/4th_edition/papers/812/ explains in more detail. And, of course, file storage servers similarly provide an arbitrary tree of files, and when you remotely log into a CPU server, you mount your local filesystem on the CPU server so that processes running on the CPU server can access your local files transparently—including /dev/screen, /dev/mouse, and /dev/bitblt, if you so choose.
- bombela 6y agoAnd what's the advantage vs an API via function calls? It's the same thing no? Calling 0x42 with a given ABI vs interpreting bytes as an ABI seems oddly similar.
- majewsky 6y agoI'm not overly familiar with Plan 9, but a significant advantage of the filesystem as an API is that it composes well. You can put any service inbetween that consumes the existing file and provides a new file with the same API contract, but different behavior (e.g. a /dev/screen that's cropped to a certain area, or that inverts colors on everything drawn into it). Then you can make a new mount namespace where the new file is put in the place of the old file, so that the actual process consuming it has no idea that someone is sitting in the middle. With a traditional shared object, you'd have to engage in LD_PRELOAD shenanigans to achieve the same, or if the library is statically linked and does not have any hooks, you're straight out of luck.
- bombela 6y ago
- AceJohnny2 6y agoIt may be useful to see Russ Cox's "Tour of ACME" video [1]. ACME is a Plan-9 text editor, which applies the "everything is a file" philosophy pretty deeply. It doesn't answer your ioctl question (that I remember), but maybe it'll give you a better example of how other things can be accessed as files. [1] https://www.youtube.com/watch?v=dP1xVpMPn8M https://www.youtube.com/watch?v=dP1xVpMPn8M
- ofrzeta 6y ago"Everything is a file but with different semantics"