This post is a blast from the past \(\times 2\). One reason it’s a blast from the past is that it discusses the Unix V6 code. The other reason is that it discusses some of the code that first helped me understand what was going on with Unix.
One of the real wins in Unix is the notion of pipes. Not even Ken Thompson or Dennis Ritchie understood this at first. It was Doug McIlroy, who insisted that the ability to link processes be implemented, who was responsible. One of the things that everyone in the labs say about them is that they were all astounded how quickly the ability lead to a whole new way of thinking about computation. Once pipes were implemented, it was almost trivial to make applications talk to each other and build up the modern notion of pipelines.
The thing about pipes is that despite their power, they have a fairly simple implementation. Abhijit Menon-Sen has an illuminating post that explains how pipes are implemented. If you go through his post, you will see that there’s not that much code in the pipe implementation and that it’s pretty easy to understand. I started with the V7 code base but it’s not much different and after I understood that, most of the other things in the kernel seemed to come easily.
Since the early days, there have been alternative implementations. BSD used Unix domain sockets for a while and later AT&T Unix versions built them on top of the STREAMS mechanism. BSD, at least, found the socket implementation too slow and reverted to the traditional mechanism. Linux, of course, never implemented the STREAMS paradigm so most extant Unices are using the traditional implementation.
If you read and understand the pipe implementation code you will find that you understand many of the important Unix kernel mechanisms and will be able to understand the rest of the kernel fairly easily.