Thread: semaphores

  1. #1
    Registered User
    Join Date
    Nov 2005
    Location
    Alpine, TX
    Posts
    31

    semaphores

    good afternoon all, so I'm trying my first attempt at semaphores and trying to recreate the producer consumer problem. My question seems kinda silly because its already done all over the internet but nobody talks about how to do it (so I guess Im the only one that doesn't know how, and that is how to name a semaphore.

    In my program I am using multiple semaphores getting them using:
    Code:
    semid = semget(IPC_PRIVATE, 4, 0600 | IPC_CREAT);
         /* Initialize values for the 4 semaphores */
         semctl(semid, 0, SETVAL, 0);
         semctl(semid, 1, SETVAL, ITEM_SIZE * 10);
         semctl(semid, 2, SETVAL, 0);
         semctl(semid, 3, SETVAL, 0);
    two of these are the empty and full semaphores that I will use to communicate between the producer and consumer using wait(full); and signal(empty); but my semaphores are not named accordingly. How can I do this? thx for the help.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think you need to use sem_open()
    http://www.opengroup.org/pubs/online.../sem_open.html

    You won't be able to get four semaphores in one call with this method, but I'm sure you can work around that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Nov 2005
    Location
    Alpine, TX
    Posts
    31
    okay so I think I got the name thing figured out thx for the reply but im thinking because I used <sys/sem.h> instead I have to go a different route. Now my program hangs up and neither process will run. heres my code, any ideas why this is happening?
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/sem.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    #include <sys/wait.h>
    
    #define ITEM_SIZE 4096
    
    /* define semaphores within the set */
    #define SEM_FULL 0
    #define SEM_EMPTY 1
    #define SEM_LAST_TRANS_SIZE 2
    #define SEM_TERMINATED 3
    
    char input_line[50];            /* gather file names from user */
    char output_line[50];
    
    char items[ITEM_SIZE];
    char buffer[ITEM_SIZE * 10];    /* array of 10 items  */
    
    FILE *in_file;                  /* input = file to read; output = file to write */
    FILE *out_file;
    
    union semun
    {
        int val;
        struct semid_ds *buf;
        ushort *array;
    } seminfo;
    
    struct sembuf Wait_Empty={SEM_EMPTY, -1, 0};
    struct sembuf Signal_Empty={SEM_EMPTY, 1, 0};
    struct sembuf Wait_Full={SEM_FULL, -1, 0};
    struct sembuf Signal_Full={SEM_FULL, 1, 0};
    
    int main(){
        int pid;
        int terminated_val;
        int read_size;              /* number of bytes on last read */
        
        /* gather shared memory space */
        int shmid;
        char * shm_addr;
        shmid = shmget(IPC_PRIVATE, ITEM_SIZE * 10, IPC_CREAT);  /* creat sh memory */
        shm_addr = shmat(shmid, NULL, 0);                        /* attach sh memory */
        
        /* get the 4 semaphores to be used */
        int semid;
         semid = semget(IPC_PRIVATE, 4, 0600 | IPC_CREAT);
         /* Initialize values for the 4 semaphores */
         semctl(semid, SEM_FULL, SETVAL, 0);
         semctl(semid, SEM_EMPTY, SETVAL, ITEM_SIZE * 10);
         semctl(semid, SEM_LAST_TRANS_SIZE, SETVAL, 0);
         semctl(semid, SEM_TERMINATED, SETVAL, 0);
    
        /* gather the input file for the child to read from the user */
        fprintf(stderr, "Enter the file name to be copied:");
        fgets(input_line, sizeof(input_line), stdin);
        if(input_line[strlen(input_line)-1] == '\n') input_line[strlen(input_line)-1] = 0;
        
        /* gather the output file for the parent to put the copy in */
        fprintf(stderr, "Enter the file name to be written:");
        fgets(output_line, sizeof(output_line), stdin);
        if(output_line[strlen(output_line)-1] == '\n') output_line[strlen(output_line)-1] = 0;
        
        
        /* fork and cross fingers */
        pid = fork();
        /* parent process responsible for generating the copy "write to the file" */
        if(pid == 0){
            int out = 0;
            /* test if file exists, if not create the file specified by user */
            if((out_file = fopen(output_line, "r")) == NULL){
                creat(output_line, "w");
                fprintf(stderr, "File created\n");
            }
            /* write to file from buffer */
            while(1){
                /* wait(full) */
                semop(semid, &Wait_Full, 1);
                
                
                terminated_val = semctl(semid, SEM_TERMINATED, GETVAL);
                if(terminated_val == 1){
                    write(out_file, buffer[out], (unsigned int) read_size);
                    fprintf(stderr, "File copy complete\n");
                    fclose(out_file);
                    semctl(semid, 4, IPC_RMID);        /* remove the semaphores */
                    shmdt(shm_addr);                   /* detach shared memory for removal */
                    shmctl(shmid, IPC_RMID, NULL);     /* remove shared memory */ 
                    return(0);
                }
                
                
                
                /* write the copy file from the buffer */
                write(out_file, buffer[out], (unsigned int) read_size);
                /* update the buffer */
                out = (out+1)%(ITEM_SIZE*10);
                /* signal(empty) */
                semop(semid, &Signal_Empty, 1);
            }
        }
        /* child process responsible for reading the file and passing it to the buffer */
        else if (pid > 0){
            int in = 0;
            /* file entered by the user was not found */
            if((in_file = fopen(input_line, "r")) == NULL){
                fprintf(stderr, "File could not be opened\n");
                perror("fopen");
            }
            /* file specified by user was found */
            else
                fprintf(stderr, "File Found\n");
            while(1){
                /* wait(empty) */
                semop(semid, &Wait_Empty, 1);
                /* read ITEM_SIZE into the buffer */
                read_size = read(in_file, buffer[in], ITEM_SIZE);
                fprintf(stderr, "%d\n", read_size);
                /*update the buffer */
                in = (in+1)%(ITEM_SIZE*10);
                /* read_size must not be negative or error */
                if(read_size < 0){
                    fprintf(stderr, "something bad happend\n");
                    exit(8);
                }
                /* end of file */
                else if(read_size > 0 && read_size < ITEM_SIZE){
                /* last of the file set last-transfer-size semaphore to size of file left */
                    semctl(semid, SEM_LAST_TRANS_SIZE, SETVAL, read_size);
                    fclose(in_file);
                /* set the terminated semaphore to 1 */
                    semctl(semid, SEM_TERMINATED, SETVAL, 1);
                    semop(semid, &Signal_Full, 1);
                }
                /* signal(full) */
                semop(semid, &Signal_Full, 1);
            }
        }
        /* Oops fork did not happen */
        else perror("fork\n");
    }

  4. #4
    Registered User
    Join Date
    Nov 2005
    Location
    Alpine, TX
    Posts
    31
    So ive made some progress on my program and some significant changes that I think are for the best but I still have a problem. In this example I dont want to just set the buffer to a size that can handle the entire copy at once. I want to break the copying up so that read will deposit an item in buffer[in] and write will take that deposit at buffer[out] and write it to the copy. But when I do this I get an error of "Bad Adress". Would greatly appreciate some help with this. And as a trial run, I did abandon the idea of not having a large buffer to check if my file copy implementation worked. What I got was a binary file for the copy cant figure out why this happened. Any help on this matter also would help me greatly. thx for the help heres the codes

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/sem.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define ITEM_SIZE 4096
    
    /* define semaphores within the set */
    #define SEM_FULL 0
    #define SEM_EMPTY 1
    #define SEM_LAST_TRANS_SIZE 2
    #define SEM_TERMINATED 3
    
    char items[ITEM_SIZE];
    char buffer[ITEM_SIZE * 10];    /* array of 10 items  */
    
    int in_file;                  /* input = file to read; output = file to write */
    int out_file;
    int read_size;
    
    union semun
    {
        int val;
        struct semid_ds *buf;
        ushort *array;
    } seminfo;
    
    struct sembuf Wait_Empty={SEM_EMPTY, -1, 0};
    struct sembuf Signal_Empty={SEM_EMPTY, 1, 0};
    struct sembuf Wait_Full={SEM_FULL, -1, 0};
    struct sembuf Signal_Full={SEM_FULL, 1, 0};
    
    int main(int argc, char *argv[]){
        int pid;
        int terminated_val;
        int read_size;              /* number of bytes on last read */
        
        /* gather shared memory space */
        int shmid;
        char * shm_addr;
        shmid = shmget(IPC_PRIVATE, ITEM_SIZE * 10, IPC_CREAT);  /* creat sh memory */
        shm_addr = shmat(shmid, NULL, 0);                        /* attach sh memory */
        
        /* get the 4 semaphores to be used */
        int semid;
        int stat;
         semid = semget(IPC_PRIVATE, 4, 0600 | IPC_CREAT);
         if (semid < 0)
           perror("semget");
         /* Initialize values for the 4 semaphores */
         semctl(semid, SEM_FULL, SETVAL, 0);
         stat = semctl(semid, SEM_EMPTY, SETVAL, 10);
         if (stat < 0) perror("semctl sem_empty setval");
         semctl(semid, SEM_LAST_TRANS_SIZE, SETVAL, 0);
         semctl(semid, SEM_TERMINATED, SETVAL, 0);
    
        /* gather the input file for the child to read from the user */
         if (argc != 3) {
             fprintf(stderr, "Error:Wrong number of arguments\n");
             fprintf(stderr, "Usage is: copy <from> <to>\n");
             exit(8);
         }
         in_file = open(argv[1], O_RDONLY);
         if (in_file < 0) {
             fprintf(stderr, "Error:Unable to open %s\n", argv[1]);
             exit(8);
         }
         out_file = open(argv[2], O_WRONLY|O_TRUNC|O_CREAT, 0666);
         if (out_file < 0) {
             fprintf(stderr, "Error:Unable to open %s\n", argv[2]);
             exit(8);
         }
    
        /* fork and cross fingers */
        pid = fork();
        /* parent process responsible for generating the copy "write to the file" */
        if(pid == 0){
            int out = 0;
            
            /* write to file from buffer */
            while(1){
                /* wait(full) */
                semop(semid, &Wait_Full, 1);
                int last_trans_size;
                last_trans_size = semctl(semid, SEM_LAST_TRANS_SIZE, GETVAL);
                terminated_val = semctl(semid, SEM_TERMINATED, GETVAL);
                if(terminated_val == 1){
                    write(out_file, buffer[out], last_trans_size);
                    fprintf(stderr, "File copy complete\n");
                    semctl(semid, 4, IPC_RMID);        /* remove the semaphores */
                    shmdt(shm_addr);                   /* detach shared memory for removal */
                    shmctl(shmid, IPC_RMID, NULL);     /* remove shared memory */ 
                    close(out_file);
                    close(in_file);
                    return(0);
                }
                /* write the copy file from the buffer */
                write(out_file, buffer[out], ITEM_SIZE);
                /* update the buffer */
                out = (out+1)%(ITEM_SIZE*10);
                /* signal(empty) */
                semop(semid, &Signal_Empty, 1);
            }
        }
        /* child process responsible for reading the file and passing it to the buffer */
        else if (pid > 0){
            int in = 0;
            while(1){
                /* wait(empty) */
                semop(semid, &Wait_Empty, 1);
                /* read ITEM_SIZE into the buffer */
                read_size = read(in_file, buffer[in], ITEM_SIZE);
                /* read_size must not be negative or error */
                if (read_size < 0) {
                    fprintf(stderr, "Error:Read error\n");
                    perror("read");
                    exit(8);
                }
                in = (in+1)%(ITEM_SIZE*10);
    
                /* end of file */
                if(read_size > 0 && read_size < ITEM_SIZE){
                /* last of the file set last-transfer-size semaphore to size of file left */
                    semctl(semid, SEM_LAST_TRANS_SIZE, SETVAL, read_size);
                /* set the terminated semaphore to 1 */
                    semctl(semid, SEM_TERMINATED, SETVAL, 1);
          !         semop(semid, &Signal_Full, 1);
                }
                /* signal(full) */
                semop(semid, &Signal_Full, 1);
            }
        }
        /* Oops fork did not happen */
        else perror("fork\n");
    }

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you use gdb, do you get a stack-trace that can be used to deduce where the problem is? You can either do that by just running your code inside gdb, or use the core file that is generated when it crashes.

    I don't see anything OBVIOUS, but it's quite possible that there's problems someplace in the code.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Nov 2005
    Location
    Alpine, TX
    Posts
    31
    sure.... first off I am getting compiler warnings here they are if they will help you
    Code:
    sem.c: In function ‘main’:
    sem.c:108: warning: passing argument 2 of ‘write’ makes pointer from integer without a cast
    sem.c:118: warning: passing argument 2 of ‘write’ makes pointer from integer without a cast
    sem.c:134: warning: passing argument 2 of ‘read’ makes pointer from integer without a cast
    here is gdb out
    Code:
    (gdb) run read.txt foo.txt
    Starting program: /home/drspud/Desktop/sem read.txt foo.txt
    
    Error:Read error
    read: Bad address
    
    Program exited with code 010.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    char items[ITEM_SIZE];
    char buffer[ITEM_SIZE * 10]; /* array of 10 items */

    No it isn't.
    It might be as big as an array of 10 items, but it sure isn't an array of 10 items.
    As a result, all your attempts to use buffer fail.

    char buffer[10][ITEM_SIZE];
    might be of some use.

    And replacing the likes of
    in = (in+1)&#37;(ITEM_SIZE*10);
    with
    in = (in+1)%10;
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Nov 2005
    Location
    Alpine, TX
    Posts
    31
    Awesome Salem thx for your post and help. Your suggestion worked like a charm now I just gotta figure out why my copied file is printed in binary instead of ASCII. Any good tutorials on this anyone could suggest?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Semaphores, need advice on implementation.
    By Swerve in forum C++ Programming
    Replies: 2
    Last Post: 01-13-2009, 01:54 AM
  2. Semaphores Problems
    By mhelal in forum Linux Programming
    Replies: 2
    Last Post: 05-06-2007, 10:36 PM
  3. Semaphores
    By Jules in forum C Programming
    Replies: 4
    Last Post: 01-18-2004, 01:58 PM
  4. semaphores
    By theLukerBoy in forum C Programming
    Replies: 0
    Last Post: 11-05-2002, 01:46 AM
  5. Semaphores
    By edk in forum C++ Programming
    Replies: 1
    Last Post: 11-25-2001, 03:55 PM