0

I am using Shared memory (POSIX), to share a FILE pointer(FILE * rt_file), but it's not getting file pointer at client end. Any suggestions please.

/*
*  shm_msgserver.c
*  
*  Illustrates memory mapping and persistency, with POSIX objects.
*  This process produces a message leaving it in a shared segment.
*  The segment is mapped in a persistent object meant to be subsequently
*  open by a shared memory "client".
*
*
*  Created by Mij <mij@bitchx.it> on 27/08/05.
*  Original source file available at http://mij.oltrelinux.com/devel/unixprg/
*
*/


#include <stdio.h>
/* shm_* stuff, and mmap() */
#include <sys/mman.h>
#include <sys/types.h>
/* exit() etc */
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
/* for random() stuff */
#include <stdlib.h>
#include <time.h>


/* Posix IPC object name [system dependant] - see
http://mij.oltrelinux.com/devel/unixprg/index2.html#ipc__posix_objects */
#define SHMOBJ_PATH         "/foo1423"
/* maximum length of the content of the message */
#define MAX_MSG_LENGTH      50
/* how many types of messages we recognize (fantasy) */
#define TYPES               8

/* message structure for messages in the shared segment */
struct msg_s {
    int type;
    char content[MAX_MSG_LENGTH];
    FILE *pt;
};


int main(int argc, char *argv[]) {
    int shmfd;
    int shared_seg_size = (1 * sizeof(struct msg_s));   /* want shared segment capable of storing 1 message */
    struct msg_s *shared_msg;      /* the shared segment, and head of the messages list */

    FILE *rt_file;
    rt_file = fopen ("res","a+");
    printf("rt_file : %s\n",rt_file);
    /* creating the shared memory object    --  shm_open()  */
    shmfd = shm_open(SHMOBJ_PATH, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG);
    if (shmfd < 0) {
        perror("In shm_open()");
        exit(1);
    }
    fprintf(stderr, "Created shared memory object %s\n", SHMOBJ_PATH);

    /* adjusting mapped file size (make room for the whole segment to map)      --  ftruncate() */
    ftruncate(shmfd, shared_seg_size);

    /* requesting the shared segment    --  mmap() */    
    shared_msg = (struct msg_s *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
    if (shared_msg == NULL) {
        perror("In mmap()");
        exit(1);
    }
    fprintf(stderr, "Shared memory segment allocated correctly (%d bytes).\n", shared_seg_size);


    srandom(time(NULL));
    /* producing a message on the shared segment */
    shared_msg->type = random() % TYPES;
    snprintf(shared_msg->content, MAX_MSG_LENGTH, "My message, type %d, num %ld", shared_msg->type, random());
    shared_msg->pt = rt_file;


    /* [uncomment if you wish] requesting the removal of the shm object     --  shm_unlink() */
/*
    if (shm_unlink(SHMOBJ_PATH) != 0) {
        perror("In shm_unlink()");
        exit(1);
    }
*/

    return 0;
}

Client Code

/*
*  shm_msgclient.c
*  http://mij.oltrelinux.com/devel/unixprg/#ipc__posix_shm
*  Illustrates memory mapping and persistency, with POSIX objects.
*  This process reads and displays a message left it in "memory segment
*  image", a file been mapped from a memory segment.
*
*
*  Created by Mij <mij@bitchx.it> on 27/08/05.
*  Original source file available at http://mij.oltrelinux.com/devel/unixprg/
*
*/

#include <stdio.h>
/* exit() etc */
#include <unistd.h>
/* shm_* stuff, and mmap() */
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
/* for random() stuff */
#include <stdlib.h>
#include <time.h>


/* Posix IPC object name [system dependant] - see
http://mij.oltrelinux.com/devel/unixprg/index2.html#ipc__posix_objects */
#define SHMOBJ_PATH         "/foo1423"      
/* maximum length of the content of the message */
#define MAX_MSG_LENGTH      50
/* how many types of messages we recognize (fantasy) */
#define TYPES               8

/* message structure for messages in the shared segment */
struct msg_s {
    int type;
    char content[MAX_MSG_LENGTH];
    FILE *pt;
};



int main(int argc, char *argv[]) {
    int shmfd;
    int shared_seg_size = (1 * sizeof(struct msg_s));   /* want shared segment capable of storing 1 message */
    struct msg_s *shared_msg;      /* the shared segment, and head of the messages list */

    FILE *rt_file;
    /* creating the shared memory object    --  shm_open()  */
    shmfd = shm_open(SHMOBJ_PATH, O_RDWR, S_IRWXU | S_IRWXG);
    if (shmfd < 0) {
        perror("In shm_open()");
        exit(1);
    }
    printf("Created shared memory object %s\n", SHMOBJ_PATH);

    /* requesting the shared segment    --  mmap() */    
    shared_msg = (struct msg_s *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
    if (shared_msg == NULL) {
        perror("In mmap()");
        exit(1);
    }
    printf("Shared memory segment allocated correctly (%d bytes).\n", shared_seg_size);
    rt_file = shared_msg->pt;
    printf("rt_file : %s\n",rt_file);
    rt_file = fopen ("res","a+");
    printf("rt_file : %s\n", rt_file);
    char x[10]="ABCDEFGHIJ";
    fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), rt_file);
    printf("Message type is %d, content is: %s\n", shared_msg->type, shared_msg->content);
    if(shm_unlink(SHMOBJ_PATH) == -1){
        printf("%s is used by another Process\n",SHMOBJ_PATH);
        }
        else{
            printf("Memory is freed\n");
            }
    return 0;
}
Arun Gupta
  • 810
  • 2
  • 9
  • 26
  • 5
    The `FILE` structure is an opaque structure, with fields you know nothing about, but most likely it contains a least one pointer to memory (for the buffering) that is handled by the stdio system and not by you, so that memory can't be in shared memory. You might use e.g. [`setbuf`](http://en.cppreference.com/w/c/io/setbuf) to set the buffer manually, but the `FILE` structure may contain other data that can't be shared. – Some programmer dude May 14 '14 at 13:02
  • 5
    Not to mention that the `FILE` structure is for an open file in one process only, the other processes will not have the same file opened. It might even have a completely different file opened with the same file descriptor, or even a socket or other "file"-like file descriptor. – Some programmer dude May 14 '14 at 13:02
  • 2
    What you *can* do is [share file-descriptors between processes](http://stackoverflow.com/questions/909064/portable-way-to-pass-file-descriptor-between-different-processes), but you can't share a stdio `FILE`. – Some programmer dude May 14 '14 at 13:05

1 Answers1

1

FILE* pointers are valid only in the process where they were created.

While you can transfer the pointer value, or even the structure it points to, to another process, using it in the other process will invoke undefined behaviour.

If you want another process on the same machine to access a certain file I suggest that you send the file name, mode and offset to the other process and let it create it's own FILE* structure by calling fopen.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82