Too bad this article is totally Linux/mdadm-centric and does not mention other sofware RAID solutions, like the “rampant layering violation” called ZFS, FreeBSD’s graid, OpenBSD’s softraid, etc.
I found that it caused me to check my phone/inbox/Slack more, not less.
This behavior is called extinction burst.
The idea that a stable API surface area for kernel modules is “nonsense” is definitely one reason I’m keen to avoid seriously working on or even with Linux for the rest of my career. The article itself doesn’t appear to have actually used the word “nonsense”, but it definitely offers some false dichotomies; e.g., the idea that innovation and improvement can’t be had if you also want to provide stability, or that API/ABI stability is somehow a burden for those closed source operating systems to bear.
In illumos, we have inherited a rich, stable interface for various kinds of kernel modules from our Solaris heritage. Though Solaris was closed source, illumos is not, and yet we continue to support the same kind of stability. We remove ancient things from time to time, but if you’re working on a device driver for a PCI network card or certain other classes of kernel module, and you stick to the stable interfaces, you should be well-served. Most recently we extended our USB framework to support XHCI controllers and USB 3.0, without needing to ditch support for existing USB device drivers.
API/ABI stability is a critical variety of engineering empathy for the people who build software on top of the platform you provide.
The article itself doesn’t appear to have actually used the word “nonsense”
The HTML file itself is named stable-api-nonsense.html.
The HTML file itself
Original file: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/stable-api-nonsense.rst
Ah, so it is!
Also, I had somehow missed this gem from the executive summary:
You think you want a stable kernel interface, but you really do not, and you don’t even know it.
The author must be great fun at parties.
If you like this talk you might also be interested in his previous ones:
30C3: How to Build a Mind
33C3: Machine Dreams
The same guy also wrote an article about laptops (http://www.nytimes.com/1985/12/08/business/the-executive-computer.html):
But the real future of the laptop computer will remain in the specialized niche markets. Because no matter how inexpensive the machines become, and no matter how sophisticated their software, I still can’t imagine the average user taking one along when going fishing.
He’s right, but of course we’re all carrying computers vastly more powerful than anything available in 1985 around with us every day. Everything is impossible until it is obvious.
Clang and GCC have intrinsics for this nowadays:
http://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins
https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
Using xor is just a tiny optimization (makes it 3 bytes smaller and, in theory, saves a clock cycle per iteration):
< cmp %al,%dl
< setne %al
---
> xor %edx,%eax
Until you use a different compiler/CPU and end up with the equivalent of:
if (a[i] == b[i])
rv |= 1;
And suddenly you have data dependent branches again. That’s very unlikely, but since the point of the exercise is to avoid branching instructions, best to avoid potentially branching operators entirely.
I don’t buy it because the real protocol is what you read and write from the file, not that you can read and write files. And if the “file” is a directory, what do the filenames you read and write from/to it mean?
So is there really any difference between
open(read("/net/clone"))andnet_clone();? The author seems to say the former is more loosely coupled than the latter because the only methods are open and read on the noun that is the file…. but really, you are stating exactly the same thing as the “verb” approach (if anything, I’d argue it is more loosely typed than loosely coupled). If a new version wants to add a new operation, what’s the difference between making it a new file that returns some random data you must write code to interpret, and a new method that returns some data you must write code to use?Yes: The fact that you can write tools that know nothing about the /net protocol, and still do useful things. And the fact that these files live a uniform, customizable namespace. You can use “/net/tcp/clone”, but you can also use “/net.home/tcp/clone”, which may very well be a completely different machine’s network stack. You can bind your own virtual network stack over /net, and have your tests run against it without sending any real network traffic. Or you can write your own network stack that handles roaming and reconnecting transparently, mount it over /net, and leave your programs none the wiser. This can be done without any special support in the kernel, because it’s all just files behind a file server.
The difference is that there are a huge number of tools you can write that do useful things with /net/clone that know nothing about what gets written to the
/net/tcp/*files. And tools that weren’t intended to manipulate /net can still be used with it.The way that rcpu (essentially, the Plan 9 equivalent of VNC/remote desktop/ssh) works is built around this. It is implemented as a 90 line shell script It exports devices from your local machine, mounts them remotely, juggles around the namespace a bit, and suddenly, all the programs that do speak the devdraw protocol are drawing to your local screen instead of the remote machine’s devices.
You argue better than I can, but I’ll add that the shell is a human interactive environment, C api’s are not. Having a layer that is human interactive is neat for debugging and system inspection. Though this is a somewhat weaker argument once you get python binding or some equivalent.
I was reminded of this equivalent.
But in OOP you can provide a “FileReader” or “DataProvider”, or just a FilePath that abstracts either where the file is or what you are reading from too. The simplest would be the net_clone function above just taking a char* file_path, but in an OOP language the char* or how we read from whatever the char* is can be abstracted too.
Yes, but how do you swap it out from outside your code? The file system interface allows you to effectively do (to use some OOP jargon) dependency injection from outside of your program, without teaching any of your tools about what you’re injecting or how you need to wire it up. It’s all just names in a namespace.
LD_PRELOAD, JVM ClassPath…
Yes, there is. ”/net/clone” is data, while net_clone() is code.
Yes - but the read()/write() layer allows you to do useful things without understanding that higher-level protocol.
It’s a similar situation to text-versus-binary file formats. Take some golang code for example. A file ‘foo.go’ has meaning at different levels of abstraction:
You can interact with ‘foo.go’ at any of these levels of abstraction. To compile it, you need to understand (1). To syntax-highlight it you only need (2). To do unicode-aware search and replace, you need only (3). To count the bytes, or move/delete/rename the file you only need (4).
The simpler interfaces don’t allow you to do all the things that the richer interfaces do, but having them there is really useful. A user doesn’t need to learn a new tool to rename the file, for example.
If you compare that to an IDE, it could perhaps store all the code in a database and expose operations on the code as high-level operations in the UI. This would allow various clever optimisations (e.g. all caller/callee relationships could be maintained and refactoring could be enhanced).
However, if the IDE developer failed to support regular expressions in the search and replace, you’re sunk. And if the IDE developer didn’t like command line tools, you’re sunk.
(Edit: this isn’t just one example. Similar affordances exist elsewhere. Text-based internet protocols can be debugged with ‘nc’ or ‘telnet’ in a pinch. HTTP proxies can assume that GET is idempotent and various cacheing headers have their standard meanings, without understanding your JSON or XML payload at all.)