进程通信之共享内存

2022-10-02  本文已影响0人  二进制人类

相关API

创建

#include <sys/ipc.h>
#include <sys/shm.h>
/**
 * [shmget 通过键来创建共享内存]
 * @param  key    [
 * 共享内存的键值
 *  IPC_PRIVATE:此时在每次调用的时候,都会创建一个新的共享内存;
    非IPC_PRIVATE:有用户自定义key或者通过ftok函数获取
        1) 如果key对应共享内存不存在,则开辟共享内存空间并返回共享内存id;
        2) 如果key对应共享内存已存在,则获取已存在共享内存的id返回。
 * ]
 * @param  size   [共享内存空间大小]
 * @param  shmflg [
 * 共享的访问权限和获取的方式
 *  IPC_CREAT    :创建共享内存,在获取的时候,如果不存在则创建;
    IPC_CREAT | IPC_EXCL  :共享内存存在,不会在创建直接报错。 
 * ]
 * @return        [成功返回共享内存id,失败返回-1且修改errno的值]
 */
int shmget(key_t key, size_t size, int shmflg);

shell命令

ipcs -m             #查看系统中的所有共享内存
ipcrm -m 1802254    #删除编号1802254对应的共享内存;

映射

#include <sys/types.h>
#include <sys/shm.h>
/**
 * [shmat 将共享内存映射给用户空间]
 * @param  shmid   [共享内存的id号]
 * @param  shmaddr [
 * 需要映射的用户地址
 * 如果shmaddr为NULL,则由系统找到合适的为使用的地址空间进行自动映射;
   如果shmaddr为非NULL
     1) shmflg存在SHM_RND,则映射发生在等于shmaddr的地址,舍入到SHMLBA的最近倍数;
     2) shmflg不存在SHMRND,需要按照页面对齐进行映射。
 * ]
 * @param  shmflg  [
 * 共享内存映射方式
 *  0:共享内存具有可读可写权限。
    SHM_RDONLY:只读。
    SHM_RND:(shmaddr非空时才有效)
 * ]
 * @return         [成功返回映射给用户进程的地址,失败返回(void *) -1且修改errno的值]
 */
void *shmat(int shmid, const void *shmaddr, int shmflg);

解除

#include <sys/types.h>
#include <sys/shm.h>
/**
 * [shmdt 将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)]
 * @param  shmaddr [需要解除的共享内存空间映射给用户进程的地址]
 * @return         [成功返回0,失败返回-1且修改errno的值]
 */
int shmdt(const void *shmaddr);

控制

#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

读操作实例

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

int main()
{
    int ret;
    int shmid;
    key_t key;
    char *shmaddr;
    /* 获取共享内存的键值 */
    key = ftok(".", 'm');
    if (key == -1)
    {
        perror("ftok");
        return -1;
    }
    /* 获取共享内存 */
    shmid = shmget(key, 256, 0777 | IPC_CREAT);
    if (shmid == -1)
    {
        perror("shmget");
        return -1;
    }
    /* 共享内存的映射 */
    shmaddr = shmat(shmid, NULL, 0);
    if (shmaddr == (void *) -1)
    {
        perror("shmat");
        return -1;
    }
    while(1)
    {
        /* 读取共享内存空间中的数据 */
        printf("buf : %s\n", shmaddr);//将共享内存中的数据通过标准输出流输出。
    }
    /* 解除共享内存的映射:不会删除共享内存 */
    ret = shmdt(shmaddr);
    if (ret == -1)
    {
        perror("shmdt");
        return -1;
    }
    system("ipcs -m");
    /* 删除共享内存:从内存中删除 */
    ret = shmctl(shmid, IPC_RMID, NULL);
    if (ret == -1)
    {
        perror("shmctl->IPC_RMID");
        return -1;
    }
    system("ipcs -m");
}

写操作实例

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

int main()
{
    int ret;
    int shmid;
    key_t key;
    char *shmaddr;
    /* 获取共享内存的键值 */
    key = ftok(".", 'm');
    if (key == -1)
    {
        perror("ftok");
        return -1;
    }
    /* 获取共享内存 */
    shmid = shmget(key, 256, 0777 | IPC_CREAT);

    if (shmid == -1)
    {
        perror("shmget");
        return -1;
    }
    /* 共享内存的映射 */
    shmaddr = shmat(shmid, NULL, 0);
    if (shmaddr == (void *) -1)
    {
        perror("shmat");
        return -1;
    }
    while(1)
    {
        /* 将数据写入到共享内存空间中 */
        fgets(shmaddr, 256, stdin);//读标准输入流数据存储到共享内存中。
    }
    /* 解除共享内存的映射:不会删除共享内存 */
    ret = shmdt(shmaddr);
    if (ret == -1)
    {
        perror("shmdt");
        return -1;
    }
    system("ipcs -m");
    /* 删除共享内存:从内存中删除 */
    ret = shmctl(shmid, IPC_RMID, NULL);
    if (ret == -1)
    {
        perror("shmctl->IPC_RMID");
        return -1;
    }
    system("ipcs -m");
}
上一篇 下一篇

猜你喜欢

热点阅读