如何在进程之间共享内存区域

时间:2014-04-02 08:09:30

标签: c linux memory-management

如何在以下场景中共享内存?

  1. 在父和子进程之间
  2. 两个不相关的流程之间
  3. 物理内存的哪一部分存在共享内存(或)用于进程间通信的任何其他IPC?

1 个答案:

答案 0 :(得分:1)

这里有一个程序,解释了父母和子进程之间的内存管理..

/* 
        SHARING MEMORY BETWEEN PROCESSES

    In this example, we show how two processes can share a common
    portion of the memory. Recall that when a process forks, the
    new child process has an identical copy of the variables of
    the parent process. After fork the parent and child can update
    their own copies of the variables in their own way, since they
    dont actually share the variable. Here we show how they can
    share memory, so that when one updates it, the other can see
    the change.

*/

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>    /*  This file is necessary for using shared
                memory constructs
            */

main()
{
    int shmid. status;
    int *a, *b;
    int i;

    /*  
        The operating system keeps track of the set of shared memory
        segments. In order to acquire shared memory, we must first
        request the shared memory from the OS using the shmget()
            system call. The second parameter specifies the number of
        bytes of memory requested. shmget() returns a shared memory
        identifier (SHMID) which is an integer. Refer to the online
        man pages for details on the other two parameters of shmget()
    */
    shmid = shmget(IPC_PRIVATE, 2*sizeof(int), 0777|IPC_CREAT);
            /* We request an array of two integers */

    /* 
        After forking, the parent and child must "attach" the shared
        memory to its local data segment. This is done by the shmat()
        system call. shmat() takes the SHMID of the shared memory
        segment as input parameter and returns the address at which
        the segment has been attached. Thus shmat() returns a char
        pointer.
    */
    if (fork() == 0) {

        /* Child Process */

        /*  shmat() returns a char pointer which is typecast here
            to int and the address is stored in the int pointer b. */
        b = (int *) shmat(shmid, 0, 0);

        for( i=0; i< 10; i++) {
            sleep(1);
            printf("\t\t\t Child reads: %d,%d\n",b[0],b[1]);
        }
        /* each process should "detach" itself from the 
           shared memory after it is used */

        shmdt(b);

    }
    else {

        /* Parent Process */

        /*  shmat() returns a char pointer which is typecast here
            to int and the address is stored in the int pointer a.
            Thus the memory locations a[0] and a[1] of the parent
            are the same as the memory locations b[0] and b[1] of
            the parent, since the memory is shared.
        */
        a = (int *) shmat(shmid, 0, 0);

        a[0] = 0; a[1] = 1;
        for( i=0; i< 10; i++) {
            sleep(1);
            a[0] = a[0] + a[1];
            a[1] = a[0] + a[1];
            printf("Parent writes: %d,%d\n",a[0],a[1]);
        }
        wait(&status);

        /* each process should "detach" itself from the 
           shared memory after it is used */

        shmdt(a);

        /* Child has exited, so parent process should delete
           the cretaed shared memory. Unlike attach and detach,
           which is to be done for each process separately,
           deleting the shared memory has to be done by only
           one process after making sure that noone else
           will be using it 
         */

        shmctl(shmid, IPC_RMID, 0);
    }
}

/*
        POINTS TO NOTE:

    In this case we find that the child reads all the values written
    by the parent. Also the child does not print the same values
    again.

    1. Modify the sleep in the child process to sleep(2). What
       happens now?

    2. Restore the sleep in the child process to sleep(1) and modify
           the sleep in the parent process to sleep(2). What happens now?

    Thus we see that when the writer is faster than the reader, then
    the reader may miss some of the values written into the shared
    memory. Similarly, when the reader is faster than the writer, then
    the reader may read the same values more than once. Perfect 
    i    /* 
        SHARING MEMORY BETWEEN PROCESSES

    In this example, we show how two processes can share a common
    portion of the memory. Recall that when a process forks, the
    new child process has an identical copy of the variables of
    the parent process. After fork the parent and child can update
    their own copies of the variables in their own way, since they
    dont actually share the variable. Here we show how they can
    share memory, so that when one updates it, the other can see
    the change.

*/

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>    /*  This file is necessary for using shared
                memory constructs
            */

