linux development lecture 9 15.02.2016. agenda process id process spawning process communication...
DESCRIPTION
Process spawningTRANSCRIPT
Linux DevelopmentLecture 9
15.02.2016
Agenda• Process ID• Process spawning• Process communication• Process signals• Deadlock• Deadlock handling• Mutex• Semaphore
Process spawning
Process ID• Every processhas a pid (ProcessID), a ppid (Parent
ProcessID), and a pgid (ProcessGroup ID). In addition every process has program code, data, variables, le descriptors, and an environment. • PID > 0 && PID <= 32768
Checking PIDs• #include <unistd.h> • pid_t getpid (void);
pid_t getppid (void) ;pid_t getpgid (void);
Process group• Besides having a pid, every process is also a member of
a process group. The Process Group ID (pgid) is also a positive integer, expressedin the pid_t type. Processescan join or leave process groups.
Process leader (Process parent)• A process group has a leader which has pid = pgid. The
group continues even if the group leader terminates, ending only when all of its members terminate.
Process group functions#include <unistd.h> int setpgid (pid_t pid, pid_t pgid);pid_t getpgid(pid_t pid);int setpgrp(void);pid_t getpgrp(void);
Process group functions• The function setpgid() sets the pgid of process pid to
pgid. If pid = 0,the current processpid is used. If pgid = O the pgid of process pid is used. • The function getpgid() returns the pgid of process pid. If
pid = O,the current process pid is used. • The function setpgrp() is equivalent to setpgid(0,0).• The function get-.pgrp() is equivalent to getpgid(0). • On success, these functions return 0. On failure, they
return -1 with errno set. The possible error returns are:
Process spawning
Using system()• int system (const char *cmd); // stdlib.h must be included• The system() call runs a process from inside another program: • In effect, system() invokes /bin/sh c cmd and sends the output
of cmd to standard output. • On success system() returns the exit code for cmd; if it fails
because it can t start a shell it returns 127 with any other error returning -1. • The calling program will block, waiting for system() to
complete its actions. One can use & to run cmd as a background process but results can be unpredictable.
Using fork()• Creating a new(child) process without terminating the
old one can be done with: #include <unistd.h>#include <sys/types.h>pid_t fork(void);
Using fork()• After a fork() two processes are running. The child
inherits the parent s resources. Only the pid, ppid, file locks and pending signals are not carried forth. File descriptors, memory, etc., are inherited. However, Linux uses a copy on-write implementation, so memory is not duplicated until it is actually altered.
Using vfork()• An additional process creation call, vfork() creates a
child that shares the memory address space of the parent. To prevent the parent from stepping on the child s use of the memory, the parent s execution is blocked until the child exits or issues an execve() call. Note that the child cannot writeto this address space and thus there is no need to copy page table entries.
Using exec()• #include <unisted.h>• int execl(const char *path, const char *arg, …...);• int execlp(const char *path, const char *arg, …...);• int execle(const char *path, const char *arg, …...);• int execv(const char *path, const char *argv[], …...);• int execvp(const char *path, const char *argv[], …...);• int execve(const char *path, const char *argv[], …...);
Using exec()• Replace the spawner process with the new one. The
new process has the same PID as the spawner. The new process is inheriting memory and open files from the old.• There should be no return value, if everything went fine.
If there is an error it will be returned.
Using clone()• In addition to the traditional fork() call that generates a
child that is a full peer to the parent,a so called heavyweight process, Linux permits the creation of so-called lightweight processes that share many kernel data structures (including memory areas) between parents and children; this is the basis of the multi-threaded programming implementation under Linux. • Used only for specific spawn purposes.
Exiting• There are several functions that are ending a process:• Void _exit(int status) // defined in unistd.h• Void exit(int status) // defined in stdlib.h• Void abort(void) //defined in stdlib.h
Normal termination• Calling return(int) – same as calling exit(int)• Calling exit(int) :• All open streams are flushed and closed• All handlers registred atexit() amd on_exit() are called• _exit(int) is called
• Calling _exit(int)• All files are closed, child processes are inherited by proces init
(PID:1) and SIGCHLD is sent to the parent process
Abnormal termination• An abort() generates SIGABRT and causes a core dump
to be generated. All open streams are flushed and closed. If SIGABRT is blocked or ignored, abort() will still terminate and core dump, but if the signal is caught it may be avoided.
Exit handlers• int atexit (void (*function)(void)); // defined in stdlib.h• int on_exit(void (*function)(int, void*), void *arg);
• Functions return 0 on success and -1 on error
Waiting• The parent process can wait (suspend execution) until
one of its child processes dies or is stopped, or a signal interrupts it.
• pid_t wait (int *status);• pid_t waitpid (pid_t pid, int * status, int options);
Waiting• pid value:• Pid < -1 : waiting for any child process with a process group id
= -pid• Pid = -1 : waiting for any child process (same as wait())• Pid = 0 : wait for any child process whose process group id is
the same as the calling process• Pid > 0 : wait for child process with ID = pid
Waiting• Return values:• EINVAL : option argument is invalid• ECHILD : pid doesn’t exist or it is not a child of the calling
process• ERESTARTSYS : SIGCHLD was caught.
Pipes and FIFOs
Pipes• Pipes permit processes to exchange data, not just short
signals. These processes may either be independent or have a parent child relationship. • A process may also use a pipe to receive input from or
direct output to a command.
popen() & pclose()• These functions are used to open and close a pipe using
the standard I/O library: • #include <stdio.h> • FILE *popen (const char *command, const char *mode); • int pclose (FILE *stream);
popen()• popen() initiates a processby creating a pipe, forking,
and invoking the shell, using the system() call. • The mode argument is the same as that used in fopen().
However it can take only the values r or w . Disallowed are r+ or w+ and append modes. • The command argument points to a null terminated
string which contains a shell command line which is passed to /bin/sh using the -c ag. (which reads commands from command and does any required interpretation. .)
pclose()• pclose() waits for the associated process to terminate
and returns the exit status of the command. On error it return -1 if an error is detected.
pipe()• The lower level pipe() function passes data between two
processes without the overhead of invoking a shell and gives more control: • A parent and child process may be connected or a
process may even connect to itself. • int pipe (int filedes[2]); • The pipe has a read end and a write end; Any data
written to filedes[1] can be read back from filedes[0]. Data is processed in a first-in, first-out (FIFO) basis.
FIFOs• Named pipes (or FIFO s) allow you to create a pipe
between two processes which may or may not have a common ancestor. FIFO stands for First In, First Out. • You can create a named pipe and wait for another
process to establish a communication link with it. • Unlike pipes, named pipes create an entry in the
lesystem that can then be accessed by another process.
FIFO creating with shell# cd /tmp# mkfifo afifo# cat < afifo & # ls -l > afifo
FIFO creating with system call• #include <sys/types.h> • #include <sys/stat.h> • int mkfifo (const char *pathname, mode_t mode ); • // for example int rc=mkfifo(“/tmp/afifo”, 0666);
FIFO• FIFO s may be opened for reading or writing but not for
both; i.e., in mode, O_RDWR is not allowed, but O_RDONLY and O_WRONLY may be used in combination with O_NONBLOK• The amount of information that can be in the pipe at
any one time is given by the size of a page of memory(which is 4096 bytes on X86) • On success 0 is returned, on error -1 is returned with
errno being set
FIFO creating with mknod• A FIFO can also be created with mknod() either as a
command line call, or a system library call: • int mknod (const char *pathname, mode_t mode, (dev_t
)0 ); • To create a FIFO entry in the filesystem, mode must be
comprised of the desired permissions, bitwise OR’ed with S_IFIFO. mnknod() is also used to create device special files.
Signals
Signals• Signals are software interrupts and provide a way to
handle asynchronous events. They provide a basic method of inter-process communication; the communicating processes may or may not be related and under most conditions the only information sent is the type of signal.
Signals• A process can send signals only to a process for which it
has the appropriate permissions .• Signals may be used to alert a process to take certain
actions or to die gracefully. For most signals, if a process receives it without first arranging to catch it the process will terminate. • If the process does not terminate execution will be
resumed by going back to the instruction that was being executed when the signal was received.• More info - $ man 7 signal
Signals available• $ kill –l• $ cat /usr/include/asm-generic/signal.h
Dispatching signals #include <sys/types.h> #include <signal.h>
int kill(pid_t pid, int sig); int raise(int sig);
kill()• kill() sends any signal to any process group or process.
Note that the sending process must have the proper permissions to send a signal to another process
raise()• raise() is used for a process to send signal to itself. • In a multithread process it sends a signal only to the
current thread
Alarm• #include <unistd.h>• Unsigned int alarm (usigned int seconds);• Sets alarm for certain amount of seconds. When the
seconds has expired a SIGALRM signal is raised.• Only one alarm is permitted per process. If another
alarm is set during countdown of one, the one is reset and started with the time of the another
Pausing and sleep• #include <unistd.h>
• int pause(void);• unsigned int sleep(unsigned int seconds);
pause()• pause() causes a process to sleep until a signal is
received. The function returns only if a signal handler is executed and that handler returns. In this case pause() returns -1 with errno set to EINTR.
sleep()• sleep() makes the current process sleep until seconds
have elapsed or a signal arrives which is not ignored. The function returns 0 if the requested time has elapsed, or the number of seconds left to sleep.
sleep()• #include <unistd.h>• void usleep(usec);
• #include <time.h>• struct timespec {time_t tv_sec; long tc_nsec;}• int nanosleep (const struct timespec *req, struct
timespec *rem);
sleep()• Usleep() – sleeps a process for microseconds• Nanosleep() – sleeps a process for nanoseconds
Signal handler• The signal handler is a handler that is responsible for
catching a signal and execute an action for handling the signal
Setting up a signal handler• #include <signal.h>
• void (*signal(int signum, void (*handler)(int)))(int);
• The signal() system call installs a new signal handler for the signal with number signum. The signal handlerissettohand1er() which may be a user specifed function,or one of the following: • SIG_IGN – ignore the signal• SIG_DFL – reset the signal to it’s default behaviour
Setting up a signal handler• The prototype is confusing. In practice looks like • typedef void (*sighandler_t)(int);• sighandler_t signal (int signum, sighandler_t handler);
Signal sets• It is possible to create a data type to represent multiple
signals, a so called signal set. With such a set one can tell the kernel to block, not block, or change the effect of any of the signals in the set on a given process.
Signal sets• Int sigemptyset (sigt_t *set);• Int sigfillset (sigset_t *set);• Int sigaddset (sigset_t *set, int signum);• Int sigdelset (sigset_t *set, int signum);• Int sigismember (const sigset_t *set, int signum);
Signals sets return• All functions but sigismember () return 0 on success, -1
on failiure. Sigismember () is returning 1 if the signal is member, 0 if not.
Signal sets• Int sigprocmask(int how, const sigset_t *set, sigset_t
*oldset);• Sigprocmask changes e list of currently blocked signals
according to the value of how:• SIG_BLOCK – signals from set are added to the signals of
oldset and all of them are blocked• SIG_UNBLOCK – signals specified in set are removed from
oldset
Deadlocks
Deadlock• A set of processes is deadlocked when each process in
the set is blocked awaiting an event that can only be triggered by another blocked process in the set• Typically involves processes competing for the same set of
resources• No efficient solution
Deadlock
Deadlock
Process P and Q (Deadlock is happening)
Process P and Q (Deadlock is not happening)
Deadlock conditions• Mutual exclusion• Only one process may use a resource at a time
• Hold-and-wait• A process may hold allocated resources while awaiting
assignment of others• No pre-emption• No resource can be forcibly removed form a process holding it
Dealing with deadlock• Three general approaches exist for dealing with
deadlock.• Prevent deadlock• Avoid deadlock• Detect Deadlock
Deadlock Prevention• Design a system in such a way that the possibility of
deadlock is excluded.• Two main methods• Indirect – prevent all three of the necessary conditions
occurring at once• Direct – prevent circular waits
Deadlock avoidance• A decision is made dynamically whether the current
resource allocation request will, if granted, potentially lead to a deadlock• Requires knowledge of future process requests
Deadlock avoidance• Process Initiation Denial• Do not start a process if its demands might lead to deadlock
• Resource Allocation Denial• Do not grant an incremental resource request to a process if
this allocation might lead to deadlock
Deadlock detection• Deadlock prevention strategies are very conservative; • limit access to resources and impose restrictions on processes.
• Deadlock detection strategies do the opposite• Resource requests are granted whenever possible.• Regularly check for deadlock
Mutex
Mutex• Suppose two or more processes require access to a
single nonsharable resource, such as a printer. • During the course of execution, each process will be
sending commands to the I/O device, receiving status information, sending data, and/or receiving data.• The code that needs the critical resource is called
critical section
Requirements for mutual exclusion• Only one process at a time is allowed in the critical
section for a resource• A process that halts in its noncritical section must do so
without interfering with other processes• No deadlock or starvation
Requirements for mutual exclusion• A process must not be delayed access to a critical
section when there is no other process using it• No assumptions are made about relative process speeds
or number of processes• A process remains inside its critical section for a finite
time only
Mutex POSIX• Int pthread_mutex_init(pthread_mutex_t *mutex, const
pthread_mutexattr_t *mutexattr);• Int pthread_mutex_lock(pthread_mutex_t *mutex);• Int pthread_mutex_unlock(pthread_mutex_t *mutex);• Int pthread_mutex_trylock(pthread_mutex_t *mutex);• Int pthread_mutex_destroy(pthread_mutex_t *mutex);
Semaphore
Semaphore• Multiple processes require single resource• In order to have no deadlock only one process must use
the resource.• The process to be using the resource is selected by a
integer counter
Semaphore
Semaphores POSIX• int sem_init (sem_t *sem, int pshared, unsigned int
value); • int sem_wait (sem_t *sem);• int sem_trywait (sem_t *sem);• int sem_post (sem_t *sem); • int sem_getvalue (sem_t *sem, int *sval); int
sem_destroy (sem_t *sem);
Starvation• This is the process when a process is needing a resource
which is not available.
Spinlock• This is the process when a process is waiting for a
mutex lock or semaphore
Daily task• 100 people must exit a room with one exit. Only one of
them can exit at a time and needs 200 ms to exit. Represent the peopl by spawning child processes and represent the door as a critical resource
Daily task 2• Do the same process but this time with 3 exits.