/*sem-mutex.c - demonstrates the usage of a semaphore as a
mutex that
that synchronizes accesses of
multiple processes to a file.*/
#include
<stdio.h> /* standard I/O routines. */
#include
<stdlib.h> /* rand() and
srand() functions */
#include
<unistd.h> /* fork(), etc. */
#include
<time.h> /* nanosleep(),
etc. */
#include
<sys/types.h> /* various type
definitions. */
#include
<sys/ipc.h> /* general SysV IPC
structures */
#include
<sys/sem.h> /* semaphore
functions and structs. */
#include
<sys/wait.h> /* wait(), etc. */
#define
NUM_PROCS 5 /* number of processes to launch. */
#define
SEM_ID 250 /* ID for the semaphore. */
#define
FILE_NAME "sem_mutex" /* name
of file to manipulate */
#define
DELAY 400000 /* delay between file
updates by one process. */
/*this
function updates the contents of the file with the given path name. */
void
update_file(int sem_set_id, char* file_path, int number)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
FILE* file;
/* wait on the semaphore, unless it's value
is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1; /* <-- Comment 1 */
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
/* Comment 2 we "locked" the semaphore, and are
assured exclusive access to file. manipulate the file in some way. for example,
write a number into it. */
file = fopen(file_path, "w");
if (file) {
fprintf(file, "%d\n",
number);
printf("%d\n", number);
fclose(file);
}
/* finally, signal the semaphore - increase
its value by one. */
sem_op.sem_num = 0;
sem_op.sem_op = 1; /* <-- Comment 3 */
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
}
/* this function calls
"file_update" several times in a row, and waiting a little time between
each two calls, in order to allow other
processes time to operate.
*/
void
do_child_loop(int sem_set_id, char* file_name)
{
pid_t pid = getpid();
int i, j;
for (i=0; i<3; i++) {
update_file(sem_set_id, file_name, pid);
for (j=0; j<400000; j++)
;
}
}
/*
finally, the main() function. */
void
main()
{
int sem_set_id; /* ID of the
semaphore set. */
union semun sem_val; /* semaphore value, for semctl(). */
int child_pid; /* PID of our child
process. */
int i; /* counter for loop operation. */
int rc; /* return value of system calls. */
/* create a semaphore set with ID 250, with
one semaphore */
/* in it, with access only to the
owner. */
sem_set_id = semget(SEM_ID, 1, IPC_CREAT |
0600);
if (sem_set_id == -1) {
perror("main: semget");
exit(1);
}
/* intialize the first (and single)
semaphore in our set to '1'. */
sem_val.val = 1;
rc = semctl(sem_set_id, 0, SETVAL,
sem_val);
if (rc == -1) {
perror("main: semctl");
exit(1);
}
/* create a set of child processes that
will compete on the semaphore */
for (i=0; i<NUM_PROCS; i++) {
child_pid = fork();
switch(child_pid) {
case -1:
perror("fork");
exit(1);
case 0: /* we're at child
process. */
do_child_loop(sem_set_id,
FILE_NAME);
exit(0);
default: /* we're at parent process. */
break;
}
}
/* wait for all children to finish running
*/
for (i=0; i<NUM_PROCS; i++) {
int child_status;
wait(&child_status);
}
printf("main: we're done\n");
fflush(stdout);
}
/* sem-producer-consumer.c - demonstrates a basic producer-consumer implementation.*/
#include <stdio.h> /* standard I/O routines. */
#include <stdlib.h> /* rand() and srand() functions */
#include <unistd.h> /* fork(), etc. */
#include <time.h> /* nanosleep(), etc. */
#include <sys/types.h> /* various type definitions. */
#include <sys/ipc.h> /* general SysV IPC structures */
#include <sys/sem.h> /* semaphore functions and structs. */
#define NUM_LOOPS 20 /* number of loops to perform. */
int main(int argc, char* argv[])
{
int sem_set_id; /* ID of the semaphore set. */
union semun sem_val; /* semaphore value, for semctl(). */
int child_pid; /* PID of our child process. */
int i; /* counter for loop operation. */
struct sembuf sem_op; /* structure for semaphore ops. */
int rc; /* return value of system calls. */
struct timespec delay; /* used for wasting time. */
/* create a private semaphore set with one semaphore in it, with access only to the owner. */
sem_set_id = semget(IPC_PRIVATE, 1, 0600);
if (sem_set_id == -1) {
perror("main: semget");
exit(1);
}
printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id);
/* intialize the first (and single) semaphore in our set to '0'. */
sem_val.val = 0;
rc = semctl(sem_set_id, 0, SETVAL, sem_val);
/* fork-off a child process, and start a producer/consumer job. */
child_pid = fork();
switch (child_pid) {
case -1: /* fork() failed */
perror("fork");
exit(1);
case 0: /* child process here */
for (i=0; i<NUM_LOOPS; i++) {
/* block on the semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
printf("consumer: '%d'\n", i);
fflush(stdout);
}
break;
default: /* parent process here */
for (i=0; i<NUM_LOOPS; i++) {
printf("producer: '%d'\n", i);
fflush(stdout);
/* increase the value of the semaphore by 1. */
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
/* pause execution for a little bit, to allow the child process to run and handle some requests.*/
/* this is done about 25% of the time. */
if (rand() > 3*(RAND_MAX/4)) {
delay.tv_sec = 0;
delay.tv_nsec = 10;
nanosleep(&delay, NULL);
}
}
break;
}
return 0;
}
/* shared-mem-with-semaphore.c - using a semaphore to synchronize access to a shared memory segment. PAGE 1/3*/
#include <stdio.h> /* standard I/O routines. */
#include <sys/types.h> /* various type definitions. */
#include <sys/ipc.h> /* general SysV IPC structures */
#include <sys/shm.h> /* semaphore functions and structs. */
#include <sys/sem.h> /* shared memory functions and structs. */
#include <unistd.h> /* fork(), etc. */
#include <wait.h> /* wait(), etc. */
#include <time.h> /* nanosleep(), etc. */
#include <stdlib.h> /* rand(), etc. */
#define SEM_ID 250 /* ID for the semaphore. */
/* define a structure to be used in the given shared memory segment. */
struct country {
char name[30];
char capital_city[30];
char currency[30];
int population;
};
/*function: random_delay. delay the executing process for a random number of nano-seconds.
* input: none.
* output: none.*/
void random_delay()
{
static int initialized = 0;
int random_num;
struct timespec delay; /* used for wasting time. */
if (!initialized) {
srand(time(NULL));
initialized = 1;
}
random_num = rand() % 10;
delay.tv_sec = 0;
delay.tv_nsec = 10*random_num;
nanosleep(&delay, NULL);
}
/* function: sem_lock. locks the semaphore, for exclusive access to a resource.
* input: semaphore set ID.
* output: none. */
void sem_lock(int sem_set_id)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
/* wait on the semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
}
/* function: sem_unlock. un-locks the semaphore.
* input: semaphore set ID. PAGE-2/3
* output: none.*/
void sem_unlock(int sem_set_id)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
/* signal the semaphore - increase its value by one. */
sem_op.sem_num = 0;
sem_op.sem_op = 1; /* <-- Comment 3 */
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
}
/* function: add_country. adds a new country to the counties array in the shard memory segment. Handles locking using a semaphore.
* input: semaphore id, pointer to countries counter, pointer to counties array, data to fill into country.
* output: none. */
void add_country(int sem_set_id, int* countries_num, struct country* countries, char* country_name, char* capital_city, char* currency,int population)
{
sem_lock(sem_set_id);
strcpy(countries[*countries_num].name, country_name);
strcpy(countries[*countries_num].capital_city, capital_city);
strcpy(countries[*countries_num].currency, currency);
countries[*countries_num].population = population;
(*countries_num)++;
sem_unlock(sem_set_id);
}
/* function: do_child. runs the child process's code, for populating the shared memory segment with data.
* input: semaphore id, pointer to countries counter, pointer to counties array.
* output: none. */
void do_child(int sem_set_id, int* countries_num, struct country* counties)
{
add_country(sem_set_id, countries_num, counties,"U.S.A", "Washington", "U.S. Dollar", 250000000);
random_delay();
add_country(sem_set_id, countries_num, counties,"Israel", "Jerusalem", "New Israeli Shekel", 6000000);
random_delay();
add_country(sem_set_id, countries_num, counties,"France", "Paris", "Frank", 60000000);
random_delay();
add_country(sem_set_id, countries_num, counties,"Great Britain", "London", "Pound", 55000000);
}
/*
* function: do_parent. runs the parent process's code, for reading and printing the contents of the 'countries' array in the shared memory segment.
* input: semaphore id, pointer to countries counter, pointer to
* counties array. PAGE 3/4
* output: printout of countries array contents.
*/
void
do_parent(int sem_set_id, int* countries_num, struct country* countries)
{
int i, num_loops;
for (num_loops=0; num_loops < 5; num_loops++) {
/* now, print out the countries data. */
sem_lock(sem_set_id);
printf("---------------------------------------------------\n");
printf("Number Of Countries: %d\n", *countries_num);
for (i=0; i < (*countries_num); i++) {
printf("Country %d:\n", i+1);
printf(" name: %s:\n", countries[i].name);
printf(" capital city: %s:\n", countries[i].capital_city);
printf(" currency: %s:\n", countries[i].currency);
printf(" population: %d:\n", countries[i].population);
}
sem_unlock(sem_set_id);
random_delay();
}
}
int main(int argc, char* argv[])
{
int sem_set_id; /* ID of the semaphore set. */
union semun sem_val; /* semaphore value, for semctl(). */
int shm_id; /* ID of the shared memory segment. */
char* shm_addr; /* address of shared memory segment. */
int* countries_num; /* number of countries in shared mem. */
struct country* countries; /* countries array in shared mem. */
struct shmid_ds shm_desc;
int rc; /* return value of system calls. */
pid_t pid; /* PID of child process. */
/* create a semaphore set with ID 250, with one semaphore in it, with access only to the owner. */
sem_set_id = semget(SEM_ID, 1, IPC_CREAT | 0600);
if (sem_set_id == -1) {
perror("main: semget");
exit(1);
}
/* intialize the first (and single) semaphore in our set to '1'. */
sem_val.val = 1;
rc = semctl(sem_set_id, 0, SETVAL, sem_val);
if (rc == -1) {
perror("main: semctl");
exit(1);
}
/* allocate a shared memory segment with size of 2048 bytes. */
shm_id = shmget(100, 2048, IPC_CREAT | IPC_EXCL | 0600);
if (shm_id == -1) {
perror("main: shmget: ");
exit(1);
}
/* attach the shared memory segment to our process's address space. */
shm_addr = shmat(shm_id, NULL, 0);
if (!shm_addr) { /* operation failed. */
perror("main: shmat: ");
exit(1);
}
/* create a countries index on the shared memory segment. */
countries_num = (int*) shm_addr;
*countries_num = 0;
countries = (struct country*) ((void*)shm_addr+sizeof(int));
/* fork-off a child process that'll populate the memory segment. */
pid = fork();
switch (pid) {
case -1:
perror("fork: ");
exit(1);
break;
case 0:
do_child(sem_set_id, countries_num, countries);
exit(0);
break;
default:
do_parent(sem_set_id, countries_num, countries);
break;
}
/* wait for child process's terination. */
{ int child_status;
wait(&child_status);
}
/* detach the shared memory segment from our process's address space. */
if (shmdt(shm_addr) == -1) {
perror("main: shmdt: ");}
/* de-allocate the shared memory segment. */
if (shmctl(shm_id, IPC_RMID, &shm_desc) == -1) {
perror("main: shmctl: ");}
return 0; }
కామెంట్లు లేవు:
కామెంట్ను పోస్ట్ చేయండి