21, ఏప్రిల్ 2012, శనివారం

ADVANCED UNIX PROGRAMMING


/*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;                                           } 


కామెంట్‌లు లేవు:

కామెంట్‌ను పోస్ట్ చేయండి