EmbeddedSoftware4
EmbeddedSoftware4
• Process or Thread?
• Processes
• Threads
• Scheduling
PROCESS OR THREAD?
• Part of the address space is mapped to a file that contains the code and static
data that the program is running
• As the program runs, it will allocate resources such as stack space, heap memory,
references to files, etc.
• When the process terminates, these resources are reclaimed by the system
• all the memory is freed up and all the file descriptors are closed
• Processes can communicate with each other using inter-process communication
(IPC), such as local sockets
THREAD IN SHORT
• A thread is a thread of execution within a process.
• All processes begin with one thread that runs the main()function
• called the main thread
• You can create additional threads, for example, using the POSIX function
pthread_create()
• Results in multiple threads executing in the same address space
• Being in the same process, the threads share resources with each other
• They can read and write the same memory and use the same file
descriptors
• Communication between threads is easy
• Take care of the synchronization and locking issues
TWO EXTREME DESIGNS
• FIFO and named pipe are just different terms for the same thing
• An extension of the anonymous pipe used to communicate between parent and
child processes when implementing pipes in the shell
• A FIFO is a special sort of file, created by the mkfifo()command.
• As with Unix sockets, the file access permissions determine who can read and write
• They are unidirectional
• There is one reader and usually one writer, but there may be several
• The data is a pure byte stream but with a guarantee of the atomicity of messages
that are smaller than the buffer associated with the pipe
• Writes less than this size will not be split into several smaller writes and
• Read the whole message in one go as long as the size of the buffer is large enough
• The default size of the FIFO buffer is 64 KiB on modern kernels
• Can be increased using fcntl()with F_SETPIPE_SZ up to the value in
/proc/sys/fs/pipe-max-size
• typically 1 MiB
• There is no concept of priority
POSIX MESSAGE QUEUES
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int main(void)
#include <sys/syscall.h> {
pthread_t t;
printf("Main thread, PID %d TID %d\n",
static void *thread_fn(void *arg) getpid(), (pid_t)syscall(SYS_gettid));
{ pthread_create(&t, NULL, thread_fn, NULL);
pthread_join(t, NULL);
printf("New thread started, PID %d TID %d\n", return 0;
getpid(), (pid_t)syscall(SYS_gettid)); }
sleep(10);
printf("New thread terminating\n");
return NULL;
}
TERMINATING A THREAD
• Big advantage of threads: they share the address space and can share
memory variables
• Big disadvantage: It requires synchronization to preserve data consistency
• In fact, threads can create private memory using thread local storage (TLS),
but not covered here
• The pthreads interface provides the basics necessary to achieve
synchronization:
• mutexes and condition variables
• If you want more complex structures, you will have to build them yourself
• All of the IPC methods described earlier, that is sockets, pipes and message
queues, work equally well between threads in the same process
MUTUAL EXCLUSION
• To write robust programs, you need to protect each shared resource with a
mutex lock
• make sure that every code path that reads or writes the resource has locked the
mutex first
• Problems which still remain:
• Deadlocks: system is locked completely, because of mutual wait for several mutexes
• Solution: same order locking, timeouts, back-off periods
• Priority inversion: high priority thread becomes blocked waiting for a mutex locked
by a low priority thread
• Solution: priority inheritance, priority ceiling
• Poor performance: usually mutexes have minimal overhead, but performance
problems occur, if threads block on them most of the time
• Solution: proper design
CHANGING CONDITIONS