main()
{
    int shmid. status;
    int *a, *b;
    int i;

    /*  
        The operating system keeps track of the set of shared memory
        segments. In order to acquire shared memory, we must first
        request the shared memory from the OS using the shmget()
            system call. The second parameter specifies the number of
        bytes of memory requested. shmget() returns a shared memory
        identifier (SHMID) which is an integer. Refer to the online
        man pages for details on the other two parameters of shmget()
    */
    shmid = shmget(IPC_PRIVATE, 2*sizeof(int), 0777|IPC_CREAT);
            /* We request an array of two integers */

    /* 
        After forking, the parent and child must "attach" the shared
        memory to its local data segment. This is done by the shmat()
        system call. shmat() takes the SHMID of the shared memory
        segment as input parameter and returns the address at which
        the segment has been attached. Thus shmat() returns a char
        pointer.
    */
    if (fork() == 0) {

        /* Child Process */

        /*  shmat() returns a char pointer which is typecast here
            to int and the address is stored in the int pointer b. */
        b = (int *) shmat(shmid, 0, 0);

        for( i=0; i< 10; i++) {
            sleep(1);
            printf("\t\t\t Child reads: %d,%d\n",b[0],b[1]);
        }
        /* each process should "detach" itself from the 
           shared memory after it is used */

        shmdt(b);

    }
    else {

        /* Parent Process */

        /*  shmat() returns a char pointer which is typecast here
            to int and the address is stored in the int pointer a.
            Thus the memory locations a[0] and a[1] of the parent
            are the same as the memory locations b[0] and b[1] of
            the parent, since the memory is shared.
        */
        a = (int *) shmat(shmid, 0, 0);

        a[0] = 0; a[1] = 1;
        for( i=0; i< 10; i++) {
            sleep(1);
            a[0] = a[0] + a[1];
            a[1] = a[0] + a[1];
            printf("Parent writes: %d,%d\n",a[0],a[1]);
        }
        wait(&status);

        /* each process should "detach" itself from the 
           shared memory after it is used */

        shmdt(a);

        /* Child has exited, so parent process should delete
           the cretaed shared memory. Unlike attach and detach,
           which is to be done for each process separately,
           deleting the shared memory has to be done by only
           one process after making sure that noone else
           will be using it 
         */

        shmctl(shmid, IPC_RMID, 0);
    }
}

/*
        POINTS TO NOTE:

    In this case we find that the child reads all the values written
    by the parent. Also the child does not print the same values
    again.

    1. Modify the sleep in the child process to sleep(2). What
       happens now?

    2. Restore the sleep in the child process to sleep(1) and modify
           the sleep in the parent process to sleep(2). What happens now?

    Thus we see that when the writer is faster than the reader, then
    the reader may miss some of the values written into the shared
    memory. Similarly, when the reader is faster than the writer, then
    the reader may read the same values more than once. Perfect 
    inter-process communication requires synchronization between the
    reader and the writer. You can use semaphores to do this.

    Further note that "sleep" is not a synchronization construct.
        We use "sleep" to model some amount of computation which may
    exist in the process in a real world application.

    Also, we have called the different shared memory related
    functions such as shmget, shmat, shmdt, and shmctl, assuming
    that they always succeed and never fail. This is done to
    keep this proram simple. In practice, you should always check for
        the return values from this function and exit if there is 
    an error.   
*/nter-process communication requires synchronization between the
    reader and the writer. You can use semaphores to do this.

    Further note that "sleep" is not a synchronization construct.
        We use "sleep" to model some amount of computation which may
    exist in the process in a real world application.

    Also, we have called the different shared memory related
    functions such as shmget, shmat, shmdt, and shmctl, assuming
    that they always succeed and never fail. This is done to
    keep this proram simple. In practice, you should always check for
        the return values from this function and exit if there is 
    an error.   
*/