Let's return to our discussion of threads and processes, this time from the perspective of a real live system. Then, we'll take a look at the function calls used to deal with threads and processes.
We know that a process can have one or more threads. (A process that had zero threads wouldn't be able to do anything—there'd be nobody home, so to speak, to actually perform any useful work.) A QNX Neutrino system can have one or more processes. (The same discussion applies—a QNX Neutrino system with zero processes wouldn't do anything.)
So what do these processes and threads do? Ultimately, they form a system—a collection of threads and processes that performs some goal.
At the highest level, the system consists of a number of processes. Each process is responsible for providing a service of some nature—whether it's a filesystem, a display driver, data acquisition module, control module, or whatever.
Within each process, there may be a number of threads. The number of threads varies. One designer using only one thread may accomplish the same functionality as another designer using five threads. Some problems lend themselves to being multithreaded, and are in fact relatively simple to solve, while other processes lend themselves to being single-threaded, and are difficult to make multithreaded.
The topic of designing with threads could easily occupy another book—we'll just stick with the basics here.