Pergunta

I have a program where I want to set up a pointer to a struct as shared memory. I think I've set up the shared memory correctly in the main method; then I call a function to initialize the struct, and fork. However, the child process can't access the shared memory; the parent process works as expected, which isn't that big of a surprise. I know for sure that the child process executes and works, but it cannot access the shared memory, so the function doesn't really do much besides print out printf statements.

struct OverSharedData{
    struct SharedData ** rep;
    int rop;
};

void initialize( struct OverSharedData * bill){
bill->rep = (struct SharedData**)malloc(sizeof(struct SharedData*)*consumerthreads);
int on =0;
for (on=0; on<consumerthreads; on++) {
    *(bill->rep+on) = (struct SharedData *)malloc(sizeof(struct SharedData));
    init(*(bill->rep + on), on); //
 }}

int main(int argc, const char * argv[])
{

    databases(argv[1]); /* Takes care of setting up the database*/
    categories(argv[2]); /*Takes care of setting up the book categories*/
    bookorders = argv[3];

    key_t key = ftok("garbage.txt", 71);
    int eyedee = shmget(key, sizeof(struct OverSharedData ),
                        IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    if (eyedee == -1)
    {
        perror("shmget");
        exit(1);
    }

    struct OverSharedData *remp = (struct OverSharedData *) shmat(eyedee, 0, 0);

    if (remp == (void *) -1)
    {
        perror("shmat");
        exit(1);
    }

    initialize(remp);
    struct SharedData * d = *(remp->rep + 0);


    printf("Hallo\n");
    shmctl(eyedee, IPC_RMID, 0);



    pid_t forkk = fork();

    if (forkk==0) {
        /*THIS DOES NOT WORK*/
        printf("Entered consumer check: %d\n", remp->rop);

         int z = 0;
         pthread_t Consumer_Threads[consumerthreads];
         for (z=0; z<consumerthreads; z++) {
         remp->rop = z;
         d = *(remp->rep + z);
         d->da = z;
         pthread_create((Consumer_Threads+z), 0, Consumer, d);


         }
         for (z = 0; z<consumerthreads; z++) {
         pthread_join(Consumer_Threads[z], NULL);
         }
         shmdt(remp);

    }

    else{
       /*THIS WORKS*/
        printf("Entered Producer: %d\n",remp->rop);

        pthread_t Produc;
        pthread_create(&Produc, 0, Producer, remp); 
        pthread_join(Produc, NULL);


        printf("Hey guys: %d\n", remp->rop);
        shmdt(remp);
    }

My guess is that I didn't initialize the struct correctly, but I'm not all too clear what I'm doing wrong. I left out some of the other initializing code but I figured since I can't even access the int in the OverSharedData struct, it's more of a matter where I can't access the struct in the first place.

Foi útil?

Solução

The problem is that your shared data (the single OverSharedData object) contains pointers to non-shared data. You need to allocate all the data that you want shared in the shared memory segment, rather than with malloc. Something like:

static void *shared_available;
static size_t shared_left;
void init_shared(size_t size) {
    key_t key = ftok("garbage.txt", 71);
    int eyedee = shmget(key, size,
                        IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    if (eyedee == -1) {
        perror("shmget");
        exit(1); }
    shared_available = shmat(eyedee, 0, 0);
    if (shared_available == (void *) -1) {
        perror("shmat");
        exit(1); }
    shared_left = size;
}
void *alloc_shared(size_t size) {
    void *rv = shared_available;
    if (size > shared_left) {
        fprintf(stderr, "Ran out of shared memory!\n");
        exit(1); }
    shared_available = (char *)rv + size;
    shared_left -= size;
    return rv;
}

OverSharedData *initialize() {
    init_shared(sizeof(struct OverSharedData) +
                       sizeof(struct SharedData *) * consumerthreads +
                       sizeof(struct SharedData) * consumerthreads)
    OverSharedData *bill = alloc_shared(sizeof(OverSharedData));
    bill->rep = alloc_shared(sizeof(struct SharedData*)*consumerthreads);
    for (int on=0; on<consumerthreads; on++) {
        bill->rep[on] = alloc_shared(sizeof(struct SharedData));
        init(&bill->rep[on], on); }
}

The above will still have problems if the init routine tries to store pointers to non-shared memory into the SharedData struct (you don't show the definition of either, so we can't say).

If you want to be able to more flexibly allocate and manage shared memory across processes, you really need to use a general purpose shared memory allocator/manager, such as this

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top