So this is pretty neat. From the code we can see that:
If you set the console switches of the PDP-11 to the magic number 173030 init executes "/bin/sh -" on the console tty (probably a decwriter).
Otherwise it starts /etc/getty on /dev/tty0 - tty8, ttya, and ttyb.
It also starts /etc/dpd ("Dpd is the 201 data phone daemon. It is designed to submit jobs to the Honeywell 6070 computer via the GRTS interface."), /usr/mel/da (???) and /usr/demo/dds (???).
When user logs out it's copying the utmp entry to wtmp.
I can see that the init binary is 456 bytes.
It's mounting hard drives /dev/rk1-rk3 on /usr, /sys and /crp. Maybe no /etc/fstab yet. I guess /dev/rk0 had root.
It's not that magic. It's the address of the (RF disc) IPL in the "UNIX ROM". It allows the operator to bootstrap Warm UNIX into single-user mode by just pressing LOAD then START without adjusting the front panel switches. Bootstrapping Warm UNIX into multi-user mode is achieved by just toggling one front panel switch (#15) in between LOAD and START. It's all described in the accompanying boot(7) manual page.
I would look in the git repository for Unix: https://github.com/dspinellis/unix-history-repo. It isn't guaranteed to be correct, either, but should have a commit describing its addition that can be trusted slightly more.
The original Unix operating system was written in assembler, and the applications in a mix of assembler and an interpreted language called B, which had the virtue that it was small enough to run on the PDP-7. But B was not powerful enough for systems programming, so Dennis Ritchie added data types and structures to it. The resulting C language evolved from B beginning in 1971; in 1973 Thompson and Ritchie finally succeeded in rewriting Unix in their new language. This was quite an audacious move; at the time, system programming was done in assembler in order to extract maximum performance from the hardware, and the very concept of a portable operating system was barely a gleam in anyone's eye. As late as 1979, Ritchie could write: “It seems certain that much of the success of Unix follows from the readability, modifiability, and portability of its software that in turn follows from its expression in high-level languages”, in the knowledge that this was a point that still needed making.
The C compiler in this 1972 UNIX is written in an interesting early dialect:
1972 Modern
---- ------
foo; int foo;
foo 1; int foo = 1;
foo[]; int *foo;
foo[] 1, 2, 3; int foo[] = { 1, 2, 3 };
char foo[][]; char **foo;
No struct, union, or static. I'm wondering if locals not marked with auto are static. Also "extern foo" is used as a forward declaration to function or int foo.
Yes. But the Burroughs architecture was literally designed to support the high level language (it was heavily CISC), so that solution did not extend to any other computer systems, whereas C of course was relatively portable.
(To head off complaints about what "portable means": portable enough that people did port Unix and C programs to many architectures, unlike the case with the Burroughs OS and programs.)
So the Unix claims of firsts need qualifiers to be absolutely true, but are true in spirit even when phrased casually: the earlier exceptions are mostly just curiosities.
Pretty cool. I knew the shallow history B -> C, but not that UNIX ~beta was in assembly nor that B was interpreted. Somehow I think of game design in the early 80s were people would write a kernel in asm then built DSL-like interpreter for their domain/game.
I agree it's pretty neat. PDP 11 assembler code is the only assembler
I can read like C. I've never come up to speed on x86, I sort of get
it but it was weird in a lot of places so I punted.
I've done other assembler code, not a lot, but I've written swtch()
(process context switch) in 68K and VAX assembly.
Never liked anything as much as the PDP 11. So simple, so clean. The TA
who taught the course where I learned PDP 11 assembly (Ken Witte) was
so into it that he could read octal dumps like it was C. I remember
getting him to come help me debug a problem, I coaxed him to my apartment
with a 6 pack of beer, he looked at some octal and said "right there".
Amazing guy but the PDP 11 code was so clean you could do that.
Anyone have a modern instruction set they like as much?
The TA who taught the course where I learned PDP 11 assembly (Ken Witte) was so into it that he could read octal dumps like it was C
I think this is a case of "do anything enough and you'll memorise it" - I can mentally disassemble most of the first-page x86 instructions from a hexdump, although x86 really looks much better in octal ( http://reocities.com/SiliconValley/heights/7052/opcode.txt ), and I still have vague memories of some 6502 instructions from many years ago.
I used to be able to do this for z80. I owned a spectrum and the user manual had a list of z80 instructions together with their byte code. Lacking an assembler, my only way of writing code was to hand write the numbers and then POKE them into memory.
Ah, all those wasted hours writing code, only for it to instantly crash and lose everything...
I was most interested to see how the fork syscall works:
sys fork
br new process code
/ old process code continues here
/ r0 contains new process pid
/ c flag set if fork failed
so the if(fork() == 0) { child code } else { parent code } of modern fork is magic right inside the fork syscall (which just has to increment the return address by the size of one br instruction before returning to the parent)
Echoes of this idea still persist in modern systems. For example, from http://uninformed.org/?v=1&a=1&t=txt discussing PowerPC OS X system calls:
"An interesting feature of Mac OS X is that a successful system call will return to the address 4 bytes after the end of 'sc' instruction and a failed system call will return directly after the 'sc' instruction. This allows you to execute a specific instruction only when the system call fails. The most common application of this feature is to branch to an error handler, although it can also be used to set a flag or a return value."
A similar idea crops up in ARM's exception/interrupt table, where on exception N, control passes to the instruction at memory location N*4. Since instructions are all 4 bytes wide, you usually put a branch instruction in each slot that jumps to the real handler routine.
They're not so much echoes as a continuing necessity. System calls in UNIX-style operating system APIs generally return two integer values, a file descriptor/character count/ID/whatever and an error code; and because the twain are largely mutually exclusive the system call mechanism usually (dependent from the architecture of course) has some way of marshalling that into one processor register, be it using alternative return addresses or a flag bit such as the carry flag in the status word.
The OS/2 Control Program API and the Windows NT Native API return the error codes explicitly from the HLL wrapper functions, the (for example) open file handle returned from DosOpen() being an integer passed by reference, and their system call marshalling is thus somewhat different. It helps that calling conventions such as APIENTRY32 (http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/fu...) lend themselves easily to a treat-the-stacked-arguments-as-a-structure system, moreover.
I implemented a similar API once, marshalling by-reference system call arguments through processor registers using a pass-by-value-return scheme.
It's already been incorporated into systemd. Along with code to fetch today's xkcd cartoon at startup and a system registry that uses Pig Latin as the storage format.
Actually, the Pig Latin feature was deprecated recently when they combined it with the boot loader for reasons only the development team understands. It didn't help that all of their email correspondence was in pig latin.
I really appreciate this. I wasn't even though of at the time it was written. What I mean is that I'm very grateful for computers / electrical engineering. What a excellent world we live in.
I'm not sure its that excellent a world. We went from this to a mix of massive broken ISA like x86, piles of firmware, EFI, SecureBoot and then when you actually organise all the turtles to point the right way, a GDT, IDT to set up. Ugh.
You seem to be forgetting about all of the other unixes.
Because systemd does not (to my knowledge) support any unix other than Linux, we can say for certain that OpenBSD, FreeBSD, NetBSD, MINIX 3, Plan 9, GNU/Hurd, MAC OSX, et al. all do not use systemd. Add to that the fact that some Linux distributions do not use systemd (Including Slackware, etc), and you can easily come to the conclusion that systemd is (strictly speaking) in the minority, and therefore not the main unix init system these days at all.
If you set the console switches of the PDP-11 to the magic number 173030 init executes "/bin/sh -" on the console tty (probably a decwriter).
Otherwise it starts /etc/getty on /dev/tty0 - tty8, ttya, and ttyb.
It also starts /etc/dpd ("Dpd is the 201 data phone daemon. It is designed to submit jobs to the Honeywell 6070 computer via the GRTS interface."), /usr/mel/da (???) and /usr/demo/dds (???).
When user logs out it's copying the utmp entry to wtmp.
I can see that the init binary is 456 bytes.
It's mounting hard drives /dev/rk1-rk3 on /usr, /sys and /crp. Maybe no /etc/fstab yet. I guess /dev/rk0 had root.