39051 certs 0.0%
40404 usr 0.0%
164228 init 0.0%
240426 virt 0.0%
250265 ipc 0.0%
459021 io_uring 0.0%
664443 rust 0.1%
979555 samples 0.1%
1885010 block 0.1%
2849606 scripts 0.2%
2953164 security 0.2%
3609139 crypto 0.3%
5165331 mm 0.4%
7156454 lib 0.5%
12419586 kernel 1.0%
33047417 net 2.5%
39916290 include 3.1%
43223905 fs 3.3%
45000780 sound 3.4%
54987535 tools 4.2%
107971048 arch 8.3%
943527384 drivers 72.2%
Based on byte count (total 1,306,550,042 bytes in the above).And a proper secure microkernel much less.
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!
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.
* 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
17838In 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.
The original Unix provided one implementation for each subsystem. They relentlessly simplified the problem they were solving to make it doable.