IPC进程间通信---共享内存
共享内存
共享内存:共享内存就是分配一块能被其它进程访问的内存。每个共享内存段在内核中维护着一个内部结构shmid_ds,
该结构定义在头文件linux/shm.h中,其结构如下:
struct shmid_ds
{
struct ipc_perm shm_perm; //操作许可,里面包含共享内存的用户ID、组ID等信息
int shm_segsz; //共享内存段的大小,单位为字节
__kernel_time_t shm_atime; //最后一个进程访问共享内存的时间
__kernel_time_t shm_dtime; //最后一个进程离开共享内存的时间
__kernel_time_t shm_ctime; //最后一次修改共享内存的时间
__kernel_ipc_pid_t shm_cpid; //创建共享内存的进程ID
__kernel_ipc_pid_t shm_lpid; //最后操作共享内存的进程ID
ushort shm_nattch; //当前使用该共享内存段的进程数量
ushort shm_unused;
void *shm_unused2;
void *shm_unused3;
};
要获得一个共享内存的描述符,只需提供该共享内存的键值即可,该键值通常由函数ftok返回,该函数原形为:
#include <sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
创建一个新的共享内存或访问一个已存在的共享内存前需要使用ftok函数得到key值,下面是ftok函数的包裹函数:
key_t Ftok(const char *pathname,int proj_id)
{
key_t key= ftok(pathname,proj_id);
if(key== -)
{
perror("ftok.");
exit();
}
return key;
}
共享内存的创建或打开:
Linux下使用shmget函数来创建一个共享内存区,或者访问已经存在的共享内存区。该函数定义在头文件<sys/shm.h>
中,该函数原形为:
#include <sys/ipc.h>
#include <sys/msg.h>
int shmget(key_t key,size_t size,int shmflg);
函数中,第一个参数是由ftok()函数得到的键值,第二个参数size为以字节为单位指定内存的大小,第三个参数shmflg为
操作标志位,它的值为一些宏,如下所示:
- IPC_CREAT:调用shmget时,系统将此值与其它所有共享内存区的key值进行比较,如果存在相同的key,说明共享内
存区已存在,此时返回该共享内存区的标识符,否则新建一个共享内存区并返回其标识符。
- IPC_EXCL:该宏必须和IPC_CREAT一起使用,否则没有意义。当shmget取IPC_CREAT|IPC_EXCL时,表示如果发现信号
集已经存在,则返回-1,错误码为EEXIST。
共享内存区的操作:
在使用共享内存区前,必须通过shmat函数将其附加到进程的地址空间。进程与共享内存就建立了连接。shmat调用成
功后就会返回一个指向共享内存区的指针,使用该指针就可以访问共享内存区了,如果失败返回-1。该函数声明在头文件
<sys/shm.h>中,该函数原形为:
#include <sys/types.h>
#include <sys/shm.h>
void* shmat(int shmid,const void *shmaddr,int shmflg);
函数中参数shmid为shmget函数的返回值,参数shmaddr为共享内存的附加点,参数shmflg为存取权限标志,参数shmaddr
不同取值情况的含义说明如下:
- 如果为空,则由内核选择一个空闲的内存区;如果非空,返回地址取决于调用者是否给shmflg参数指定了SHM_RND值,
如果没有指定,则共享内存区附加到由shmaddr指定的地址;否则附加地址为shmaddr向下舍入一个共享内存低端边界地址
后地址(SHMLBA,一个常址)。
- 通常将参数shmaddr设置为NULL。
当进程结束使用共享内存区时,要通过函数shmdt断开与共享内存区的连接。该函数声明在<sys/shm.h>头文件中,该
函数原形为:
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
参数shmaddr为shmat函数的返回值。该函数调用成功后,返回0,否则返回-1。进程脱离共享内存区后,数据结构shmid_ds
中的shm_nattch就会减1。但是共享内存段依然存在,只有shm_nattch为0后,即没有任何进程再使用共享内存区,共享内存
区才在内核中被删除。一般来说,当一个进程终止时,它所附加的共享内存区都会自动脱离。
共享内存区的控制:
对共享内存区的控制是通过函数shmctl来完成的,该函数定义在<sys/shm.h>中,该函数原形为:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
函数中,参数shmid为共享内存区的标识符;参数buf为指向shmid_ds结构体的指针;cmd为操作标志位,支持以下控制操作:
- IPC_RMID:从系统中删除由shmid标识的共享内存区。
- IPC_SET:设置共享内存区的shmid_ds结构。
- IPC_STAT:读取共享内存区的shmid_ds结构,并将其存储到buf指向的地址中。
下面是使用共享内存区发送消息的例子:
// myipc.h
#pragma once #include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h> union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
}; key_t Ftok(const char *pathname,int proj_id)
{
key_t key= ftok(pathname,proj_id);
if(key== -)
{
perror("ftok.");
exit();
}
return key;
}
//server.c
#include "myipc.h" int main(int argc,char *argv[])
{
key_t shm_key= Ftok(argv[],atoi(argv[]));
int shm_id= shmget(shm_key,,IPC_CREAT|);
if(shm_id== -)
{
perror("shmget");
exit();
}
char *addr= (char*)shmat(shm_id,NULL,);
if((void*)addr== (void*)-)
{
perror("shmat");
shmctl(shm_id,IPC_RMID,NULL);
exit();
}
key_t sem_key= shm_key;
int sem_id= semget(sem_key,,IPC_CREAT|);
struct sembuf p= {,-,};
struct sembuf v= {,,};
while()
{
printf("Ser: ");
scanf("%s",addr);
semop(sem_id,&v,); semop(sem_id,&p,);
printf("Cli: %s\n",addr);
}
shmdt(addr);
semctl(sem_id,,IPC_RMID);
semctl(sem_id,,IPC_RMID);
shmctl(shm_id,IPC_RMID,NULL);
return ;
}
//client.c
#include "myipc.h" int main(int argc,char *argv[])
{
key_t shm_key= Ftok(argv[],atoi(argv[]));
int shm_id= shmget(shm_key,,);
char *addr= (char*)shmat(shm_id,NULL,);
key_t sem_key= shm_key;
int sem_id= semget(sem_key,,);
struct sembuf p= {,-,};
struct sembuf v= {,,};
while()
{
semop(sem_id,&p,);
printf("Ser: %s\n",addr);
printf("Cli: ");
scanf("%s",addr);
semop(sem_id,&v,);
}
shmdt(addr);
return ;
}
IPC进程间通信---共享内存的更多相关文章
- 进程间通信IPC之--共享内存
每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲 区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲 ...
- Linux进程间通信—共享内存
五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...
- Linux环境进程间通信: 共享内存
Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...
- Linux IPC之共享内存C 事例
Linux IPC之共享内存 标签: linuxrandomnull工作 2011-08-25 11:52 4123人阅读 评论(0) 收藏 举报 分类: Linux(3) 读书札记(3) 版权 ...
- C# 进程间通信(共享内存)
原文:C# 进程间通信(共享内存) 进程间通信的方式有很多,常用的方式有: 1.共享内存(内存映射文件,共享内存DLL). 2.命名管道和匿名管道. 3.发送消息 本文是记录共享内存的方式进行进程间通 ...
- 进程间通信——IPC之共享内存
共享内存是三个IPC机制中的一个.它允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在进行的进程之间传递数据的一种非常有效的方式. 大多数的共享内存的实现,都把由不同进程之间共享 ...
- 【Linux 应用编程】进程管理 - 进程间通信IPC之共享内存 mmap
IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...
- 五十、进程间通信——System V IPC 之共享内存
50.1 共享内存 50.1.1 共享内存的概念 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到自己的虚拟内存空间.所有用户空间的进程若要操作共享内存,都要将其映射到自己 ...
- System V IPC 之共享内存
IPC 是进程间通信(Interprocess Communication)的缩写,通常指允许用户态进程执行系列操作的一组机制: 通过信号量与其他进程进行同步 向其他进程发送消息或者从其他进程接收消息 ...
随机推荐
- Java中的深拷贝和浅拷贝(转载)
深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java.虽然java自动管理对象的回收,但对于深拷贝(深复 ...
- Java的Final和C#的Const,Readonly比较分析(转载)
Java里面没有readonly关键字,预留了const的关键字,目前还没有实际用途,在Java中,跟这两个关键字比较接近的是final; C#中,两者都存在并可用.两者修饰的全局变量或局部变量都不能 ...
- 用虚拟信用卡注册Google Play开发者账号
本文首发于http://www.abcdsxg.cn/free/net/562 虚拟信用卡 首先介绍一下虚拟信用卡(Virtual Credit Card),顾名思义,虚拟就是没有实体卡,一般都是在提 ...
- arcgis server10.1 gp GetResultMapServiceLayer
根据10.1文档 silverlight 里面提供了新的_geoprocessorTask.GetResultMapServiceLayer方法 研究了一下得知 原来的GetResultImageLa ...
- asp.net ashx导出excel到前台
最近有一个项目使用以前的ashx,不能使用FileResult,只有通过response返回拼接好的字符串.但是通过查阅资料拼接的字符串总是提示文件格式不匹配,虽然能正常打开,但是体验很不好,在此总结 ...
- 个体商户POS机遭遇禁刷 职业养卡人称自有对策
“套现猛于虎也”,这对于信用卡业而言无异于一大命门,信用卡套现金额的规模如同滚雪球般愈演愈烈.记者昨日采访银行业内了解到,虽然为防套现将根据规定关闭个体商户POS机刷信用卡的功能,但职业“养卡人”不以 ...
- X11/Xlib.h:没有该文件或目录
编译程序时出现的错误,在安装日志上发现一句:x11/xlib.h nosuch file or directory 在网上查阅了资料,原来是x11M没有装. 解决方案:先安装X11,命令为 su ...
- 用java读取多种文件格式的文件(pdf,pptx,ppt,doc,docx..)
本文通过开源pdfbox和poi进行处理多种文件格式的文本读入 1.需要的jar的maven坐标: <dependency> <groupId>org.apache.pdfbo ...
- MVC的验证(模型注解和非侵入式脚本的结合使用)
@HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客户端,后台服务器的验证,MVC统统都做了包含,即使用户 ...
- QTimer掉坑出坑过程
最近遇到一个问题,就是关于QTimer设置了10ms,结果不生效,很头疼啊,查了快一天了,终于知道为什么了? 先说下QTimer的使用方法: m_delayHideTimer这是QTimer的对象. ...