共享内存函数(shmget、shmat、shmdt、shmctl)练习

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

  • fname就时你指定的文件名(该文件必须是存在并且能够访问的),
  • id是子序号,虽然为int,可是只有8个比特被使用(0-255),默认写1。
  • 当成功执行的时候,一个key_t值将会被返回,不然 -1 被返回。

shmget(100,4096,shmflg);

  • shmflg: 创建共享内存的时候使用,类似于open函数是否存在
    • IPC_CREAT: 创建共享内存
    • IPC_CREAT | IPC_EXCL: 检测共享内存是否存在
      • 如果存在函数返回 -1
      • 不存在,返回0
  • 返回值:
    • 成功->对应这块共享内存的地址
    • 失败->-1

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

  • shmaddr: 写NULL->委托内核区指定
  • shmflg: 操作权限
    • SHM_RDONLY: 只读
    • 0: 读写
  • 返回值
    • 成功: 共享内存的起始地址
    • 失败: (void*) -1

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

  • cmd: 对共享内存的操作
    • IPC_STAT: 获取共享内存的状态
    • IPC_SET: 设置共享内存状态
    • IPC_RMID: 标记共享内存要被销毁
  • buf: 为第二个参数服务的
    • cmd == IPC_STAT: 获取共享内存的具体状态信息
    • cmd == IPC_SET: 自定义共享内存的状态,设置到共享内存中去
    • cmd == IPC_RMID: 直接指定为NULL
  • 返回值
    • 成功 0
    • 失败 -1

写入共享内存

  #include <stdio.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <string.h>
  #include <sys/ipc.h>
  #include <sys/shm.h>
  
int main(int argc, char *argv[])    
  {
      // 创建共享内存
      int shmid = shmget(100,4096,IPC_CREAT|0664);
      // 和当前进程关联
      void* ptr = shmat(shmid,NULL,0);
      // 写共享内存
     char *pt = "这是一个块共享内存";
      memcpy(ptr,pt,strlen(pt)+1);
      printf("按任意键继续\n");
      getchar();                                                                 
      // 解除关联
      shmdt(ptr);
      // 删除共享内存
      shmctl(shmid,IPC_RMID,NULL);
      return 0;
  }

读取共享内存

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

int main(int argc, char *argv[])

{
    // 打开共享内存
    int shmid = shmget(100,0,0);
    // 和当前进程关联
    void* ptr = shmat(shmid,NULL,0);
    // read共享内存
    printf("%s\n",(char*)ptr);
    printf("按任意键继续\n");
    getchar();
    // 解除关联
    shmdt(ptr);
    // 删除共享内存
    shmctl(shmid,IPC_RMID,NULL);
    return 0;
}

思考问题

  • 问题1: 操作系统如何知道一块共享内存被多少进程关联
    • 共享内存维护了一个结构体struct shmid_ds这个结构体中有要给成员shm_nattch
    • shm_nattch中记录了关联的进程的个数
  • 问题2: 是不是可以对共享内存进行多次删除->多次调用shmctl
    • 可以多次操作
    • 因为shmctl函数是标记删除共享内存,不是直接删除
    • 什么时候被真正删除了?
      • 当关联这块共享内存进程个数 == 0的时候,真正被删除了

ipcs -m 查看共享内存

posted on 2021-05-29 14:39  lodger47  阅读(640)  评论(0)    收藏  举报

导航