3. OS Performs following Actions While
creating Process
Assign Process Id and Priority
Allocating Memory and other
resources
Set up the Process environment
Creating PCB
Return Process Id
5. Process ID
Priority
Process State
PSW
CPU register
Event Information
Memory Allocation
Resource Held
PCB Pointer
Process
Scheduling
Information
PSW & CPU reg
information
Info for which
process is waiting
Pointer to another
PCB
Process Control Block(PCB)
7. Parent process create children processes, which, in turn create other
processes, forming a tree of processes.
Resource sharing
✦ Parent and children share all resources.
✦ Children share subset of parent’s resources.
✦ Child will not exceed resource limits on that process.
Execution
✦ Parent and children execute concurrently.
✦ Parent waits until children terminate.
Process Creation
8. ✦ fork system call creates new process
✦ exec system call used after a fork to
replace the process’ memory space with a new program
Process Creation (Cont.)
The system calls used for the creation of the process:
9. 1.A call to fork() will create a completely separate sub-
process which will be exactly the same as the parent.
2.The process that initiates the call to fork is called the
parent process.
3.The new process created by fork is called the child
process.
4.The child gets a copy of the parent's text and memory
space.
5.They do not share the same memory .
Fork()
10. fork() system call returns an integer to both the parent
and child processes:
-1 this indicates an error with no child process
created.
A value of zero indicates that the child process code is
being executed.
Positive integers represent the child’s process
identifier (PID) and the code being executed is in the
parent’s process.
Fork(contd.)
11. if ( (pid = fork()) == 0)
printf(“I am the childn”);
else
printf(“I am the parentn”);
Simple Fork Example
12. Calling one of the exec() family will terminate the currently
running program and starts executing a new one which is
specified in the parameters of exec in the context of the
existing process. The process id is not changed.
exec()
13. • int execl( const char *path, const char *arg, ...);
• int execlp( const char *file, const char *arg, ...);
• int execle( const char *path, const char *arg , ..., char * const envp[]);
• int execv( const char *path, char *const argv[]);
• int execvp( const char *file, char *const argv[]);
Exec family of functions
16. UNIX Pipes
• Pipe sets up communication channel between two
(related) processes.
Two processes connected by a pipe
17. • One process writes to the pipe, the other reads from the
pipe.
• Looks exactly the same as reading from/to a file.
• System call:
int fd[2] ;
pipe(&fd[0]) ;
fd[0] now holds descriptor to read from pipe
fd[1] now holds descriptor to write into pipe
UNIX Pipes
18. #include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
char *message = "This is a message!!!" ;
main()
{ char buf[1024] ;
int fd[2];
pipe(fd); /*create pipe*/
if (fork() != 0) { /* I am the parent */
write(fd[1], message, strlen (message) + 1) ;
}
else { /*Child code */
read(fd[0], buf, 1024) ;
printf("Got this from MaMa!!: %sn", buf) ;
}
}
UNIX Pipes
19. Shared Memory
Common chunk of read/write memory
among processes
Proc. 1 Proc. 2
ptr
Attach
Proc. 3 Proc. 4 Proc. 5
ptr ptr ptr
ptr
Attach
Create
Shared Memory
(unique key)
0
MAX
20. Creating Shared Memory
int shmget(key_t key, size_t size, int shmflg);
Example:
key_t key;
int shmid;
key = ftok(“<somefile>", ‘A');
shmid = shmget(key, 1024, 0644 | IPC_CREAT);
Here’s an example: shm_create.c.
21. Attach and Detach
Shared Memory
void *shmat(int shmid, void *shmaddr, int shmflg);
int shmdt(void *shmaddr);
Example:
key_t key;
int shmid;
char *data;
key = ftok("<somefile>", ‘A');
shmid = shmget(key, 1024, 0644);
data = shmat(shmid, (void *)0, 0);
shmdt(data);
Here’s an shm_attach.c
22. Deleting Shared Memory
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmctl(shmid, IPC_RMID, NULL);
Example: Shm_delete.c
23. FIFOs (named pipes)
FIFOs are sometimes called named pipes. Pipes can be
used only between related processes when a common
ancestor has created the pipe. With FIFOs, unrelated
processes can exchange data.
Creating a FIFO is similar to creating a file.
#include <sys/ stat.h>
int mkfifo( const char *pathname, mode_t mode);
Returns: 0 if OK,-1 on error.
24. Opening a FIFO
● open(pathname, O_RDONLY)
● Open read end
● open(pathname, O_WRONLY)
● Open write end
● open() locks until other end is opened
● Opens are synchronized
open(pathname, O_RDONLY |
O_NONBLOCK) can be useful
25. Message Queues
● Message-oriented communication
● Receiver reads messages one at a time
– No partial or multiple message reads
● Unlike pipes, multiple readers/writers can be useful
● Messages have priorities
● Delivered in priority order
● Message notification feature
26. Message queue operations
Int msgget(key_t, int flag)
Int msgctl(int msgid, int cmd, struct msgid_ds *buf)
Int msgsnd(int msgid, const void *ptr, size nbytes, int flag);
Int msgrcv(int msgid, void *ptr, size_t nbytes, long type, int flag);
27. Semaphores
• A semaphore is a counter used to provide access to a shared
data object for multiple processes.
• To obtain a shared resource, a process needs to do the
following:
1.Test the semaphore that controls the resource.
1. If the value of the semaphore is positive, the process can use
the resource. In this case, the process decrements the
semaphore value by 1, indicating that it has used one unit of
the resource.
28. 3.If the value of the semaphore is 0, the process goes to sleep
until the semaphore value is greater than 0. When the
process wakes up, it returns to step 1.
29. • The first function to call is semget to obtain a semaphore ID.
#include <sys/ sem.h>
int semget(key_t key, int nsems, int flag);
Returns: semaphore ID if OK, -1 on error.
• The number of semaphores in the set is nsems. If a new set is
being created (typically in the server), we must specify
nsems. If we are referencing an existing set (a client), we
can specify nsems as 0.
30. semget()
Gets a semaphore set. The value returned is its id, for use
with other calls.
int semget(key_t key, int n, int flags);
key is the key associated with the semaphore set you want.
Don’t think about it—just use IPC PRIVATE. n is the number of
semaphores the set should contain. flags specifies how how
the set should be allocated. SHM R | SHM W is the best thing
to pass.
31. semop()
Performs a semaphore operation (i.e. incrementing, decrementing,
etc.) on the selected members of a semaphore set. This is one of
those ones that should really be a bunch of seperate calls.
int semop(int id, struct sembuf* op, unsigned n);
id is the semaphore set’s id. op is the operation to perform. n is
the number of semaphores to affect. You’ll nearly always be
passing in a value of 1 here. struct sembuf’s sem op field is
important. It specifies what you want to do to the semaphore, be
it incrementing, decrementing, or toasting over an open fire8 . • A
non-zero value will be added to the semaphore’s value. Note that
this means negative values indicate subtraction. • A value of zero
will make the operation block until the semaphore value becomes
zero.
32. semctl()
A bit like shmctl(), but for semaphores. Again, ridiculously
overcomplicated.
int semctl(int id, int iSem, int cmd, union semun arg);
id is the semaphore set id. iSem is the semaphore you want
to twiddle. Only valid with some of the commands. cmd is the
command you want to perform. arg is used for fiddling with
semaphore values. With everything but cmd set to SETALL,
just pass NULL. There are two values for cmd worth looking
at: SETALL and IPC RMID. For details on the others, type man
semctl.
34. Signals
• A signal is a mechanism for notifying a program that
some event has occurred.
• intuition: signal “software interrupt”
• when a signal is sent to a program, its normal execution is
interrupted
• depending on (1) the state of the program, and (2) the type of
signal, the program may
• enter some pre-specified signal handler; or
• take some default action.
35. Example Signals (not a complete list)
Signal Name Number Description
SIGHUP 1 Hangup (POSIX)
SIGINT 2 Terminal interrupt (ANSI)
SIGQUIT 3 Terminal quit (POSIX)
SIGILL 4 Illegal instruction (ANSI)
SIGTRAP 5 Trace trap (POSIX)
SIGFPE 8 Floating point exception (ANSI)
SIGKILL 9 Kill(can't be caught or ignored) (POSIX)
SIGSEGV 11 Invalid memory segment access (ANSI)
SIGTERM 15 Termination (ANSI)
SIGSTKFLT 16 Stack fault
SIGSTOP 19 Stop executing(can't be caught or ignored) (POSIX)
SIGPROF 27 Profiling alarm clock (4.2 BSD)
SIGWINCH 28 Window size change (4.3 BSD, Sun)
SIGPWR 30 Power failure restart (System V)
… … …
37. Synchronous vs. Asynchronous Signals
• Synchronous signals:
• arise from executing an instruction in the process’s instruction
stream
• e.g.: illegal instruction (SIGILL); illegal address (SIGSEGV)
• causes a trap into the OS kernel trap handler
• sometimes referred to as “traps”
• directed to the process/thread that executed the instruction
• Asynchronous signals:
• source is external to the current execution
• e.g.: profiling clock (SIGPROF); terminal interrupt, ^C (SIGINT)
38. Signal Handling
• Use the signal handling library: signal.h
• Then can use the signal call:
#include <signal.h>
void (*signal( int sig, void (*handler)(int))) (int) ;
• signal returns a pointer to the PREVIOUS signal
handler
• #include <signal.h>
typedef void Sigfunc(int); /* my defn */
Sigfunc *signal( int signo, Sigfunc *handler );
Signal is a function
that takes two
arguments:
sig and handler
The signal to be
caught or ignored
is given as argument
sig
The function to be called
when the specified signal
is received is given as a
pointer to the function
handler
The handler function
Receives a single integer
Argument and returns void
The signal function itself
returns a pointer to a function.
The return type is the same
as the function that is passed in,
i.e., a function that takes an
int and returns a void
The returned function
takes a integer
parameter.
41. Behind the scenes of a SIGSEGV
• When a program tries to access a bad address:
• execution traps into the OS kernel
• if no handler is specified:
• kernel invokes the default handler
• default handler prints out “Segmentation fault” and kills the
process
• if a handler is specified:
• kernel executes the handler
• the expectation is that the handler fixes the problem
• restarts the offending operation
• this allows programmer-controlled recovery from errors
42. Sending signals
• A program can send a signal to another program using
the kill() system call:
int kill(pid_t pid, int sig)
sends the signal number sig to process pid
(see /usr/include/asm-generic/signal.h)
• A user can send a signal from the command line using
the kill command:
kill –N pid
E.g., “kill -9 pid” (9 = SIGKILL)
43. Sending Signals via Function Call
raise()
int raise(int iSig);
• Commands OS to send a signal of type iSig to current process
• Returns 0 to indicate success, non-0 to indicate failure
Example
int ret = raise(SIGINT); /* Process commits suicide. */
assert(ret != 0); /* Shouldn't get here. */
44. Sending Signals via Function Call
kill()
int kill(pid_t iPid, int iSig);
• Sends a iSig signal to the process whose id is iPid
• Equivalent to raise(iSig) when iPid is the id of current process
• Editorial comment: Better function name would be sendsig()
Example
pid_t iPid = getpid(); /* Process gets its id.*/
kill(iPid, SIGINT); /* Process sends itself a
SIGINT signal (commits
suicide?) */
45. • Suspend the calling process until a signal is
caught.
• #include <unistd.h>
int pause(void);
• Returns -1 with errno assigned EINTR.
(Linux assigns it ERESTARTNOHAND).
• pause() only returns after a signal handler has
returned.
pause()
46. alarm()
• Set an alarm timer that will ‘ring’ after a specified
number of seconds
• a SIGALRM signal is generated
• #include <unistd.h>
long alarm(long secs);
• Returns 0 or number of seconds until previously set
alarm would have ‘rung’.
47. Installing a Signal Handler
signal()
sighandler_t signal(int iSig,
sighandler_t pfHandler);
• Installs function pfHandler as the handler for signals
of type iSig
• pfHandler is a function pointer:
typedef void (*sighandler_t)(int);
• Returns the old handler on success, SIG_ERR on error
• After call, pfHandler is invoked whenever process
receives a signal of type iSig
48. Installing a Handler Example 2
Program testsignalall.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <signal.h>
static void myHandler(int iSig) {
printf("In myHandler with argument %dn", iSig);
}
…
50. Installing a Handler Example 2 (cont.)
Program testsignalall.c (cont.):
…
/* Etc., for every signal. */
printf("Entering an infinite loopn");
for (;;)
;
return 0;
}