拥有梦想是一种智力,实现梦想是一种能力

 

概述

若是一个多线程的进程,由于各个线程共享一个地址空间,可以直接通过变量的形式进行通信。而进程,由于各个进程独占一个地址空间,我们需要一种通信机制来完成进程间的数据交互。本章介绍的是共享内存,进程间的通信机制有以下几种:

无名管道(pipe)
有名管道 (fifo)
信号(signal)

System  V  IPC
共享内存(share memory)
消息队列(message queue)
信号灯集(semaphore set)


套接字(socket)

 

之间有区分与各自的运用场景,其中套接字通常使用在网络服务,其他只能在本地场景下使用。笔者以后会逐一学习,本章介绍System  V  IPC中的共享内存。

 

System  V  IPC

System  V IPC引入了三种高级进程间的通信机制。一个IPC对象包含消息队列、共享内寸和信号量。

  • 共享内存
  • 消息队列
  • 信号灯集

 

 

System V IPC对象

每个IPC对象有唯一的ID
IPC对象创建后一直存在,直到被显式地删除
每个IPC对象有一个关联的KEY(其中进程的私有对象KTY值为0)

 

 

命令查看IPC对象

IPC对象是全局对象,可用ipcs,ipcrm等命令查看或删除

ipcs -q: 只显示消息队列
ipcs -s: 只显示信号量
ipcs -m: 只显示共享内存
ipcs –help: 其他的参数

 

函数操作

 

创建一个IPC对象

进程创建IPC对象之前,先ftok生成一个key值。

 #include  <sys/types.h>
 #include <sys/ipc.h>
 key_t  ftok(const char *path,  int proj_id);

  •  成功时返回合法的key值,失败时返回EOF
  •  path  存在且可访问的文件的路径
  •  proj_id  用于生成key的数字,不能为0


 

共享内存

特点

  • 共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
  • 共享内存在内核空间创建,可被进程映射到用户空间访问,使用灵活
  • 由于多个进程可同时访问共享内存,因此需要同步和互斥机制配合使用

 

共享内存使用步骤

  1. 创建/打开共享内存
  2. 映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
  3. 读写共享内存
  4. 撤销共享内存映射
  5. 删除共享内存对象

 

shmget 创建共享内存

 #include <sys/ipc.h>
 #include <sys/shm.h>
 int shmget(key_t key, int size, int shmflg);

  •  成功时返回共享内存的id,失败时返回EOF
  •  key  和共享内存关联的key,IPC_PRIVATE 或 ftok生成
  •  shmflg 共享内存标志位  IPC_CREAT|0666

 

shmat 共享内存映射

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

  成功时返回映射后的地址,失败时返回(void *)-1
  shmid   要映射的共享内存id
  shmaddr   映射后的地址, NULL表示由系统自动映射
  shmflg   标志位  0表示可读写;SHM_RDONLY表示只读

 

共享内存读写

通过指针访问共享内存,指针类型取决于共享内存中存放的数据类型
例如

      char *addr;
      int  shmid;
      ……
      if ((addr = (char *)shmat(shmid, NULL, 0)) == (char *)-1) {//映射
         perror(“shmat”);
         exit(-1);
      }
      fgets(addr, N, stdin);//从终端读数据到内存

 

shmdt撤销映射

 #include <sys/ipc.h>
 #include <sys/shm.h>
 int  shmdt(void *shmaddr);

  •   成功时返回0,失败时返回EOF
  •   不使用共享内存时应撤销映射
  •   进程结束时自动撤销

 

shmctl内存控制

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

  •   成功时返回0,失败时返回EOF
  •   shmid   要操作的共享内存的id
  •   cmd   要执行的操作  IPC_STAT  IPC_SET  IPC_RMID
  •   buf   保存或设置共享内存属性的地址

如果要删除内存

shmctl(shmid, IPC_RMID, NULL) 添加删除标记nattach 变成0时真正删除

 

示例

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

int main(int argc, char *argv[])
{
  key_t key;
  char *addr;
  int  shmid;
  
  if ((key = ftok(“.”, ‘a’)) == -1) 
  {
    perror(“key”);
    exit(-1);
  }   

  if ((shmid = shmget(key, 1024, IPC_CREAT|0666)) < 0) 
  {
    perror(“shmget”);
    exit(-1);
  }
     
  if ((addr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)
  {
    perror(“shmat”);
    exit(-1);
  }
  
  fgets(addr, N, stdin);
  shmdt(addr);
  shmctl(shmid, IPC_RMID, NULL);

  return 0;
}