Especially process and thread are terms which have many different definitions and implementations. And therefor, it is easy to get confused, and hard to get the concepts crystallized in your mind. Just do some googling and you will find plenty of sources which more or less contradict each other. We will add another source i.e. our source 🙂 which, we believe, is very relevant for embedded programmers. This is not the definite answer (as this would depend on the specific operating system) BUT it will set you on the right track when studying these terms in the context of your next (or current) operating system. The easiest term is probably program. Let us begin with that one.
Basically, a (computer) program is just a sequence of computer instructions. And to promote re-use, programs are stored somewhere, though the exact storage form highly depends on the age you were living in :-). The punched card, dated end 1960 – early 1970, shows a stored Fortran program.
The terminal view arguably lists the very best editor, stored in a file on disk and dated 2011.
Programs that are stored in a file mostly follow a format such as ELF (Executable and Linkable Format) e.g. Linux programs, GHS Integrity programs. The format includes more detail on how a program has to be loaded and executed.
In low-end embedded systems, programs are flashed on the target as a raw binary, but on the host side, the raw binary could have been stored in another format (ELF, SREC or IHEX are well-known formats). Most of the time it is possible to convert one format into another e.g. with the help of objcopy or srecord.
In a broad sense, data (e.g. initialized data) is also part of a program because it is used and transformed by the computer instructions (e.g. compiled C code).
A program = (stored) code and data!
A process is a loaded program. It contains all resources (file descriptors, memory, sockets, threads etc.) but here we only consider memory. You might think CPU power is another important process’ resource and it actually is, but only in an indirect way (we will come to this later). So, a process is a living program and if there is enough memory it is possible to load several instances of the same program.
If a process lives in its own “private” memory address space which cannot be accessed by other processes, we talk about memory protection. This is an important process’ feature which can only be implemented by the OS if underlying hardware (MMU or MPU ) is available.
When a program is loaded, it isn’t necessarily executing (that is something different and discussed in section ‘Thread’)!
In our (somewhat simplified) view of a process we can state that:
A process = memory- or ‘space’-related concept!
Example 1: Linux (from Linus Torvalds et al.)
In the Linux kernel a process is represented by a struct task_struct. The definition can be found here. It is a large data structure in which all information of a process is stored. Some notable (memory-related) members are:
- pid_t pid: process identifier,
- struct mm_struct *mm, *active_mm: memory-related information. The mm_struct has virtual memory areas. And apparently,
- each task_struct has its own personality 🙂 No idea what it means though.
A typical Linux system provides memory protection and – with those capabilities activated – can only be deployed on hardware architectures with MMU. However, there are exceptions, like for example uCLinux,which is a port of Linux to systems without MMU (e.g. read here and here for available ports). The major parts of μClinux have been integrated with the main line kernel for a number of processor architectures and thus, in this regard, μClinux is essentially no longer a separate fork of Linux.
Example 2: Integrity RTOS (from Green Hills Software)
Integrity, a hard real-time RTOS from GHS with MMU-support, has the concept of a software partition. One feature, or call it dimension, of a software partition is memory protection which is achieved by a protected memory space or Virtual Address Space (VAS). A software partition cannot corrupt the memory of another one. If they need to communicate with each other then the only way is to use OS-provided mechanisms such as IPC or memory page sharing. This also implies that both parties have to agree with the communication!
Example 3: FreeRTOS (www.freertos.org)
In the vanilla version of FreeRTOS everything (tasks, coroutines, data etc.) lives in one physical address space. There is no ‘process’ concept, no memory protection and thus one could regard the whole application as one big process. BUT a patched version of FreeRTOS which is called FreeRTOS-MPU allows developers to protect certain memory regions and then the concept of a process might become relevant again…