进程间通信---共享内存

进程间通信---共享内存

   ------->双向通信

   ------->仅是一块内存,可以随意写入数据

   ------->无同步互斥

   ------->生命周期随内核

   -----共享内存是最快的IPC形式.共享内存的本质是物理内存,一旦这样的内存映射到共享它的进程的地址空间,这些空间不涉及内核.

进程是一个独立的资源管理单元,不同进程间的资源是独立的,不能在一个进程中访问另一个进程的用户空间和内存空间。但是,进程不是孤立的,不同进程之间需要信息的交互和状态的传递,因此需要进程间数据的传递、同步和异步的机制。   

当然,这些机制不能由哪一个进程进行直接管理,只能由操作系统来完成其管理和维护,Linux提供了大量的进程间通信机制,包括同一个主机下的不同进程和网络主机间的进程通信,如下图所示:


共享内存是进程间通信中最简单的方式之中的一个。

共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区。

共享内存同意两个或很多其他进程訪问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。

当一个进程改变了这块地址中的内容的时候,其他进程都会察觉到这个更改

用ftok()函数获得一个ID号


应用说明,在IPC中,我们经经常使用用key_t的值来创建或者打开信号量,共享内存和消息队列。

key_t ftok(const char *pathname, int proj_id);
參数 描写叙述
pathname 一定要在系统中存在而且进程能够訪问的
proj_id 一个1-255之间的一个整数值,典型的值是一个ASCII值。

当成功运行的时候,一个key_t值将会被返回。否则-1被返回。我们能够使用strerror(errno)来确定详细的错误信息。

考虑到应用系统可能在不同的主机上应用,能够直接定义一个key,而不用ftok获得:

#define IPCKEY 0x344378

创建共享内存


进程通过调用shmget(Shared Memory GET,获取共享内存)来分配一个共享内存块。

int shmget(key_t key ,int size,int shmflg)
參数 描写叙述
key 一个用来标识共享内存块的键值
size 指定了所申请的内存块的大小
shmflg 操作共享内存的标识

返回值:假设成功,返回共享内存表示符,假设失败,返回-1。

该函数的第一个參数key是一个用来标识共享内存块的键值。

该函数的第二个參数size指定了所申请的内存块的大小

第三个參数shmflg是一组标志。通过特定常量的按位或操作来shmget

映射共享内存


shmat()是用来同意本进程訪问一块共享内存的函数。将这个内存区映射到本进程的虚拟地址空间。

int shmat(int shmid,char *shmaddr,int flag)
參数 描写叙述
shmid 那块共享内存的ID。是shmget函数返回的共享存储标识符
shmaddr 是共享内存的起始地址,假设shmaddr为0,内核会把共享内存映像到调用进程的地址空间中选定位置。假设shmaddr不为0,内核会把共享内存映像到shmaddr指定的位置。所以一般把shmaddr设为0。
shmflag 是本进程对该内存的操作模式。假设是SHM_RDONLY的话,就是仅仅读模式。

其他的是读写模式

成功时,这个函数返回共享内存的起始地址。失败时返回-1。

共享内存解除映射


当一个进程不再须要共享内存时,须要把它从进程地址空间中多里。

int shmdt(char *shmaddr)
參数 描写叙述
shmaddr 那块共享内存的起始地址

成功时返回0。失败时返回-1。

应通过调用 shmdt(Shared Memory Detach。脱离共享内存块)函数与该共享内存块脱离。

将由 shmat 函数返回的地址传递给这个函数。假设当释放这个内存块的进程是最后一个使用该内存块的进程,则这个内存块将被删除。

控制释放


shmctl控制对这块共享内存的使用

函数原型

int  shmctl( int shmid , int cmd , struct shmid_ds *buf );
參数 描写叙述
shmid 是共享内存的ID。
cmd 控制命令
buf 一个结构体指针。

IPC_STAT的时候,取得的状态放在这个结构体中。假设要改变共享内存的状态,用这个结构体指定。

当中cmd的取值例如以下

cmd 描写叙述
IPC_STAT 得到共享内存的状态
IPC_SET 改变共享内存的状态
IPC_RMID 删除共享内存

返回值: 成功:0 失败:-1

代码演示

comm.h

  1 #define PATHNAME "."
  2 #define PROJ_ID 0x6666
  3 #include<stdio.h>
  4 #include<sys/types.h>
  5 #include<sys/ipc.h>
  6 #include<sys/shm.h>
  7 int createShm(int size);
  8 int destroyShm(int shmid);
  9 int getShm(int size);

comm.c

1 #include "comm.h"
  2 #include <sys/shm.h>
  3 #include<stdlib.h>
  4 int commShm(int size,int flag)
  5 {
  6     key_t key = ftok(PATHNAME,PROJ_ID);
  7     if(key<0){
  8        perror("ftok");
  9        return -1;
 10     }
 11     int shmid = 0;
 12     if(shmid = shmget(key,size,flag)<0){
 13       perror("shmget");
 14       return -2;
 15     }
 16     return shmid;
 17 }
 18 int destroyShm(int shmid){
 19     if(shmctl(shmid,IPC_RMID,NULL)){
 20        perror("shmctl");
 21        return -1;                                                                                                                                      
 22     }
 23     return 0;
 24 
 25 }
 26 int createShm(int size){
 27     return commShm(size,IPC_CREAT|IPC_EXCL|0666);
 28 
 29 }
 30 int getShm(int size){
 31 return commShm(size,IPC_CREAT);
 32 
 33 } 

server.c

 1 #include "comm.h"
  2 int main(){
  3 int shmid = getShm(4096);
  4 sleep(1);
  5 char *addr =(char* )shmat(shmid,NULL,0);
  6 sleep(2);                                                                                                                                              
  7 int i=0;
  8 while(i<26){
  9 addr[i]='A'+i;
 10 i++;
 11 addr[i]=0;
 12 sleep(1);
 13 
 14 }
 15 shmdt(addr);
 16 sleep(2);
 17 return 0;
 18 }

client.c

 1 #include "comm.h"
  2 #include<stdlib.h>
  3 int main(){
  4   int shmid=createShm(4096);
  5   char *addr = shmat(shmid,NULL,0);
  6   sleep(2);
  7   int i=0;
  8   while((i++)<26){                                                                                                                                     
  9     printf("client# %s\n",addr);
 10     sleep(1);
 11     }
 12   shmdt(addr);
 13   sleep(2);
 14   destroyShm(shmid);
 15   return 0;
 16 }


猜你喜欢

转载自blog.csdn.net/sx2448826571/article/details/79702361
今日推荐