We begin with a very brief overview of computer hardware. The presentation here is intended to provide you with a rough context of how things fit together. In subsequent chapters we will delve into more details of the hardware and how it is controlled by software.
We can think of computer hardware as consisting of three separate subsystems as shown in Figure 1.2.1.
- Central Processing Unit (CPU)
Controls most of the activities of the computer, performs the arithmetic and logical operations, and contains a small amount of very fast memory.
Provides storage for the instructions for the CPU and the data they manipulate.
- Input/Output (I/O)
Communicates with the outside world and with mass storage devices (e.g., disks, network, USB).
A communication pathway with a protocol specifying exactly how the pathway is used.
When you create a new program, you use an editor program to write your new program in a high-level language, for example, C, C++, or Java. The editor program sees the source code for your new program as data, which is typically stored in a file on the disk. Then you use a compiler program to translate the high-level language statements into machine instructions that are stored in a disk file. Just as with the editor program, the compiler program sees both your source code and the resulting machine code as data.
When it comes time to execute the program, the instructions are read from the machine code disk file into memory. At this point, the program is a sequence of instructions stored in memory. Most programs include some constant data that are also stored in memory. The CPU executes the program by fetching each instruction from memory and executing it. The data are also fetched as needed by the program.
This computer model—both the program instructions and data are stored in a memory unit that is separate from the processing unit—is referred to as the von Neumann architecture. It was described in 1945 by John von Neumann, although other computer science pioneers of the day were working with the same concepts. This is in contrast to a fixed-program computer, e.g., a calculator. A compiler illustrates one of the benefits of the von Neumann architecture. It is a program that treats the source file as data, which it translates into an executable binary file that is also treated as data. But the executable binary file can also be run as a program.
A downside of the von Neumann architecture is that a program can be written to view itself as data, thus enabling a self-modifying program. GNU/Linux, like most modern, general purpose operating systems, prohibits applications from modifying themselves.
Most programs also access I/O devices , and each access must also be programmed. I/O devices vary widely. Some are meant to interact with humans, for example, a keyboard, a mouse, a screen. Others are meant for machine readable I/O. For example, a program can store a file on a disk or read a file from a network. These devices all have very different behavior, and their timing characteristics differ drastically from one another.
Before tackling I/O programming, you would need to gain a thorough understanding of how the CPU executes programs and interacts with memory. Since I/O device programming is difficult, and every program makes use of them, the software to handle I/O devices is included in the operating system. The C runtime environment provides a rich set of functions that an applications programmer can use to perform I/O actions, and we will call upon these services to perform our I/O operations.
The goal of this book is to study how programs are executed by the computer. We will focus on how the program and data are stored in memory and how the CPU executes instructions. We leave I/O programming to more advanced books.