Unix shared memory management

We know that Windows shared memory is implemented through memory-mapped files maintained by the system page file and is always controlled by a countable reference (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v= vs .85) .aspx).

I wonder if Unix does a similar thing. Someone (http://stackoverflow.com/q/4278391/939142) says that Unix also manages shm in reference counting. I tried the experiment on Mac OS X and found that it was not.

Using the code provided at the end, compile two programs: host and client. A type

./host 

      

which creates shm, writes (int) 10 at the first address, and exits. Then enter

./client <shmid>

      

to check the shm segment that is attached to the generated shm prints the first int and exits.

Note that we used shmat and shmdt to connect / disconnect from shm and shmget to create shm.

To kill shm, we have to do it manually using shmctl.

Conclusion: shm is not managed like reference counting on Unix, at least for Mac OS X

/************************** host.c ****************************/

#include <stdio.h>
#include <sys/shm.h>
#include <mach/vm_param.h>
#include <assert.h>

int
main(int argc, char** argv)
{
int value = 10;
int id;
void* ptr;
    /* create a new shm */
id = shmget(IPC_PRIVATE, PAGE_SIZE, IPC_CREAT | 0666);
assert(id != -1);
    /* attach to the new shm */
ptr = shmat(id, (const void*) NULL, 0);
assert((int*) ptr != -1);
    /* print the id so that client can use */
printf("shm id = %ld\n", id);
printf("address of id = %ld, length = %ld\n", ptr, PAGE_SIZE);
((int*) ptr)[0] = value;
printf("value at address %ld = %ld\n", ptr, *(int*) ptr);
/* detach from the shm and exit */
    shmdt((const void*) ptr);
return 0;
}


/************************** host.c ****************************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include "assert.h"
#include <mach/vm_param.h>

int
main(int argc, char** argv)
{
void* ptr;
int id = atoi(argv[1]);
assert(id != -1);
    /* attach to the shm */
ptr = shmat(id, NULL, 0);
assert(ptr != -1);
printf("value at ptr = %ld = %ld\n", ptr, *(int*) ptr);
shmdt((const void*) ptr);
return 0;
}

      

+3


source to share


1 answer


This is not pure reference counting. According to shmctl (2):

IPC_RMID . Mark the segment to be destroyed. The segment will only actually be destroyed after the last process has detached it (that is, when the shm_nattch member of the associated shmid_ds structure is zero). The caller must be the owner or creator,

This means: IPC_RMID

will not be deleted immediately, but only after the reference count drops to zero the next time.



This allows you to achieve multiple goals with the same tool:

  • Or a server / client approach where the server builds, attaches and installs right away RMID

    . Then clients can connect while the server is here. If the server is down, clients should disconnect and the resource is cleaned up by the OS.

  • Or the "message" approach: someone writes a message, binds it to a known location. After that, someone else may come, look for the message and act accordingly. This is what you did. Of course, this approach is more open to resource garbage. But there are things to do for that.

+2


source







All Articles