OS Lab Tutorial 1
Spawning processes
Shared memory
The Spawn
exec() family
fork()
The exec() Functions:
Out with the old, in with the new
The exec() functions all
replace
the current program running within the process withanother
programbring up an xterm:
exec sleep 5 #what happens and
why
?There are two families of exec() functions, the “l”
family (list), and the “v” family (vector)
Each exec() call can choose different ways of finding the executable and whether the environment is
delivered in the form of a list or an array (vector)
The environment, open file handles, etc. are passed into the exec’d program
What is the return value of an exec() call?
The execl... functions
int execl(const char * path, const char * arg0, ...);
executes the command at path, passing it the environment as a list: arg0 ... argn
thus, the execl family breaks down argv into its individual constituents, and then passes them as a list to the execl?
function (the l stands for list)
int execlp(const char * path, const char * arg0, ...);
same as execl, but uses $PATH resolution for locating the program in path, thus an absolute pathname is not
necessary
int execle(const char * path, const char * arg0, ... char * envp[]);
allows you to specifically set the new program’s
environment, which replaces the default current program’s environment
The execv... functions
int execv(const char * path, char *const argv[]);
executes the command at path, passing it the environment contained in a single argv[]
vector
int execvp(const char * path, char *const argv[]);
same as execv, but uses $PATH resolution for locating the program in
path
int execve(const char * path, char *const argv[], char * const envp[]);
note that this is the only system call of the lot
fork()
fork() creates a new child process
the OS copies the current program into the
new process , resets the program pointer to the start of the new program (child fork
location), and both processes continue execution independently as two separate processes
The child gets its own copy of the parent’s:
data segments
heap segment
stack segment
file descriptors
fork() Return Values
fork() is the one Unix function that is called
once but returns twice :
If fork() returns 0:
you’re in the new child process
If fork() returns > 1 (i.e., the pid of the new child process)
you’re back in the parent process
Waiting on Our Children
Unlike life, parents should always hang around for their children’s lives (runtimes) to end, that is to say:
Parent processes should always wait for their child processes to end
When a child process dies, a SIGCHLD signal is sent to the parent as notification
The SIGCHLD signal’s default disposition is to ignore the signal
A parent can find out the exit status of a child process by calling one of the wait() functions
Waiting on Our Children
Parent processes find out the exit status of their children by executing a wait() call:
pid_t wait(int * status);
pid_t waitpid(pid_t pid, int * status, int options);
Wait()
blocks
until it receives the exit status from a childWaitpid can wait on a specific child, and doesn’t necessarily block (WNOHANG)
Waiting allows the parent to obtain the
return value
from the child’s process
waitpid()
pid_t waitpid(pid_t pid, int * status, int options);
pid can be any of 4 values:
< - 1: wait for any child whose gpid is the same as pid
== - 1: waits for any child to terminate
== 0: waits for a child in the same process group as the current process
> 0: waits for process pid to exit
The following macros work on status:
WIFEXITED(status): true if process exited normally
WIFSIGNALED(status): true if process was killed by a signal
Sleeping
unsigned int sleep (unsigned int seconds)
The sleep function is declared in
`unistd.h'.
The sleep function waits for seconds or until a signal is delivered, whichever
happens first.
If sleep function returns because the
requested interval is over, it returns a
value of zero. If it returns because of
delivery of a signal, its return value is
Working with shared memory
There are 4 stages to be executed while using shared memory
Tell the OS we want a shared memory object
Map the object to the process’ memory (virtual)
Unmap the memory from the process’ memory
Delete the shared memory object
Important: IPC objects are never deleted
unless explicitly deleted or the computer is
rebooted
shmget - allocates a shared memory segment
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
DESCRIPTION
shmget() returns the identifier of the shared memory segment
associated with the value of the argument key. A new shared memory segment, with size equal to the value of size rounded up to a multiple of PAGE_SIZE, is created if key has the value IPC_PRIVATE or key isn't IPC_PRIVATE, no shared memory segment corresponding to key exists, and IPC_CREAT is asserted in shmflg (i.e.
shmflg&IPC_CREAT isn't zero).
In practice
Shared memory flags ( shmflg )
The value shmflg is composed of:
IPC_CREAT
to create a new segment. If this flag is not used, then shmget() will find the segment associated with key and check to see if the user has permission to access the
segment.
IPC_EXCL
used with IPC_CREAT to ensure failure if the segment already exists.
mode_flags (lowest 9 bits)
specifying the permissions granted to the owner, group, and world. Presently, the execute permissions are not used by the system.
In practice(2)
shmat – attching a shared memory segment to a process
SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
DESCRIPTION
shmid – segment id prevousy allocated by shmget
shmaddr – if is NULL, the system chooses a suitable (unused) address at which to attach the segment. Otherwise, it is used as the (virtual) address for attachment
Flags
shmflg
SHM_RND - the address equal to
shmaddr
rounded down to the nearest multiple of
SHMLBA. Otherwise
shmaddr
must be a page- aligned address at which the attach occurs.SHM_RDONLY - segment is attached for
reading. Otherwise the segment is attached for read and write
In practice(3)
shmdt – detaches a previously attached shared memory
SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void * shmaddr );
In practice(4)
shmctl - shared memory control
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
DESCRIPTION
shmctl() allows the user to receive information on a shared memory segment, set the owner, group, and permissions of a shared memory segment, or destroy a segment.
The shmctl commands
IPC_STAT
is used to copy the information about the shared memory segment into the buffer buf.
IPC_SET
is used to apply the changes the user has made to the uid, gid, or mode members of the shm_perms field. Only the lowest 9 bits of mode are used. The shm_ctime member is also updated. The user must be the owner, creator, or the super-user.
IPC_RMID
is used to mark the segment as destroyed. It will actually be destroyed after the last detach. The user must be the
owner, creator, or the super-user.
Father-son relationship
fork()
After a fork() the child inherits the attached shared memory segments.
exec()
After an exec() all attached shared memory segments are detached (not destroyed).
exit()
Upon exit() all attached shared memory segments are detached (not destroyed).
Assignment 1
Write a program p1 which will accept two arguments: delay and string. It then prints
string on screen every delay seconds.
Write a program p2 which will prompt the
user for delay and string. It will then spawn a
copy of p1 to deal with these arguments, and
itself continue to prompt the user for another
set of arguments ( delay and string ) .
Assignment 1
Exiting:
p1 exits cleanly with SIGUSR1
p2 exits cleanly when given the input
“quit”. It should call for all its children to exit before quitting.
Coding conventions:
Use indent command to indent code