共享内存: Shared Memory

Linux进程间通信方法有:

  • 同一主机的父子进程间:管道
  • 同一主机上的进程间:FIFO(命名管道)、消息队列、信号量、信号、共享内存,socket。
  • 不同主机间:socket

这里总结共享内存知识,主要是代码总结。详细帮助见unp vol2 : 进程间通信,或者man 文档。

System V: shmget shmat shmdt
示例代码:

#include 
#include 

typedef unsigned char byte;

#define INVALID_SHMPOS ((void*)-1)

typedef struct random
{
    byte data[512];
} random;

int main()
{
    int shmid; 
    void *shmpos = NULL; 
    key_t shm_key = 0x80000008;

    if((shmid = shmget(shm_key, sizeof(struct random), IPC_CREAT | 0666)) == -1) 
    {
        perror("shmget");
        return -1;
    }
    if((shmpos = shmat(shmid, NULL, 0)) == INVALID_SHMPOS)
    {
        perror("shmat");
        return -2;
    }
    printf("shmat : %p\n", shmpos);

    struct random * rnd = (struct random *)shmpos;
#ifdef WRITER
    rnd->data[0] = 0xAF;
#else
    printf("data[0] = 0x%X\n", rnd->data[0]);
#endif

    if(shmdt(shmpos) == -1)
    {
        perror("shmdt");
        return -3;
    }

    return 0;
}

注意:这里的共享内存没有加入同步控制。可以使用信号量、互斥锁对这段内存进行同步控制。方法1:使用互斥锁。即,互斥锁也放入共享内存中,每次使用共享内存前加锁。方法2:使用信号量,信号量分为有名信号量和基于内存的信号量,而有名信号量能在不同进程间共享(使用POSIX IPC名字标识)。而基于内存的信号量可以放在共享内存中,让不同的进程使用。
下图摘自《UNP vol2》的后记部分,值得仔细体会。
共享内存: Shared Memory_第1张图片

POSIX : shm_open mmap munmap shm_unlink
示例代码:

#include 
#include 
#include 
#include 
#include 
#include 

#define SHM_NAME "/jinger_shmname"
typedef unsigned char byte;
typedef struct random
{
    byte data[512];
} random;

int main()
{
    int shm_fd;
    if((shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666)) == -1)
    {
        perror("shm_open");
        return -1;
    }

    /* 没有这个函数,会导致Bus Error,因为默认创建的文件大小是0 */
    if(ftruncate(shm_fd, sizeof(struct random)) == -1)
    {
        perror("ftruncate");
        return -1;
    }

    void *shm_addr = NULL;
    shm_addr = mmap(NULL, sizeof(struct random), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if(shm_addr == MAP_FAILED)
    {
        perror("mmap");
        return -1;
    }
    printf("Attached at %p\n", shm_addr);

    struct random * rnd = (struct random *)shm_addr;
#ifdef WRITER
    rnd->data[0] = 0xAF;
#else
    printf("data[0] = 0x%X\n", rnd->data[0]);
#endif

    if(munmap(shm_addr, sizeof(struct random)) == -1)
    {
        perror("munmap");
    }

#ifdef DELETE_AT_LAST
    if(shm_unlink(SHM_NAME) == -1)
    {
        perror("shm_unlink");
        return -1;
    }
#endif
    return 0;
}

ubuntu下的存放路径是/dev/shm。

你可能感兴趣的:(共享内存: Shared Memory)