IPC机制下的共享内存shm,以及shmget、shmat、shmdt、shmctl函数

共享内存是相对较高的通信方式。其本身不提供同步机制
在Linux中,只要把共享内存段连接到进程的地址空间中,这个进程就可以访问共享内存中的地址了。
信号量必须与共享内存结合起来才能达到正常通信。
shm的主要函数:

  • shmget函数

头文件:#include #include
函数功能:得到一个共享内存的标识符或创建一个共享内存对象并返回其标识符
函数原型:int shmget(key_t key,size_t size,int shmflg);
参数1**key**:用ftok函数得到的键值
参数2**size**:大于0创建的共享内存的大小; 等于0获取共享内存
参数3shmflg等于0获取共享内存的标识符,若不存在则报错; IPC_CREATIPC_CREAT|IPC_EXCL
函数返回值:出错返回-1,成功返回共享内存的标识符

  • shmat函数

函数功能:连接共享内存标识符为shmid的共享内存,连接成功后吧共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
函数原型:void *shmat(int shmid,const void *shmaddr,int shmflg);
参数1**shmid**:共享内存的标识符
参数2**shmaddr**:指定共享内存出现在进程内存地址的什么位置,一般指定为NULL让内核自己决定一个合适的地址位置
参数3**shmflg**:SHM_RDONLY:为只读模式,其他为读写模式。一般为0
返回值:失败返回-1,成功返回共享内存的地址

  • shmdt函数

函数作用:断开与共享内存附加点的连接,禁止本进程访问此片共享内存
函数原型:int shmdt(const void *shmaddr);
参数1**shmaddr**:连接的共享内存的地址
返回值:成功返回0,失败返回-1

  • shmctl函数

函数作用:完成对共享内存的控制
函数原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);
参数1**shmid**:共享内存的标识符
参数2**cmd**:IPC_STAT得到共享内存的状态,吧共享内存的shmid_ds结构复制到buf中;IPC_SET改变共享内存的状态,吧buf所指的shmid_ds结构体中的uid,gid,mode复制到共享内存的shmid_ds结构内;IPC_RMID删除共享内存
参数3**buf**共享内存管理结构体
返回值:成功返回0,失败返回-1

代码实现:

  1 #include"../ipc.h"
  2 
  3 //1.创建关键字
  4 //2.创建共享内存
  5 //3.链接共享内存
  6 //同步机制:用信号量实现
  7 //4.发送信息
  8 //5.断开与共享内存的链接
  9 //6.删除共享内存
 10 
 11 int main(int argc,char *argv[])
 12 {
 13     if(argc!=3)
 14     {
 15         printf("Error:>Please input %s pathname proj_id\n",argv[    0]);
 16         exit(1);
 17     }
 18     key_t shm_key=Ftok(argv[1],atoi(argv[2]));
 19     int shm_id=Shmget(shm_key,1024,IPC_CREAT|IPC_EXCL|0755);
 20 
 21     char *addr=(char*)Shmat(shm_id,NULL,0);
 22     //同步机制
 23 
 24     int sem_id=Semget(shm_key,2,IPC_CREAT|IPC_EXCL|0755);
 25     union semun init;
 26     init.val=0;
 27     semctl(sem_id,0,SETVAL,init);//将信号量集中的0下标的信号量赋
    值为0
 28     semctl(sem_id,1,SETVAL,init);
 29     struct sembuf p={0,-1,0};//用0号信号量实现P操作
 30     struct sembuf v={1,1,0};
 31 
 32     //4
 33     while(1)
 34     {
 35         printf("Ser:>");//服务器先发起会话
 36         scanf("%s",addr);
 37         semop(sem_id,&v,1);//当服务器完成完成数据的输入后,希望>    客户端能读走数据,对1号信号量进行V操作,此时客户端就可对1号信号>    量进行P操作,以下P操作类似
 38 
 39         semop(sem_id,&p,1);
 40         printf("Cli:>%s\n",addr);
 41     }
 42 
 43     //5
 44     shmdt(addr);
 45     semctl(sem_id,IPC_RMID,0);//删除信号量集上的0号信号量
 46     semctl(sem_id,IPC_RMID,1);
 47     //6
 48     int ret=Shmctl(shm_id,IPC_RMID,NULL);//删除共享内存
 49     return 0;
 50 }
//cli.c
  1 #include"../ipc.h"
  2 
  3 int main(int argc,char *argv[])
  4 {
  5     key_t shm_key=Ftok(argv[1],atoi(argv[2]));
  6     int shm_id=Shmget(shm_key,0,0);
  7     char *addr=Shmat(shm_id,NULL,0);
  8     int sem_id=Semget(shm_key,0,0);
  9     struct sembuf v={0,1,0};
 10     struct sembuf p={1,-1,0};
 11     while(1)
 12     {
 13         semop(sem_id,&p,1);
 14         printf("Ser:>%s\n",addr);
 15         printf("Cli:>");
 16         scanf("%s",addr);
 17         semop(sem_id,&v,1);
 18     }
 19     shmdt(addr);
 20     return 0;
 21 }

你可能感兴趣的:(Linux)