IPC之共享内存

man 7 shm_overview编程

shm_overview - Overview of POSIX shared memory.ide

一样,SystemV实现的共享内存是旧的机制,但应用普遍;Posix标准提供了新的统一接口。函数

共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。若是段的权限设置恰当,每一个要访问该段内存的进程均可以把它映射到本身私有的地址空间中。若是一个进程更新了段中数据,那么其余进程当即回看到更新。由一个进程建立的段也能够由另外一个进程读写。共享内存这一名称表达出是由多个进程分享对段及其保存的数据的访问权这一含义。共享内存很像内存映射文件。spa

Posix API:code

shm_open, ftruncate, mmap, munmap, shm_unlink, close, fstat, fchown, fchmod.blog

System V API:接口

shmget,shmat,shmdt进程

#include <sys/types.h>ip

#include <sys/ipc.h>内存

#include <sys/shm.h>

int shmget(key_t key, int size, int flags);

flags能够是一个或多个IPC_CREAT、IPC_EXCL和一组权限位(模式)按位“或”的结果。权限位以八进制表示。IPC_EXCL确保若是段已经存在,执行失败,而不是返回一个已经存在的段的标示符。IPC_CREAT指出若是没有和key关联的段就应该建立一个新段。key既能够是IPC_PRIVATE也能够是ftok函数返回的一个关键字。参数size指定段的大小,但它以PAGE_SIZE的值为界,这个值是某种处理器自己页的大小(intel是4KB)。shmget成功返回段标识符,出错返回-1。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFSZ  4096

int main(void)
{
    int shmid;

    if((shmid = shmget(IPC_PRIVATE, BUFSZ, 0666)) < 0)
    {   
        perror("shmget");
        exit(EXIT_FAILURE);
    }   

    printf("segment created: %d\n", shmid);

    system("ipcs -m\n");
    
    exit(EXIT_SUCCESS);
}
~$./a.out 
segment created: 65538

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 0          yuxi       666        4096       0                       
0x00000000 32769      yuxi       666        4096       0                       
0x00000000 65538      yuxi       666        4096       0 

shmget只是建立了共享内存区,进程要把它映射到本身的地址空间才能使用它,调用shmat完成。

#include <sys/types.h>

#include <sys/shm.h>

void *shmat(int shmid, const char *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

在函数shmat中,若是shmaddr为NULL,则内核会把段映射到调用进程的地址空间中它所选定的位置。假如shmaddr不为NULL,而且shmflg指定SHM_RND,则attach发生在附近的最小倍数SHMLBA。不然shmaddr必须是页对齐的地址。通常老是把shmaddr设置为0。flags能够为SHM_RDONLY,这意味着被附加的段是只读的。不然,被附加的段默认是可读写的。若是shmat调用成功,则返回附加了段的地址。不然,它返回-1而且设置errno变量。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, char *argv[])
{
    int shmid;
    char *shmbuf;

    if(argc != 2)
    {   
        puts("USAGE: atshm <identifier>");
        exit(EXIT_FAILURE);
    }   
    shmid = atoi(argv[1]);

    if((shmbuf = shmat(shmid, 0, 0)) < (char *)0)
    {   
        perror("shmat");
        exit(EXIT_FAILURE);
    }   
    printf("segment attached at %p\n", shmbuf);

    system("ipcs -m");

    if((shmdt(shmbuf)) < 0)
    {
        perror("shmdt");
        exit(EXIT_FAILURE);
    }

    puts("segment detached");

    system("ipcs -m");

    exit(EXIT_SUCCESS);
}
~$./a.out 32769
segment attached at 0xb7709000

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 0          yuxi       666        4096       0                       
0x00000000 32769      yuxi       666        4096       1                       
0x00000000 65538      yuxi       666        4096       0                       

segment detached

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 0          yuxi       666        4096       0                       
0x00000000 32769      yuxi       666        4096       0                       
0x00000000 65538      yuxi       666        4096       0

 使用举例:

include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <ctype.h>

#define BUFSZ 4096

int main(int argc, char **argv)
{
    int shmid;
    char *shmbuf;
    int fd; 
    int i;

    if(argc != 2)
    {   
        puts("USAGE: opshm <identifier>");
        exit(EXIT_FAILURE);
    }   
    shmid = atoi(argv[1]);

    if((shmbuf = shmat(shmid, 0, 0)) < (char *)0)
    {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    if((shmbuf = malloc(sizeof(char) * BUFSZ)) < (char *)0)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    for(i = 0; i < BUFSZ; ++i)
    {
        shmbuf[i] = rand();
    }

    fd = open("opshm.out", O_CREAT | O_WRONLY, 0600);
    write(fd, shmbuf, BUFSZ);

    free(shmbuf);

    exit(EXIT_SUCCESS);
}

建立shm举例

void *init_shm(void)
{
    key_t key;
    int shmid;
    void *addr = NULL;

    key = ftok(SHM_PATH, SHM_PROJ);
    if(key == -1) 
    {   
        perror("ftok()");
        return NULL;
    }       

    shmid = shmget(key, sizeof(struct shm_block), IPC_CREAT | 0600);
    if(shmid == -1)
    {
        perror("shmget: ");
        return NULL;
    }
    addr = shmat(shmid, 0, 0);
    if (addr == (void *)-1)
    {
        perror("shmat()");
        return NULL;
    }

    return addr;
}

经过命令ipcs -m能够查看共享内存信息。

注:大部份内容来自《GNU/LINUX编程指南》

相关文章
相关标签/搜索