Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C (http://www.programmingforums.org/forum60.html)
-   -   token ring simulation (http://www.programmingforums.org/showthread.php?t=12560)

Serinth Feb 12th, 2007 2:11 AM

token ring simulation
 
This is my assignment and i'm having a little trouble understanding how to set up and pass around the tokens/data. Any part of the code with /* ... */ is the stuff i can't get working. More specifically the token_node function and the bit at the end where it generates random data.
:

/*
 * The program simulates a Token Ring LAN by forking off a process
 * for each LAN node, that communicate via shared memory, instead
 * of network cables. To keep the implementation simple, it jiggles
 * out bytes instead of bits.
 *
 * It keeps a count of packets sent and received for each node.
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>

/*
 * N_NODE defines how many nodes to simulate and MAX_DATA is the maximum data
 * size.
 */
#define        N_NODE                7
#define SIM_PACKETS        500

/*
 * Define any handy constants and structures.
 * Also define the functions.
 */
#define        MAX_DATA        250
#define        TOKEN_FLAG        1
#define        TO                2
#define        FROM                3
#define        LEN                4
#define        DATA                5
#define        DONE                6

struct data_pkt {
        char                token_flag;        /* 'T' for token, 'D' for data        */
        char                to;                /* Destination node #                */
        char                from;                /* Source node #                */
        unsigned char        length;                /* Data length 1<->MAX_DATA        */
        char                data[MAX_DATA];        /* Up to MAX_DATA bytes of data        */
};

void token_node(int), send_pkt(int), send_byte(int, unsigned char);
void panic(char *);
unsigned char rcv_byte(int);

/*
 * The shared memory region includes a byte used to transfer data between
 * the nodes, a packet structure for each node with a packet to send and
 * sent/received counts for the nodes.
 */
struct node_data {
        unsigned char        data_xfer;
        struct data_pkt        to_send;
        int                sent;
        int                received;
        int                terminate;
};

struct shared_data {
        struct node_data node[N_NODE];
};

/*
 * Assign a number/name to each semaphore.
 * Semaphores are used to co-ordinate access to the data_xfer and
 * to_send shared data structures and also to indicate when data transfers
 * occur between nodes.
 * Macros with the node # as argument are used to access the sets of
 * semaphores.
 */
#define        EMPTY0                0
#define        FILLED0                (N_NODE)
#define        TO_SEND0        (FILLED0 + N_NODE)
#define        CRIT                (TO_SEND0 + N_NODE)
#define        NUM_SEM                (CRIT + 1)

#define        EMPTY(n)        (EMPTY0 + (n))
#define        FILLED(n)        (FILLED0 + (n))
#define        TO_SEND(n)        (TO_SEND0 + (n))

/*
 * The Linux semaphore ops are done using the fields of sembuf.
 * sem_num - Which semaphore of the set, as defined below
 * sem_op  - set to 1 for "signal" and -1 for "wait"
 * sem_flg - set to 0 for our purposes
 * The macros WAIT_SEM, SIGNAL_SEM and INITIALIZE_SEM are defined
 * to, hopefully, simplify the code.
 */
/*
 * POSIX Now says this can't be in sem.h, so we have to put it in
 * ourselves? (It was in sys/sem.h in RedHat 5.2)
 */
union semun {
        int val;
        struct semid_ds *buf;
        unsigned short int *array;
        struct seminfo *__buf;
};

#define        WAIT_SEM(s) do {                                                \
        struct sembuf sb;                                                \
        sb.sem_num = (s);                                                \
        sb.sem_op = -1;                                                        \
        sb.sem_flg = 0;                                                        \
        if (semop(semid, &sb, 1) < 0) {                                        \
                fprintf(stderr, "Wait sem failed errno=%d\n", errno);        \
                exit(4);                                                \
        }                                                                \
    } while (0)

#define        SIGNAL_SEM(s) do {                                                \
        struct sembuf sb;                                                \
        sb.sem_num = (s);                                                \
        sb.sem_op = 1;                                                        \
        sb.sem_flg = 0;                                                        \
        if (semop(semid, &sb, 1) < 0) {                                        \
                fprintf(stderr, "Signal sem failed errno=%d\n", errno);        \
                exit(4);                                                \
        }                                                                \
    } while (0)

#define INITIALIZE_SEM(s, n) do {                                        \
        union semun semarg;                                                \
        semarg.val = (n);                                                \
        if (semctl(semid, (s), SETVAL, semarg) < 0) {                        \
                fprintf(stderr, "Initialize sem failed errno=%d\n", errno); \
                exit(4);                                                \
        }                                                                \
    } while (0)

/*
 * Global data, (not shared between processes).
 */
int semid, snd_state, debugprintf = 0;
struct shared_data *shared_ptr;
extern int errno;
char *alphabits = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

/*
 * This function is the body of a child process emulating a node.
 */
void
token_node(int num)
{

        /*
        * If this is node #0, start the ball rolling by creating the
        * token.
        */
        /* ... */
        if(num==0){
                shared_ptr->node[num].to_send.token_flag='T';
                }
       
        /*
        * Loop around processing data, until done.
        */
        while (not_done) {
                /* ... */

                /*
                * Handle the byte, based upon current state.
                */
                /* ... */
               
                        if (debugprintf)
                                fprintf(stderr, "Got token flag %c\n", byte);
                /* ... */
        }
        exit(0);
}

/*
 * This function sends a data packet followed by the token, one byte each
 * time it is called.
 */
void
send_pkt(int num)
{

        /* ... */
        if(shared_ptr->node[num].to_send.token_flag=='T'){
                if(shared_ptr->node[num].to_send.length!=0){
                       
                }
        }
                /*
                * Start sending data packet
                */
                if (debugprintf)
                        fprintf(stderr, "Sending data packet\n");
        /* ... */
}

