Some definitions
Different operating systems often have different meanings for
terms such as process,
thread,
task,
program,
and so on.
In the QNX OS, an application typically means a collection of processes, although sometimes—especially for UI pieces—it can mean just one process. A program is the file generated as the result of a compile and link operation; when you run a program on a QNX target, this creates a process; a process is, basically, a particular instance of a running program.
A thread is a single flow of execution or control. At the lowest level, this equates to the program counter or instruction pointer register advancing through some machine instructions. Each thread has its own current value for this register.
A process is a collection of resources shared by one or more threads. These resources include at least the following:
- all code and data in the process, including all nonlocal (nonstack) variables
- signal handlers (although you typically have one thread that handles
signals, and you block them in all the other threads)
Note:The kernel saves and restores the FPU context on entering and leaving signal handlers, so it's safe to use floating-point operations in them.
- signal ignore state
- file descriptors (fds), and their relatives, such as sockets, mqueue descriptors, etc.
- channels
- side-channel connections
Along with ownership of these resources goes cleanup. When a process terminates, all process-owned resources are cleaned up, including terminating all threads, releasing all memory, closing all file descriptors, etc. This happens for both normal termination (e.g., calling exit()) and abnormal termination (e.g., dying due to accessing invalid memory).
Threads don't share such things as stack, register values, processor affinity, and a few other things.
Two threads residing in two different processes don't share very much. About the only thing they do share is the CPU, and maybe not even that if they're running on a multicore processor. Threads in different processes can share memory, but this takes takes a little setup (see shm_open() in the C Library Reference for an example).
When you run a program (creating a process), you're automatically running a thread.
This thread is called the main
thread, since the first programmer-provided function that runs in a C program is
main().
The main thread can then create additional threads if need be.
A few things are special about the main thread. One is that if it returns normally, the code it returns to calls exit(). Calling exit() terminates the process, meaning that all threads in the process are terminated. So when you return normally from the main thread, the process is terminated. When other threads in the process return normally, the code they return to calls pthread_exit(), which terminates just that thread.
Another special thing about the main thread is that if it terminates in such a manner that the process is still around (e.g., it calls pthread_exit() and there are other threads in the process), then the memory for the main thread's stack isn't freed up. This is because the command-line arguments are on that stack and other threads may need them. If any other thread terminates, then that thread's stack is freed.