欢迎光临
我们一直在努力

Linux 系统编程:System V IPC-->共享内存高效通信原理

目录

system v IPC对象 共享内存、消息队列、信号灯集

原理

1、创建key值

功能

参数

2、共享内存

申请一块共享内存 

功能

参数

返回值:

注意

查看IPC对象

删除IPC对象

共享内存映射

功能

参数

返回值

撤销共享内存映射

返回值

删除共享内存

功能

进程间通信小结

同主机内

传统的进程间通信方式

管道

信号

system V 进程间通信方式

不同主机

socket


system v IPC对象 共享内存、消息队列、信号灯集

原理

  • 进程都是通过IPC对象唯一的名字,称为键key,
  • 找到IPC对象,但内核还是通过IPC对象的ID来找到它.
  • 不同进程只要获得同一IPC对象的键key,
  • 就可以实现操作同一IPC对象,从而实际进程间通信

进程a和进程b能实现通信是因为:它们通过一个key值,来找到共享内存的id号

在System V(系统5)通信中,第一步先创建一个key值,只要创建方式一样,就是同一个key值;第二步建立key值和IPC之间对应的关系;第三步,结合对应IPC对象的操作逻辑实现操作,最终用完之后销毁。

1、创建key值

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

功能
  • 获得key值
参数
  • pathname:一个已经存在的文件路径(避免传".")
  • proj_id:只会使用它的低八位

例:key_t key = ftok("/home/will/",'i');

2、共享内存

共享内存效率高是因为它直接使用一块内核空间

申请一块共享内存 

#include <sys/ipc.h>

#include <sys/shm.h>

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

功能
  • 申请一块指定大小共享内存
参数

key 

获得key方法

  •         IPC_PRIVATE : 在亲缘间进程通信使用 
  •         ftok()函数获得key :可用于非亲缘关系的进程间

size  

  • 申请的大小,(分配的实际大小是4K的倍数,但可用的大小为申请大小)

shmflg  

  •         IPC_CREAT | 0666  对应的共享内存段不存在,则创建, 存在直接返回ID 
  •         IPC_CREAT | IPC_EXCL | 0666 
  • 如果对应的共享内存段已经存在,此时shmget调用失败,错误码设为EEXIST 
返回值:
  • 成功返回共享内存id;失败返回-1 
注意
  • 当key值对应的共享内存ID不存在,此时会申请一块新的共享内存区域
  • 当key值对应的共享内存ID存在,此时直接返回已经存在的共享内存ID  
查看IPC对象

ipcs -m/-q/-s 

删除IPC对象

ipcrm -m/-q/-s  ID

-m:memory 

-q:queue 

-s:semaphore

练习:探测共享内存是否存在,如果存在,报错,如果不存在,则创建

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
//1.创建key值
key_t key = ftok("/",'A');
if(key < 0)
{
perror("ftok fail");
return -1;
}
printf("key:%#x\\n",key);

//2.shmget:创建共享内存对象并建立和key关系
int shmid = 0;
if((shmid = shmget(key,1024,IPC_CREAT|IPC_EXCL|0666))<0)
{
perror("shmget fail");
return -1;
}
printf("id:%d\\n",shmid);
return 0;
}

共享内存映射

#include <sys/types.h>

#include <sys/shm.h>

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

功能
  • 映射共享内存到进程的私有地址空间
参数

    shmid   共享内存段的标识

    shmaddr NULL        让系统自动完成映射

    shmflg  0           映射可以读写;

            SHM_RDONLY  映射后只能读

返回值
  • 成功返回映射后的地址
  • 失败返回 (void *)-1,并置errno

注意:进程结束,映射自动撤销

撤销共享内存映射

int shmdt(const void *shmaddr); 

返回值
  • 成功返回0
  • 失败返回-1,并置errno

注意给shmdt传的地址必须是shmat获得的!

删除共享内存

#include <sys/ipc.h>

#include <sys/shm.h>

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

功能
  • 对共享内存进行控制
  • 若cmd参数设置为IPC_RMID,可实现删除共享内存

注意:删除共享内存并不是只要有进程删除就立刻删除,而是当映射次数为0时才会真正删除。

例:删除共享内存

shmctl(shmid,IPC_RMID,NULL);

write.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
//1.创建key值
key_t key = ftok("/",'A');
if(key < 0)
{
perror("ftok fail");
return -1;
}
printf("key:%#x\\n",key);

//2.shmget:创建共享内存对象并建立和key关系
int shmid = 0;
if((shmid = shmget(key,1024,IPC_CREAT|0666))<0)
{
perror("shmget fail");
return -1;
}
printf("id:%d\\n",shmid);

//3.映射共享内存
int* p=shmat(shmid,NULL,0);
if(p == (void*)-1)
{
perror("shmat fail");
return -1;
}

//4.已经获得一块可使用的内存空间
*p = 100;

//5.解除映射
if(shmdt(p) < 0)
{
perror("shmdt fail");
return -1;
}

//6.删除共享内存
shmctl(shmid,IPC_RMID,NULL);

return 0;
}

read.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
//1.创建key值
key_t key = ftok("/",'A');
if(key < 0)
{
perror("ftok fail");
return -1;
}
printf("key:%#x\\n",key);

//2.shmget:创建共享内存对象并建立和key关系
int shmid = 0;
if((shmid = shmget(key,1024,IPC_CREAT|0666))<0)
{
perror("shmget fail");
return -1;
}
printf("id:%d\\n",shmid);

//3.映射共享内存
int* p=shmat(shmid,NULL,0);
if(p == (void*)-1)
{
perror("shmat fail");
return -1;
}

//4.已经获得一块可使用的内存空间
printf("*p:%d\\n",*p);

//5.解除映射
if(shmdt(p) < 0)
{
perror("shmdt fail");
return -1;
}

//6.删除共享内存
shmctl(shmid,IPC_RMID,NULL);

return 0;
}

进程间通信小结

同主机内

传统的进程间通信方式

管道
  • 无名管道———亲缘关系      pipe
  • 有名管道———亲缘/非亲缘(任意进程)   mkfifo
信号
  • 软中断
  • siganal
  • kill
  • pause
system V 进程间通信方式
  • 共享内存:ftok shmget shmat shmdt shmctl
  • 消息队列
  • 信号量集

不同主机

socket

套接字

赞(0)
未经允许不得转载:171主机测评 » Linux 系统编程:System V IPC-->共享内存高效通信原理
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址