System V IPC

advertisement
System V IPC
Provides three mechanisms for InterProcess
Communication (IPC) :
 Messages : exchange messages with any
process or server.
 Semaphores : allow unrelated processes to
synchronize execution.
 Shared memory : allow unrelated processes to
share memory.
Semaphores - General
Used to monitor and control the availability
of system resources such as shared
memory segments.
 Can be operated on as individual units or
as elements in a set.
 A semaphore set consists of a control
structure and an array of individual
semaphores (default 25 elements).

Semaphores - Functions

The semget() function initializes or gains access
to a semaphore.




semid = semget (key_t key, int nsems, int semflg);
key : value associated with the semaphore ID
nsems : number of semaphores in array
semflg :
 IPC_CREAT used to create a new resource
 IPC_EXCL used with IPC_CREAT to ensure failure if the
resource exists.
 rwxrwxrwx access permissions.
returns : semid on success. -1 on failure.
Semaphores - Functions

The semctl() function allows a process to alter
permissions and other characteristics of a
semaphore set.
int semctl (int semid, int semnum, int cmd, union semun arg);

semid : id obtained by a call to semget().
 cmd : control flags





GETVAL
SETVAL
etc…
returns : 0 on success. -1 on failure.
arg is a union : (usually optional)
union semun{
int val;
struct semid_ds *buf;
ushort *array;
}
Semaphores - Functions




The semop() function performs operations on a
semaphore set.
int semop (int semid, struct sembuf *sops, unsigned nsops);
semid : id obtained by a call to semget().
sops : array of semaphore operations.
nsops : number of operations in array.
Operations are described by a structure sembuf:
struct sembuf{
ushort sem_num;
short sem_op;
short sem_flg;
}
/* semaphore index in array */
/* semaphore operation */
/* operation flags */.
Shared Memory - General



An efficient means of passing data between
processes.
One process will create a memory portion which
other processes (if permitted) can access.
When write access is allowed for more than one
process, an outside protocol or mechanism such
as a semaphore can be used to prevent
inconsistencies and collisions.
Shared Memory - Functions

The shmget() function is used to obtain access to
a shared memory segment.



shmid=shmget(key_t key, int size, int shmflg);
key : key value of shared memory
size : size of the segment in bytes
shmflg :




IPC_CREAT used to create a new resource
IPC_EXCL used with IPC_CREAT to ensure failure if the resource
exists.
rwxrwxrwx access permissions.
returns : shmid on success. -1 on failure.
Shared Memory - Functions



The shmctl() is used to alter the permissions and
other characteristics of a shared memory
segment.
int shmctl (int shmid, int cmd, struct shmid_ds *buf);
shmid : id got from call to shmget().
cmd :control commands

IPC_RMID
 IPC_SET
 IPC_STAT
 etc…


buf : used to read (IPC_STAT) or write (IPC_SET) information.
returns : 0 on success, -1 on failure.
Shared Memory - Functions

shmat() and shmdt() functions are used to attach
and detach shared memory segments
respectively.
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
shmat() returns a pointer to the head of the shared segment associated
with a valid shmid.( values of shmaddr and shmflg are usually set to
0)
shmdt() detaches the shared memory segment located at the address
indicated by shmaddr. returns : 0 on success. -1 on failure
Shared Memory – Example(1/7)

shm_server.c
 creates

the string and shared memory portion.
shm_client.c
 attaches
itself to the created shared memory
portion and uses the string
Shared Memory – Example(2/7)
shm_server.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSZ
27
main(){
char c;
int shmid;
key_t key;
char *shm, *s;
/*
* We'll name our shared memory segment
* "5678".
*/
key = 5678;
Shared Memory – Example(3/7)
/*
* Create the segment.
*/
if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
perror("shmget"); exit(1); }
/*
* Now we attach the segment to our data space.
*/
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat"); exit(1); }
/*
* Now put some things into the memory for the
* other process to read.
*/
s = shm;
Shared Memory – Example(4/7)
for (c = 'a'; c <= 'z'; c++)
*s++ = c;
*s = NULL;
/*
* Finally, we wait until the other process
* changes the first character of our memory
* to '*', indicating that it has read what * we put there.
*/
while (*shm != '*')
sleep(1);
exit(0);
} /*main*/
Shared Memory – Example(5/7)
shm_client.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSZ
27
main(){
int shmid;
key_t key;
char *shm, *s;
/*
* We need to get the segment named
* "5678", created by the server.
*/
key = 5678;
Shared Memory – Example(6/7)
/*
* Locate the segment.
*/
if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
perror("shmget"); exit(1); }
/*
* Now we attach the segment to our data space.
*/
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat"); exit(1); }
Shared Memory – Example(7/7)
/*
* Now read what the server put in the memory.
*/
for (s = shm; *s != NULL; s++)
putchar(*s);
putchar('\n');
/*
* Finally, change the first character of the
* segment to '*', indicating we have read
* the segment.
*/
*shm = '*';
exit(0);
} /*main*/
System calls
Are functions that used to control user
processes
 fork()
 exit()

wait()
The fork() System Call (1)
A process calling fork() spawns a child
process.
 The child is almost an identical clone of
the parent:

 Program
 Stack
 Data
Text
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
The fork() System Call (2)



The fork() is one of the those system calls,
which is called once, but returns twice!
After fork() both the parent and the child
are executing the same program.
Consider a piece of program
On error, fork() returns -1
(see fork_pid.c example):
PID=28
PID=28
PID=34
fork()
p1
p1
c1
...
pid_t pid = fork();
printf(“PID: %d\n”, pid);
...
The parent will print:
PID: 34
And the child will always print:
PID: 0
The fork() System Call (3)
Remember, after fork() the execution
order is not guaranteed.
 Simple fork() examples:

 fork_pid.c
prints out return from fork()
 fork_child.c fork_child.c distinguishes
between the parent and the child
fork_pid.c
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv)
{
pid_t pid = fork();
printf("PID: %d\n", pid);
exit(0);
I
}
/*pid is actually an integer*/
/*Child will print 0, parent an ID specified by
the OS*/
/*Βoth terminate right after, not very exciting,
know.*/
fork_child.c
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
pid_t pid = fork();
printf("PID: %d\n", pid);
if(pid == 0)
{
/* fork a child */
/* both execute this line */
/* child plays here */
printf("Hello I'm a child!! My PID=%d\n", getpid());
}
else
{
/* parent goes here */
printf("Hi! I'm a parent (my PID=%d) of the child with PID=%d\n", getpid(), pid);
}
/* both terminate */
printf("Process with PID=%d terminates...\n", getpid());
exit(0);
}
The exit() System Call
#include <stdlib.h>
void exit(int status);




This call gracefully terminates process execution.
Gracefully means it does clean up and release of
resources, and puts the process into the zombie state.
By calling wait(), the parent cleans up all its zombie
children.
exit() specifies a return value from the program, which a
parent process might want to examine as well as status of
the dead process.
_exit() call is another possibility of quick death without
cleanup.
The wait() System Call

Forces the parent to suspend execution,
i.e. wait for its children or a specific child
to die (terminate is more appropriate
terminology, but a bit less common).
The wait() System Call (2)
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);




The wait() causes the parent to wait for any child
process.
The waitpid() waits for the child with specific PID.
The status, if not NULL, stores exit information of the
child
The return value is:


PID of the exited process, if no error
(-1) if an error has happened
References
man 2 fork
 man 2 wait
 man 3 exit

Download