Thread: confused: sem, shm

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    99

    Unhappy confused: sem, shm

    I'm very confused, my program is supposed control 3 child processes, allowing them to write to/delete from shared memory array and print the results to stdout.
    However, for some reason:
    -parent exits a few times removing shm and sem (the output shows that),
    -child processes print out ALWAYS the same array, consisting of some strange characters, not the uppercase /lowercase alphabetics.
    What is going on? I did not sleep a lot last night, please excuse if I'm not thinking clearly...
    Can anybody help me here?
    Last edited by kocika73; 02-27-2006 at 07:38 PM.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Instead of attaching your program, you should post it in the thread (more people will read it if they don't have to click on anything) inside [code] [/code] tags. Here it is for reference:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    #include <sys/shm.h>
    #include <time.h>
     
    #define ARR_SIZE 30
     
    union semun {
       int                 val;
       struct semid_ds    *buf;
       ushort_t           *array;
    };
     
    int random_num(int one, int two);
     
    int main()
    {
       struct sembuf oper;
       pid_t child_processes[3];
       char buffer[ARR_SIZE]; 
       int shmid, *shmptr;
       pid_t child_pid;
       int status;
       int i, j, k;
       char int_counter;
       int child_process_status;
       int semid;
       int parent_pid;
       int rand_n;
       pid_t current_child;
     
    /* returns the value of created segment */
       shmid = shmget( IPC_PRIVATE, ARR_SIZE*sizeof(char), SHM_R | SHM_W );
       if(shmid == -1) {
         perror("Shared memory segment not created\n");
         exit(1);
       }
     
    /* maps the shared segment onto process' address. Ret ptr to it */
       (void *)shmptr = (char *)shmat(shmid, 0, 0);
       if(!shmptr) {
         perror("Did not attach mem to the process\n");
         exit(1);
       }
     
    /* initialize shared memory to the array in this driver. */
       int_counter = (char *)shmptr;
     
    /* initialize the first index of the array to the counter... is zero*/
    /* we always subtract 33 from that counter to */
    /* get the real number */ 
       (int) int_counter = 0;
     
    /* set the beginning of the array of chars, which is int_counter +1 */
       buffer[1] = (char *) ( (void *) shmptr+sizeof(char) );
     
    /* semaphores segement */
       if( ( semid = semget(IPC_PRIVATE, 1, 0777 ) ) < 0 ) {
         perror("Semaphore allocation failed\n");
         exit(1);
       }
     
       semctl( semid, 0, SETVAL, (union semun)1 );
     
     
    /* forking */
       for( i = 0; i < 3; i++ ) {
         child_pid = fork();
         switch( child_pid ) {
            case -1:
                    perror("Fork failed\n");
                    exit(1);
                    break;
            case 0: /* child part */
                    child_processes[i] = getpid();
                    printf("Child no %d of process id %ld just forked\n", 
                            i+1, child_processes[i]);
                    switch(i) {
                            case 0: /* child no 1 */
                                    oper.sem_num = 0;
                                    oper.sem_op = -1;
                                    oper.sem_flg = 0;
                                    semop(semid, &oper, 1);
                                    printf("Child1 semaphore down: OK - proceed to CS.\n");
    /*  ...........................CS............................................    */
                                    for( j = 0; j < 50; j++) { 
                                       if((int)int_counter >= 29)
                                       ;
                                       else if((int)int_counter < 29) {
                                            int_counter = int_counter + sizeof(char);;
                                            rand_n = random_num(26, 65);
                                            printf("Random number for 1 is %d\n", rand_n);
                                            fprintf((shmptr+sizeof(char)+(int)int_counter), "%c", rand_n);
                                       }
                                       for(k = 0; k < (int)int_counter; k++) {
                                         usleep(random_num(751, 8000));
                                         fprintf(stdout, "%c ", shmptr + k*(sizeof(char))); /* + sizeof(char) */
                                       }
                                     }
    /* ............................end of CS ...................................   */
     
                                    oper.sem_num = 0;
                                    oper.sem_op = 1;
                                    oper.sem_flg = 0;
                                    semop(semid, &oper, 1);
                                    printf("Child1 semaphore up: OK - child exit CS.\n");
                                    break;
                            case 1:   /* child no 2 */
                                      oper.sem_num = 0;
                                      oper.sem_op = -1;
                                      oper.sem_flg = 0;
                                      semop(semid, &oper, 1);
                                      printf("Child2 semaphore down: OK - proceed to CS.\n");
    /*  ...........................CS..........................................    */
                                    for( j = 0; j < 50; j++) {    
                                         if((int)int_counter >= 29)
                                            ;
                                         else if((int)int_counter < 29) {
                                            int_counter = int_counter + sizeof(char);
                                            rand_n = random_num(26, 97);
                                            printf("Random number for 2 is %d\n", rand_n);
                                            fprintf((shmptr+sizeof(char)+(int)int_counter), "%c", rand_n);
                                            }
                                         for(k = 0; k < (int)int_counter; k++) {
                                           usleep(random_num(7501, 8000));
                                           fprintf(stdout, "%c ", shmptr + k*(sizeof(char)));
                                         }
                                    }
    /* ............................end of CS ...................................   */
     
                                    oper.sem_num = 0;
                                    oper.sem_op = 1;
                                    oper.sem_flg = 0;
                                    semop(semid, &oper, 1);
                                    printf("\nChild2 semaphore up: OK - child exit CS.\n");
                                    break;
                            case 2: /* child no 3 */
                                    oper.sem_num = 0;
                                    oper.sem_op = -1;
                                    oper.sem_flg = 0;
                                    semop(semid, &oper, 1);
                                    printf("Child3 semaphore down: OK - proceed to CS.\n");
    /* ............................CS........................................     */
                                    for( j = 0; j < 50; j++) {  
                                       if((int)int_counter <= 0)
                                            ; /* do nothing, can't remove a char if arr empty */
                                       else if((int)int_counter > 0) {
                                          fprintf((shmptr+sizeof(char)+(int)int_counter), "%c", NULL);
                                          (int)int_counter -= (int)int_counter;
                                       }
                                         for(k = 0; k < (int)int_counter; k++) {
                                            usleep(random_num(7501, 8000));
                                            fprintf(stdout, "%c ", shmptr + k); /* buffer? */
                                         }
                                    }
    /* ............................end of CS ...................................   */
     
                                    printf("Child3 semaphore up?\n");
                                    oper.sem_num = 0;
                                    oper.sem_op = 1;
                                    oper.sem_flg = 0;
                                    semop(semid, &oper, 1);
                                    printf("Child3 semaphore up: OK - child exit CS.\n");
                                    break;
                            default: printf("Error\n"); 
                                     exit(1);
                                     break;
                            }
                            break;
                    default: /* parent part */
                            break;
            }
     
    }
     
     
       wait(&child_process_status); 
     
       printf("All child processes exited.\n");
       printf("Removing shared memory segments and semaphores\n");
     
    /* when mem not needed anymore, free it after all processes are gone ???????*/
       *shmptr = 0; /* OR shmptr = (char *)shmat(shmid, 0, 0); ?????? */
     
    /* detach memory */
       shmdt( shmptr );
     
       /* free it */
       shmctl( shmid, IPC_RMID, shmptr );
     
    /* remove the semaphore */
       semctl( semid, 0, IPC_RMID );
     
       printf("Parent %ld exits.\n", parent_pid);
     
       return 0;
    }
     
    /* three cases here: uppercase is 26, 65, lowercase is 26, 97 */
    /* and for usleep is e.g 51, 50 */
    int random_num(int one, int two)
    {
       srand(time(NULL));
       return( rand() % one + two);
    }
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    char int_counter;
    int_counter = (char *)shmptr;
    What is this supposed to do?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    Registered User
    Join Date
    Sep 2004
    Posts
    99
    Supposed to attach the pointer to shared memory to my counter variable.
    I did not post the code in [] because it is kinda long, so I thought it would be more convenient to attach it as a file... I guess not.

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Supposed to attach the pointer to shared memory to my counter variable.
    Well then declare the variable as char* or change the cast. Turn on warnings, too.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    Registered User
    Join Date
    Sep 2004
    Posts
    99
    This variable was initially written as char * but the result was exactly the same. I always thought it should be, just depends what specifier you place in the printf statement: %d or %c. Was I wrong?

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well, it's like you're taking a char* and assigning it to a char. Like this:
    Code:
    char *p;
    char h = p;
    Your compiler should complain about that. Turn on warnings, as I said.

    This variable was initially written as char * but the result was exactly the same.
    Stop using casts!
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Registered User
    Join Date
    Sep 2004
    Posts
    99
    OK, I'll take a look at it again... Thanks

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    sizeof(char)
    is always 1.
    Code:
    int random_num(int one, int two)
    {
       srand(time(NULL));
       return( rand() % one + two);
    }
    You're only supposed to call srand() once. Put the highlighted code in main() or something.

    Code:
    (int) int_counter = 0;
    You definitely have excessive casts. This does the same thing:
    Code:
    int_counter = 0;
    Code:
    (union semun)1
    Casting 1 to a union probably won't do what you think it does. Maybe it will. Even if it does, it's not very portable.

    Code:
    int k;
    int *shmptr;
    fprintf(stdout, "%c ", shmptr + k);
    Does that look healthy to you? fprintf() is expecting a char and you pass it an int*! Oops . . . .

    Turn on compiler warnings. I mean it. For GCC, pass as extra arguments
    Code:
    -W -Wall -ansi -pedantic
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Confused with array size
    By desmond5 in forum C Programming
    Replies: 4
    Last Post: 12-04-2007, 05:14 PM
  2. New to C++ and confused by boolean and ifs and else
    By jconner in forum C++ Programming
    Replies: 10
    Last Post: 08-02-2006, 03:29 AM
  3. why wont this compile?!? :confused:
    By jdude in forum C++ Programming
    Replies: 5
    Last Post: 11-25-2004, 01:13 AM
  4. So Now Im getting confused?!?!?
    By zergdeath1 in forum C++ Programming
    Replies: 11
    Last Post: 03-06-2004, 05:41 PM
  5. confused.. in selecting my line of deapth
    By jawwadalam in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 05-04-2003, 01:21 PM