C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 09-20-2007, 05:25 PM   #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.
Dr Spud is offline   Reply With Quote
Old 09-20-2007, 05:31 PM   #2
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
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.
matsp is offline   Reply With Quote
Old 09-20-2007, 07:51 PM   #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");
}
Dr Spud is offline   Reply With Quote
Old 09-21-2007, 04:03 PM   #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");
}
Dr Spud is offline   Reply With Quote
Old 09-21-2007, 04:54 PM   #5
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
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.
matsp is offline   Reply With Quote
Old 09-21-2007, 05:18 PM   #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.
Dr Spud is offline   Reply With Quote
Old 09-22-2007, 12:30 AM   #7
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,661
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)%(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.

Salem is offline   Reply With Quote
Old 09-22-2007, 12:45 PM   #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?
Dr Spud is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

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


All times are GMT -6. The time now is 02:33 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22