/*
 * Send a byte to the next node on the ring.
 */
void
send_byte(int num, unsigned char byte)
{

        /* ... */
}

/*
 * Receive a byte for this node.
 */
unsigned char
rcv_byte(int num)
{

        /* ... */
}

/*
 * The main program creates the shared memory region and forks off the
 * processes to emulate the token ring nodes.
 * This process generates packets at random and inserts them in
 * the to_send field of the nodes. When done it waits for each process
 * to be done receiving and then tells them to terminate and waits
 * for them to die and prints out the sent/received counts.
 */
int
main(int argc, char **argv)
{
        int shmid, child_status, num, to, i, j;

        /* Turn on debugging if "-d" argument specified */
        if (argc == 2 && !strcmp(argv[1], "-d"))
                debugprintf = 1;

        /*
        * Seed the random number generator.
        */
        srandom(time(0));

        /*
        * Create the shared memory region.
        */
        shmid = shmget(IPC_PRIVATE, sizeof (struct shared_data), 0600);
        if (shmid < 0) {
                fprintf(stderr, "Can't create shared memory region\n");
                exit(1);
        }

        /*
        * and map the shared data region into our address space at an
        * address selected by Linux.
        */
        shared_ptr = (struct shared_data *)shmat(shmid, (char *)0, 0);
        if (shared_ptr == (struct shared_data *)0) {
                fprintf(stderr, "Can't map shared memory region\n");
                exit(2);
        }

        /*
        * Now, create the semaphores, by creating the semaphore set.
        * Under Linux, semaphore sets are stored in an area of memory
        * handled much like a shared region. (A semaphore set is simply
        * a bunch of semaphores allocated to-gether.)
        */
        semid = semget(IPC_PRIVATE, NUM_SEM, 0600);
        if (semid < 0) {
                fprintf(stderr, "Can't create semaphore set\n");
                exit(3);
        }

        /*
        * and initialize them.
        * Semaphores are meaningless if they are not initialized.
        */
        for (i = 0; i < N_NODE; i++) {
                INITIALIZE_SEM(EMPTY(i), 1);
                INITIALIZE_SEM(FILLED(i), 0);
                INITIALIZE_SEM(TO_SEND(i), 1);
        }
        INITIALIZE_SEM(CRIT, 1);

        /*
        * And initialize the shared data
        */
        for (i = 0; i < N_NODE; i++) {
                shared_ptr->node[i].to_send.length = 0;
                shared_ptr->node[i].sent = 0;
                shared_ptr->node[i].received = 0;
                shared_ptr->node[i].terminate = 0;
        }

        if (debugprintf)
                fprintf(stderr, "main after initialization\n");

        /*
        * Fork off the children that simulate the disks.
        */
        for (i = 0; i < N_NODE; i++)
                if (fork() == 0)
                        token_node(i);

        /*
        * Loop around generating packets at random.
        * (the parent)
        */
        for (i = 0; i < SIM_PACKETS; i++) {
                /*
                * Add a packet to be sent to to_send for that node.
                */
                if (debugprintf)
                        fprintf(stderr, "Main in generate packets\n");
                num = random() % N_NODE;
                /* Only semaphore call(s) deleted ... */
                if (shared_ptr->node[num].to_send.length > 0)
                        panic("to_send filled\n");
                shared_ptr->node[num].to_send.token_flag = 'D';
                do {
                        to = random() % N_NODE;
                } while (to == num);
                shared_ptr->node[num].to_send.to = (char)to;
                shared_ptr->node[num].to_send.from = (char)num;
                shared_ptr->node[num].to_send.length = (random() % MAX_DATA) + 1;
                for (j = 0; j < shared_ptr->node[num].to_send.length; j++)
                        shared_ptr->node[num].to_send.data[j] =
                            alphabits[random() % 26];
                /* Only semaphore call(s) deleted ... */
        }

        /*
        * Now wait for all nodes to finish sending and then tell them
        * to terminate.
        */
        /* ... */
        for (i = 0; i < N_NODE; i++)
                shared_ptr->node[i].terminate = 1;
        /* ... */

        if (debugprintf)
                fprintf(stderr, "wait for children to terminate\n");
        /*
        * Wait for the node processes to terminate.
        */
        for (i = 0; i < N_NODE; i++)
                wait(&child_status);

        /*
        * All done, just print out the results.
        */
        for (i = 0; i < N_NODE; i++)
                printf("Node %d: sent=%d received=%d\n", i,
                        shared_ptr->node[i].sent,
                        shared_ptr->node[i].received);
        if (debugprintf)
                fprintf(stderr, "parent at destroy shared memory\n");
        /*
        * And destroy the shared data area and semaphore set.
        * First detach the shared memory segment via shmdt() and then
        * destroy it with shmctl() using the IPC_RMID command.
        * Destroy the semaphore set in a similar manner using a semctl()
        * call with the IPC_RMID command.
        */
        shmdt((char *)shared_ptr);
        shmctl(shmid, IPC_RMID, (struct shmid_ds *)0);
        semctl(semid, 0, IPC_RMID, (union semun)0);
}

/*
 * Panic: Just print out the message and exit.
 */
void
panic(char *str)
{

        fprintf(stderr, str);
        exit(5);
}


I understand that i should be setting up the token in the token_node bit but what additional processing should be done in that while(not_done) loop? Maybe i should be calling the token_node function more times as i'm trying to send it (near the bottom after the generating packets bit) Any thoughts?


All times are GMT -5. The time now is 1:47 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC