The original Unix provided one implementation for each subsystem. They relentlessly simplified the problem they were solving to make it doable.
The original Unix provided one implementation for each subsystem. They relentlessly simplified the problem they were solving to make it doable.
39,000 certs 0.0%
40,000 usr 0.0%
164,000 init 0.0%
240,000 virt 0.0%
250,000 ipc 0.0%
459,000 io_uring 0.0%
664,000 rust 0.1%
980,000 samples 0.1%
1,885,000 block 0.1%
2,850,000 scripts 0.2%
2,953,000 security 0.2%
3,609,000 crypto 0.3%
5,165,000 mm 0.4%
7,156,000 lib 0.5%
12,420,000 kernel 1.0%
33,047,000 net 2.5%
39,916,000 include 3.1%
43,224,000 fs 3.3%
45,001,000 sound 3.4%
54,988,000 tools 4.2%
107,971,000 arch 8.3%
943,527,000 drivers 72.2%
Based on rough byte count (total 1,306,548,000 bytes in the above).And a proper secure microkernel much less.
In fact traditional unixes still do, like FreeBSD. Linux is the odd one out with this separation. I think it happened because GNU was not very successful with Hurd but they made great userland so "Linux" became kinda a combo. And for Linus the userland was never really in scope anyway.
Or to be more precise, they had very different trade-offs to make. Back then, you could have a system call and context switch for every read and live with the overhead.
Today we have something like io_uring.
Because they had to; there just wasn't a viable alternative
Most minicomputer class processors were sewn together from multiple chips and transistors; even their register sets for the CPU were often not dissimilar from main memory. Texas Instrument's minicomputer (and later microcomputer) architecture even just put registers in RAM. In the microcomputer world, the 6502 got around having a very small register set by just having a 256-byte "zero page" with slightly faster cycle access than regular memory.
There was no need for complicated cache hierarchies. Relative cost of a context switch or interrupt or transition from user space to kernel etc. was way lower than now.
And the users of the system were by and large trusted. Security was more of a suggestion.
That was the overlays… the early days substitute for the virtual memory proper. If I remember correctly, the first PDP-11 to have the true virtual memory and a MMU was PDP-11/70 which had 18-bit wide hardware addresses.
It was truly bizarre to watch the cabinet judder and shake as we accessed stuff - I think there were only 2 disks in it and it was mostly full!
* unit testing
* framework boiler plate
* testing pragmas
* mockups
I’m all for appreciating simplicity, but let’s not pretend we haven’t progressed since then.
[0] https://github.com/dank101/4.2BSD/blob/master/lib/libc/inet/...
Later development was done on a machine that supported a max of 4MB of memory and had to allow for hundreds of simultaneous logins. Keeping the code compact was a high priority, even over usability in some cases.
$ find include/kunit/ -type f | xargs wc -l --total=only
2418
$ git grep -lE '^kunit_test_suites\(' | xargs wc -l --total=only
17838