3 ms·
>A lot simpler and more consistent, and does a much better job of "everything is a file" than the POSIX API ever did (of course, it's "everything is a handle,"
by CodeArtisan 8y ago
>A lot simpler and more consistent, and does a much better job of "everything is a file" than the POSIX API ever did (of course, it's "everything is a handle," but that's fine, the point is that there's one consistent way to work with everything).
I am failing to see how this is more consistent. With UNIX, because everything is like a file, you operate on them the same manner. A file, a socket, a pipe, shared memory, ... you open them then you use the system calls for operating on files: read(), write(), poll(), dup(),... which then allow you to use operations built on these syscalls such as fprintf, fscanf,... but also all the tools like cat, head, grep,... This is what i would call consistency.
If i implement a new feature as a file in linux, for example a virtual filesystem like /proc/, all the cited operations would already be available out of the box.
- AnIdiotOnTheNet 8y agoBut you can't actually treat everything like a file, so you have to turn to ioctl and whatever structure is actually related to what you're working with in reality. In a sense, we only treat everything as a file the same way some languages have a toString method for everything. You can get something out of it no matter what it is, but there's no guarantee that something is going to be in any way useful and you still have to interact with it in a way that doesn't treat it like a generic string.
- zbentley 8y agoThe issue that GP was pointing out is that in Linux, everything is not a file. And the inconsistencies (in Linux or the POSIX model; take your pick--I'm not interested in splitting those particular hairs) are a hassle to program around. For example: - Non mmap'd memory: what do you do with memory retrieved by [s]brk(2)? - Signals: are they files or not? Signalfd is provided in addition to lots of other complicated other facilities for handling around the same things. And that's before getting into realtime signals and the like. - Timers/events: are they files? vDSOs? Available via files? No? Depends on which syscalls/APIs you're using. Additionally, many of the non-file-ish APIs in POSIX implementations are a massive hassle to use across multiple threads. Even the file-based APIs for eventing (select/poll/epoll.) have substantially different behavior with regards to edge/level triggering, and different behavior when used across multiple processes (shared fia fork or non-CLOEXEC handles) or threads. Can you master them and use them correctly? Sure. But there are so many ways to achieve very similar things, and, while each method has its niche, there's no unifying thought model that ties them together in the same way that "everything is a file" was promised to tie together UNIX operating systems. Oh, and /proc is being moved away from/found to have limitations because it's a file descriptor exhaustion hot-spot, among other things. So the plan9-style of "expose the internals as a filesystem" appears not to be the route that the Linux community is pursuing. TL;DR if you're writing simple, non-concurrent standalone utilities or working at a very high level then sure, you can pretend everything is a file. Below that, or in more complex applications, those abstractions break down in surmountable-but-annoying ways.
- lambda 8y agoYes, this is exactly what I was getting at.
- lambda 8y agoBut this is how Fuchsia is as well; these handles are pretty much equivalent to file descriptors, except for how they get numbered/allocated (though for C library compatibility, there is a per-process file descriptor table to map between file descriptors and handles). Even on UNIX like systems, you can't read or write on every file; for instance, you can open directory, but you can only readdir on that, not read from it. But they are still file descriptors like everything else, so you can call dup(), fstat(), pass them between processes on Unix sockets, etc. There are plenty of other operations which can only be done on certain types of files in UNIX-like systems; for instance, you can only recv() or recvmsg() on a socket. The difference is that in Fuchsia, more things have handles, and so more things can be treated consistently. For instance, jobs, processes, and threads all have such handles; so instead of getting a signal that you have to handle in an extremely restrictive environment in a signal handler or having to call wait4() to learn about the status of a child process, you can just wait on signals to be asserted on the child process using zx_object_wait(), which is the equivalent of select() or poll(). This means no more jumping through hoops to get signal handling to work with an event loop; it just works. Of course, the other difference in Fuchsia is that there is not a single namespace. Every component in Fuchsia has its own namespace, with just the things it needs access to; there is no "root" namespace. This is good for isolation, both for security reasons and reducing accidental dependencies, though I do wonder how much of a pain it would make debugging and administering a system.
- CodeArtisan 8y agoMy point was that with UNIX, while you have specialized operations like recvmsg, you still have read() and write() acting as an universal interface. If you look at Fuschia system calls, you would see vmo_read - read from a vmo vmo_write - write to a vmo fifo_read - read data from a fifo fifo_write - write data to a fifo socket_read - read data from a socket socket_write - write data to a socket channel_read - receive a message from a channe channel_write - write a message to a channel log_write - write log entry to log log_read - read log entries from log It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
- 8y ago