LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-24-2022, 07:16 AM   #1
gzorp
LQ Newbie
 
Registered: Nov 2022
Posts: 6

Rep: Reputation: 0
[C/CPP] - How to place items dynamically into shared queue between processes


Cheers to everybody. I am trying to create a queue in the shared memory, which will be invoked by child processes and parent processes. What I am trying to achieve is: After forking, I want the child to be able to place a struct inside the queue structure, and then using semaphores, pass into the parent process which will access the queue, pop and do something with that data. Below I have an example on how I would go on about doing it, without details (it can't compile)

PHP Code:

using 
namespace std;

// (Named) Mutex to ensure the access to the critical section
// sem_t mutex;
const charsem "/mutex";
const 
charmother_to_child "/m_to_ch";
const 
charchild_to_m "/ch_to_m";

void parent_place_into_sh_mem(Transfered DATA_INsem_tm_to_chsem_tch_to_m
      
size_t max_line_length, const charFILE_NAME) {
    
    
sem_wait(m_to_ch);  // Waiting for signaling from child so we can read
    
    
cout << "Parent process" << endl;
    
struct result queue.pop();
    
    
sem_post(ch_to_m);  // Signal parent is done
    
}

struct result {
  
int nint v;  
};

int main(int argccharargv[]) {

    
sem_unlink(mother_to_child);
    
sem_unlink(child_to_m);
    
sem_unlink(sem);

    
printf("MOTHER PROCESS IN: %d\n"getpid());
    

    
    
// Create a shared named semaphore, common to all processes
    
sem_t *mutex sem_open sem O_CREATS_IRUSR S_IWUSR 1) ;

    
// For child -> mother and mother->child communication
    
sem_tm_to_ch sem_open (mother_to_childO_CREAT O_EXCL S_IRUSR S_IWUSR 0);
    
sem_tch_to_m sem_open (child_to_mO_CREATS_IRUSR S_IWUSR 0);
    
    if (
m_to_ch == SEM_FAILED || ch_to_m == SEM_FAILED || mutex== SEM_FAILED) {
        
perror("Failed to open semphore for empty");
        exit(-
1);
    }
    
// A queue in shared memory
    
Queue queue queue_init();
    
    
// Child proccesses
    
if(fork() == 0) {
        
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
        
sem_t *semaphore sem_open(sem0);
        
sem_t *sem_m_to_ch sem_open(mother_to_child0);
        
sem_t *sem_ch_to_m sem_open(child_to_m0);

        
int selected generate_random(1n_of_segments);
        
cout << "Selected segment:" << segment_selected << endl;
        
        
sem_wait(semaphore);    // MUTEX DOWN, ENTERING ITS SHARED MEMORY TO PLACE RESULT
            // get_shared_memory_block => just a function returning a shared memory pointer
            // but I think all the magic between that is how to configure it
            
            // create a structure, I want to put it into shared memory
            
struct result local get_shared_memory_block((sizeof struct result));
            
local.something;
            
local.something_else;
            
            
queue.insert(local);
        
sem_post(semaphore);
        
        
cout << "Here at child process, I have placed myself in shared memory" << endl;
        
        
sem_post(sem_m_to_ch);  // Signal to parent we want him to transfer data into SH MEM
        
sem_wait(sem_ch_to_m);  // Waiting for parent to be done putting the data inside

        
fprintf(stdout"NOW READING THE SHARED MEMORY: \n\n");
        
cout << "Mother process done, back to child!" << endl;
        exit(
0);
    }


    
parent_place_into_sh_mem(DATA_INm_to_chch_to_m
        
max_line_length, (const char*) argv[1]);
    

    
wait(0);

    
// Very important to close the semaphore and remove it
    
sem_close(mutex);
    
sem_unlink(sem);

    
sem_close(m_to_ch); sem_unlink(mother_to_child);
    
sem_close(ch_to_m); sem_unlink(child_to_m);

    return 
0;

As I have writter in a comment, I think the magic to make this work lies in what to put
into shmget and shmat (or their key?), because I am afraid that the memory which will be mapped inside the child won't be mapped into the parent too, so I will get a seg fault. Is there something I can do? Currently, I create the shared memory block using:

PHP Code:
voidget_shared_memory_block(size_t size_of_block) {
    
voiddata;
    
int segment_id;

    
segment_id shmget (IPC_PRIVATEsize_of_block,
                        
IPC_CREAT IPC_EXCL S_IRUSR S_IWUSR);
                        
    
data shmat(segment_idNULL0);
    if (
data == NULL) {
        
perror("shmat");
        exit(
1);
    }
    return 
data;


Last edited by astrogeek; 11-25-2022 at 02:05 AM. Reason: Broke long code line for better formatting
 
Old 11-25-2022, 02:27 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,428
Blog Entries: 1

Rep: Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679
As a start, implement your queue. A possible start:
Code:
/* queue.cc */

#include <errno.h>
#include <fcntl.h>
#include <semaphore.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

struct PoolLayout {
    sem_t sem;
    uint32_t poolsize; /* brutto size */
    uint32_t rdoffs;   /* reading position */
    uint32_t wroffs;   /* writing position */
    /* QElem's */
};

struct QElem {
   uint32_t netlen;  /* length of 'data' */
   uint32_t brtlen;  /* netlen + overhead + padding; offset of the next QElem */
   char   data[];    /* netlen bytes */
};

class Queue {
private:
    PoolLayout *pooladdr;
public:
    Queue(void *ppooladdr, size_t ppoolsize);
    ~Queue();
    int push(size_t len, const void *from);
    int pop(void *into, size_t maxlen, size_t *retlen);
};

Queue::Queue(void *ppooladdr, size_t ppoolsize) {
    fprintf(stderr, "destroying the queue at %p size=%u\n",
        ppooladdr, (unsigned)ppoolsize);
    pooladdr= (PoolLayout *)ppooladdr;
    pooladdr->poolsize= ppoolsize;
    pooladdr->rdoffs= sizeof *pooladdr;
    pooladdr->wroffs= sizeof *pooladdr;
    int rc= sem_init(&pooladdr->sem, 1, 1);
    if (rc) {
        fprintf(stderr, "*** sem_init error %d: %s\n",
            errno, strerror(errno));
        exit(1);
    }
}

Queue::~Queue() {
    if (pooladdr) {
        fprintf(stderr, "destroying the queue at %p size=%u\n",
            (void *)pooladdr, (unsigned)pooladdr->poolsize);
        sem_destroy(&pooladdr->sem);
        pooladdr= NULL;
    }
}

int main () {
    size_t size= 32768;
    void *pool= malloc(size);

    Queue *q= new Queue (pool, size);
    /* ... */
    delete q;

    free (pool);
}

Last edited by NevemTeve; 11-25-2022 at 04:40 AM. Reason: refactored code
 
1 members found this post helpful.
Old 11-25-2022, 04:40 AM   #3
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,492

Rep: Reputation: 235Reputation: 235Reputation: 235
You can use stdio.
Make your queue a file, make your data text based.
Write the file in *append* mode, read/append the file with multiple processes.

It's simple, flexible, lightning fast and robust but doesn't sound very clever.
 
Old 11-25-2022, 06:37 AM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,428
Blog Entries: 1

Rep: Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679Reputation: 1679
Though deleting from the beginning of a file is non-trivial.
Also this is a homework-assignment; it is given to use shared memory.
 
Old 11-27-2022, 05:39 PM   #5
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,101
Blog Entries: 4

Rep: Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662
Since this is a homework exercise, you could not simply use the "thread-safe queue" class which C++ provides.
 
Old 12-03-2022, 01:56 PM   #6
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,005
Blog Entries: 23

Rep: Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967Reputation: 3967
Per the LQ Rules, please do not post homework assignments verbatim. We're happy to assist if you have specific questions or have hit a stumbling point, however. Let us know what you've already tried and what references you have used (including class notes, books, and Google searches) and we'll do our best to help. Also, keep in mind that your instructor might also be an LQ member.
 
Old 12-16-2022, 12:37 PM   #7
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,101
Blog Entries: 4

Rep: Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662Reputation: 3662
Speaking as someone who has been an (adjunct ...) community college instructor: "We cannot read your minds." If you are having trouble with an assignment and do not seek our help, or that of a designated lab assistant who will then pass the word to us, then we are not aware. In order to give you the quality educational experience that you rightly expect, we need to be aware. Maybe we can provide more clarification when the class next meets if we know that we need to.

You've been given a well-designed, relevant assignment. It's very important now that you do it. Don't ask someone on the Internet to do it for you, and don't just immediately search through SourceForge or GitHub and steal something that you won't fully understand. These are fundamental skills that you need to master, and there's only one way to do it. " ... ... ... ... ... "

If you were "on the job," you would look through the class libraries that come with your compiler, or GitHub, or SourceForge, and locate a class that someone else has already debugged for you. But, purposely, this is not what you should do now. Keep your instructor fully "in the loop." That's what (s)he's there for.

Last edited by sundialsvcs; 12-16-2022 at 12:42 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ preprocessor "/lib/cpp" fails sanity check C++ preprocessor "/lib/cpp" fails san mutetikasikali Linux - Software 3 01-25-2014 07:57 AM
difference between ready queue and run queue soumya_r Linux - Kernel 2 01-11-2011 10:19 PM
Cant seem to place items into cron.hourly mark8569 Linux - Software 5 12-09-2006 02:41 PM
debian dpkg cpp depends on cpp error darkleaf Linux - Software 2 06-25-2004 02:47 AM
Now I have gcc/cpp/cpp, but still can't install sfingerh Linux - Software 2 07-30-2002 04:13 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:28 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration