共享内存


共享内存

  • 共享存储允许两个或多个进程共享一给定的存储区。

  • 因为数据不需要在客户机和服务器之间复制。

  • 这是比较老的 IPC 机制。

  • 查看共享内存,shell命令

    • ipcs
      

函数

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

       key_t ftok(const char *pathname, int proj_id);

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

       int shmget(key_t key, size_t size, int shmflg);


       #include <sys/types.h>
       #include <sys/shm.h>
       void *shmat(int shmid, const void *shmaddr, int shmflg);
       int shmdt(const void *shmaddr);



       #include <sys/ipc.h>
       #include <sys/shm.h>
       int shmctl(int shmid, int cmd, struct shmid_ds *buf);

ftok()

  • 生成key,pathname必须调用进程可以访问的。
  • proj_id必须有效。

shmget()

  • 它获得一个指定大小的共享存储标识符。
  • key参数用来标识共享内存,size参数该共享存储段的最小值,如果正在创建一个新段(一般在服务器中),则必须指定其size。如果正在访问一个现存的段(一个客户机),则将size指定为0.
  • shmfig参数有IPC_CREAT 和 IPC_EXCL,最为重要的是shmfig中指定访问权限,跟open的mode参数一样,否则会出现permission denied等错误。
  • 返回值:若成功则共享内存ID,若出错为-1.

流程

  • ftok(“./temp”, 0) 申请一个key_t。
  • shmget(key)获取共享内存对应的id,如果共享内存未创建,通过flag参数创建此共享内存。
  • shmat(id)挂载共享内存,返回地址address
  • 使用该内存address
  • shmdt(id)卸载共享内存
  • shmctl()删除共享内存

删除共享内存

ipsrm -m shmid号

代码

/*************************************************************************
        > File Name: shm.c
        > Author:
        > Mail:
        > Created Time: Sat 29 Jan 2022 03:45:09 PM CST
 ************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>

int main() {
    key_t key = ftok("./t.txt", 123);
    if (key < 0) {
        perror("ftok");
        exit(1);
    }
    printf("key = ox%x\n", key);


    int shmid = shmget(key, 20, /*IPC_EXCL |*/ IPC_CREAT | 0644);
    if (shmid < 0) {
        perror("shmget");
        exit(1);
    }
    printf("shmid = %d\n", shmid);


    //把内核开辟的空间挂载到用户空间
    void* tp_shmp = shmat(shmid, NULL, 0); //返回地址
    if (tp_shmp < 0) {
        perror("shmat");
        exit(1);
    }
    printf("shmp = %p\n", tp_shmp);
    char* shmp = (char*)tp_shmp;

    memset(shmp, 0, 20);
//    sprintf(shmp, "344jfvsdbfb十多个好好减肥djkfvhkjdbfskdhkjsdhfjksdh\n");
    pid_t pd = fork();
    if (pd < 0) {
        perror("fork");
        exit(1);
    }

    if (pd == 0) {
        //子进程读共享内存
        printf("我来了!\n");

        while (1) {
            sleep(1);
            if (strcmp(shmp, "quit") == 0) break;
            if (*shmp) {
                printf("读到:%s\n", shmp);
                memset(shmp, 0, 20);
            }
        }
        printf("我走了!\n");

    } else {
        printf("我开始写了!\n");

        while (1) {

            scanf("%s", shmp);
            if (strcmp(shmp, "quit") == 0) break;
        }
        printf("你咋还没死!\n");
        wait(NULL); //阻塞等待子进程死
        printf("你死了!\n");
    }

    //取消挂载
    shmdt(shmp);


    return 0;
}

文章作者: Axieyun
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Axieyun !
评论
评论
  目录