Thread: Shared memory! Any idea on how I can make the child and parent processes take turns?

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    47

    Shared memory! Any idea on how I can make the child and parent processes take turns?

    Hi guys so i'm writing a shared memory program and currently, I can create the shared memory, but I want the parent to write to the shared memory, and then I want the child to read from that shared memory, then the parent write to the shared memory and the child again read from it.

    The shared memory is only going to be 32 bytes big, and i'm gareteened the fiels i'm reading in wont' be bigger than 32 bytes.

    Currently my program is able to write 1 line of the file to shared memory then the other process is able to read that line, and write it to a file.

    But the issue comes is now I want to read a whole file, sending 1 line of the file at a time.

    Is there a way for me to tell the reading process to wait for the other process to write its line to the shared memory, and then tell the writing process, that yes the child has read that line of shared memory? So the writing process knows when to write the next line to shared memory?


    Here's what my code looks like right now:
    Code:
    
    
    /**********************************************************************
    
        Function    : pipe_read
        Description : read message from pipe into buffer of max bytes
        Inputs      : index to mypipe
                      buf to write characters from pipe
                      max is number of bytes maximum
        Outputs     : >0 if successful (number of bytes read), <0 otherwise
    
    ***********************************************************************/
    
    int pipe_read( int index, char *buf, int max )
    {
      int read, write;
      int bytes;
    
      /* need to store vars -- in case of concurrent update */
      read = only_pipe->read;
      write = only_pipe->write; 
    
      
        printf("inside mypipe_read()\n");
        printf("reading this from only_pipe->shm: %s",only_pipe->shm);
        //copying from shared memory to buf so we can write buf to file.
        strcpy(buf,only_pipe->shm);
    
    
      return bytes;
    }
    
    
    /**********************************************************************
    
        Function    :pipe_write
        Description : write message from buffer into shm of len bytes
        Inputs      : index to mypipe
                      buf to read characters for pipe
                      len is number of bytes to read
        Outputs     : >0 if successful (number of bytes read), <0 otherwise
    
    ***********************************************************************/
    
    int pipe_write( int index, char *buf, int len ) 
    {
      int read, write;
      printf("made it to mypipe_write()\n");
    
    
    
     /* need to store vars -- in case of concurrent update */
      read = only_pipe->read;
      write = only_pipe->write; 
    
      printf("only_pipe->read: %d\n",read);
      printf("only_pipe->write: %d\n",write);
      printf("only_pipe->shm: %s",only_pipe->shm);
      printf("only_pipe->size: %d\n",only_pipe->size);
      printf("only_pipe->shmid: %d\n",only_pipe->shmid);
      printf("buf passed in: %s",buf);
    
     
    
    
      //copy buff into shared memory buff
      printf("Copying passed in buffer to shared memory buffer...\n");
      int i;
      for(i = 0; i < len; i++)
      {
          only_pipe->shm[i] = buf[i];
      }
      only_pipe->shm[len] = '\0';
    
      printf("only_pipe->shm: %s",only_pipe->shm);
        
    
      return len;
    }


    I call these functions in other functions that actually read/write a file.
    Code:
    /**********************************************************************
    
        Function    : send_file
        Description : Send file 'name' data over IPC channel 'index'
        Inputs      : name -- file path
                      index -- IPC descriptor
        Outputs     : 0 if successful, -1 otherwise
    
    ***********************************************************************/
    
    int send_file( char *name, int index )
    {
    
      //holds the number of characters you read in a line
      int readChars;
    
      FILE *fp;
      //open file for reading
      fp=fopen(name, "r");
      
      //EOF_FLAG will be 1 when EOF is found
      int EOF_FLAG = 0;
      
      //this will hold 1 line of the file at a time.
      char    text[MSG_SIZE];
      printf("made it here!\n");
      //while(EOF_FLAG != 1)
      //{ 
        readChars = readline(fp,text,MSG_SIZE,&EOF_FLAG);
        //need to null terminate the array so you won't have garbadge at the end.
        text[readChars] = '\0';
        int length = strlen(text);
        printf("length is size: %d\n",length);
        printf("This is the text array I'm passing to mypipe_write(index,text,length): %s", text);
        printf("wrote-> %d\n", mypipe_write(index,text,length));
      //  printf("read in: %s",text);
      //}
        close(fp);
    
      return 0;
    }
    
    
    
    /**********************************************************************
    
        Function    : rcv_file
        Description : Receive file 'name' data over IPC channel 'index'
        Inputs      : name -- file path
                      index -- IPC descriptor
        Outputs     : 0 if successful, -1 otherwise
    
    ***********************************************************************/
    
    
    int rcv_file( char *name, int index )
    {
    
    
      FILE *fp;  
      fp = fopen(name,"w");
      if(fp == NULL)
      {
        printf("Error creating the file\n");
        return EXIT_FAILURE;
      }
    
        char readBuff[MSG_SIZE];
    
        int readBytes = mypipe_read(index,readBuff,MSG_SIZE);
        printf("Read %d bytes from the shared memory.\n",readBytes);
    
        printf("Wrote to file: %s", readBuff);
       fprintf(fp,"%s",readBuff);
        close(fp);
    
      return 0;
    }

    Any help would be great!

    I could use sch_yeild() but the problem is, I want them to take turns, not 1 process to completely write the file, and when its done writing the file, tell the other process to start reading, because if thats the case the read process will only see the last line of the file because the writing process is only sending 1 line at a time to the shared memory as there is only 32 bytes of storage .

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    To properly take turns, you need a synchronizatin object. sch_yield() or sleep() operations will absolutely not guarantee that YOUR other process gets to run - it's just telling the OS that "I don't need to run for a bit, so go do some other process", but it's not saying "Wait here until X is done". To do that, you need a pair of semaphores or other "waitable objects" that you can use to wait for the other side to finish what it needs to do.

    --
    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
    Sep 2008
    Posts
    47
    I see, thank you for the responce.

    Can you think of a better way of sharing a file through shared memory? Could I perhaps increase the shared memory size and send the whole file and then have the reading process just read the whole file from shared memory? I'm not familiar with semaphores or waitable objects so I'm not sure if going that path will cause more issues for me at this time.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by mr_coffee View Post
    I see, thank you for the responce.

    Can you think of a better way of sharing a file through shared memory? Could I perhaps increase the shared memory size and send the whole file and then have the reading process just read the whole file from shared memory? I'm not familiar with semaphores or waitable objects so I'm not sure if going that path will cause more issues for me at this time.
    Assuming the file-size isn't ginormous, then yes, you could (try) to allocate shared memory that is big enough to share the entire file. The crux of the matter comes if the file-size is larger than the available (virtual) memory - then you won't be able to create your shared memory, or you will have to go back to a process that loads parts of the file at a time.

    --
    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.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Posts
    47
    Cool thanks, thats what I'll do then! It does sound like it could cause issues with big fiels like you said but for now this will do.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Also, bear in mind that if you do the whole file, you still need a way to tell the other side.

    --
    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.

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    In your situation a pipe feels like the better IPC primitive than shared memory, but whatever.

    You can use a simple token passing mechanism. There is one logical token. Initially the parent process has it. When it has written a line, it passes the token to the child process. The child reads the line, and passes the token back.
    There are many ways to implement such a mechanism, but the simplest is probably message queues. Another is condition variables, but since you only get a pthreads implementation within a single process, you'd have to find a library or write your own. (Boost.Interprocess has one. It also has a nice C++ wrapper for MQs.)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    A simpler way than using semaphores is to use two pipes. One pipe X from process A to process B, another pipe Y from B to A.

    Suppose A goes first. That means A writes a line, while B waits. B waits by reading a byte from pipe X. Since there is no byte in the pipe, B blocks.

    After A has written the line, it writes a byte to pipe X, which wakes up B. Then process A tried to read a byte from pipe Y, which puts it to sleep.

    Process B, meanwhile, has written a line, and writes a byte to pipe Y, which wakes up A. Process B then reads from X again, which puts it back to sleep.

    Etc, etc.

    EDIT: Using pipes, but in a different manner than Salem said.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 10-15-2008, 09:24 AM
  2. process programming
    By St0rM-MaN in forum Linux Programming
    Replies: 2
    Last Post: 09-15-2007, 07:53 AM
  3. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  4. shared int between parent and child
    By rotis23 in forum C Programming
    Replies: 1
    Last Post: 02-07-2003, 08:54 AM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM