好久没更新博客了,最近几个月一直在忙项目,现在终于有时间进一步学习了。这次记录的是unix环境中共享内存的使用方法。

  

 在我理解,共享内存就是在内存中开辟一段空间,各个毫不相干的进程就可以通过访问这段内存中的资源,从而达到进程间通信的效果。由于是对同一块内存进行操作,没有涉及到资源的复制等操作,所以在IPC对象中共享内存速度和效率都是很高的。
     使用共享内存过程中需要的函数
     1、shmget
     该函数通过键值向内核申请一块共享内存
     函数原型:int  shmget(key_t key, size_t size, int shmflg);
     其中,key是每一个IPC结构都需要的键值;size是想要获取共享内存的大小,单位是字节;shmflag是获取共享内存的标志,一般为IPC_CREAT,当该key值对应的共享内存不存在时创建之,存在的话就打开。当创建共享内存时,还应添加创建共享内存的权限,如IPC_CREAT | 0666。该函数成功返回时得到共享内存的标示符,失败返回-1。
     2、shmat
     该函数将已申请到的共享内存连接到用户进程空间中
     函数原型:void * shmat(int shmid, const void *shmaddr, int shmflg);
     其中,shmid是共享内存的标识符;shmaddr指明将该内存映射到进程空间哪一块儿区域,推荐将其置NULL,由linux内核自动分配;flag为连接到进程空间时的权限选项,一般填0。该函数成功返回时返回该共享内存的首地址,失败返回-1。
     3、shmdt
     该函数将连接到用户进程的共享内存与进程分离
     函数原型:int shmdt(const void *shmaddr);
     其中,shmaddr为要分离的共享内存的首地址。成功返回0,失败返回-1。
     4、shmctl
     该函数用于控制得到的共享内存
     函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
     内存中每一段共享内存都对应一个shmid_ds结构体用来维护。其中,cmd是要对shmid指向的共享内存执行的操作。当cmd为IPC_STAT时,取出shmid指向的共享内存对应的shmid_ds结构,并存储到buf中。当cmd为IPC_RMID时,删除shmid指向的共享内存段,此时buf填0。
 
  

======================分割线================================
 
     下面写两个程序来演示共享内存的使用方法。设计思路:write进程打开共享内存,并向其中循环写入数据,每次写完后等待read进程将其读走,再进行下一次写入。当write进程写入end时,两个进程都终止。贴代码:

/*write.c*/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> /*共享内存中缓冲区的大小*/
#define BUFFER_SIZE 2048 struct temp
{
int write_flag;
char share_buffer[BUFFER_SIZE]
}; int main(int argc, char const *argv[])
{
int shmid; /*循环开关*/
int running = ; char buffer[BUFFER_SIZE]; struct temp *share_temp; /*合成键值*/
key_t key = ftok(".", ); /*打开共享内存*/
if((shmid = shmget(key, sizeof(struct temp), IPC_CREAT)) == -)
{
printf("memory get failed\n");
exit(EXIT_FAILURE);
} printf("shmid is %d\n", shmid); /*映射共享内存*/
if((share_temp = shmat(shmid, NULL, )) == (void *)-)
{
printf("memory at failed\n");
exit(EXIT_FAILURE);
} /*循环写入数据*/
while(running)
{
while(share_temp->write_flag)
{
sleep();
printf("wait for read process\n");
}
fgets(buffer, BUFFER_SIZE, stdin);
strncpy(share_temp->share_buffer, buffer, BUFFER_SIZE); share_temp->write_flag = ;
if(strncmp(share_temp->share_buffer, "end", ) == )
running = ;
} /*分离共享内存*/
if((shmdt((void *)share_temp)) == -)
{
printf("memory fenli failed\n");
exit(EXIT_FAILURE);
} return ;
}
/*read.c*/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> /*共享内存中缓冲区的大小*/
#define BUFFER_SIZE 2048 struct temp
{
int write_flag;
char share_buffer[BUFFER_SIZE]
}; int main(int argc, char const *argv[])
{
int shmid; /*循环开关*/
int running = ; struct temp *share_temp; key_t key = ftok(".", ); /*创建共享内存*/
if((shmid = shmget(key, sizeof(struct temp), IPC_CREAT|)) == -)
{
printf("memory get failed\n");
exit(EXIT_FAILURE);
} printf("shmid is %d\n", shmid); /*映射共享内存*/
if((share_temp = shmat(shmid, NULL, )) == (void *)-)
{
printf("memory at failed\n");
exit(EXIT_FAILURE);
} /*循环读取数据*/
while(running)
{
if(share_temp->write_flag)
{
printf("write is %s\n", share_temp->share_buffer);
share_temp->write_flag = ;
} if(strncmp(share_temp->share_buffer, "end", ) == )
running = ;
} /*分离共享内存*/
if((shmdt((void *)share_temp)) == -)
{
printf("memory fenli failed\n");
exit(EXIT_FAILURE);
} /*删除共享内存*/
if((shmctl(shmid, IPC_RMID, )) == -)
{
printf("memory delete failed\n");
exit(EXIT_FAILURE);
} return ;
}

  下面说说写程序过程中遇到的问题:开始用普通用户执行read程序,创建共享内存的时候没有加上0666选项,结构返回错误信息memory at failed,即连接到进程空间失败,切换到root用户再执行就可以。一开始还以为linux歧视普通用户,不让普通用户使用共享内存。后来发现创建的时候加上权限0666就可以了,其他IPC对象也同理。

  如果有疑问或错误,欢迎指出。

UNIX环境下的共享内存的更多相关文章

  1. [转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile

    http://blog.csdn.net/stpeace/article/details/39534361 进程间的通信方式有很多种, 上次我们说了最傻瓜的“共享外存/文件”的方法. 那么, 在本文中 ...

  2. Linux环境进程间通信(五): 共享内存(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  3. Unix IPC之基于共享内存的计数器

    目的 本文主要实现一个基于共享内存的计数器,通过父子进程对其访问. 本文程序需基于<<Unix网络编程-卷2>>的环境才能运行.程序中大写开头的函数为其小写同名函数的包裹函数, ...

  4. Linux环境进程间通信(五): 共享内存(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  5. Tomcat集群环境下session共享方案 通过memcached 方法实现

    对于web应用集群的技术实现而言,最大的难点就是:如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块.要实现这一点, 大体上有两种方式:一种是把所有Ses ...

  6. 缓存利器、Lua模块下的共享内存

    上一节讲到了worker进程的共享内存,它利用丰富的指令使数据的缓存操作变得非常简单,但它也存在一些缺点. 1.worker进程之间会有锁竞争,在高并发的情况下会增加性能开销.2.只支持Lua布尔值. ...

  7. win32下进程间通信——共享内存

    一.引言     在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...

  8. Linux环境编程之共享内存区(一):共享内存区简单介绍

    共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...

  9. 【SpringBoot】spring-session-data-redis 解决集群环境下session共享

    为什么会产生Session共享问题   集群情况下,session保存在各自的服务器的tomcat中,当分发地址至不同服务时,导致sesson取不到,就会产生session共享问题. 解决方案 负载均 ...

随机推荐

  1. transition的四个属性

    transition-property 规定设置过渡效果的 CSS 属性的名称. transition-duration 规定完成过渡效果需要多少秒或毫秒. transition-timing-fun ...

  2. linux工具问题,tail -f 失效

    最近发现一个很奇怪问题: tail -f 不能实时的输出日志

  3. 在ASP中调用DLL的方法

    .net的dll已经不是严格意义上的动态连接库了,而是一个类或者类库.它是不能直接在ASP.VB等其它的应用环境中使用的.   我们可以通过COM包装器(COM callable wrapper (C ...

  4. cookie防篡改

    概述: 除了 session 外,一般不会在客户端的 cookies 里保存过于重要的凭据,但电商应用有时候不可避免地存储了一些敏感数据到客户端,当然不希望被篡改. 目的: 让服务器端能识别cooki ...

  5. cmd运行java程序,无黑框闪烁

    程序目录中创建 “启动.bat” @echo off set mypath="%~dp0myjar.jar" echo %mypath% start javaw -jar %myp ...

  6. tomcat 正常启动,无法访问。且项目启动无问题。。。的解决办法。。

    Eclipes解决方法: 1.右击项目,选择propreties选项 2.在弹出的首选项窗口的左侧选择“Web Project Settings” 3.修改context root:输入框,修改成自己 ...

  7. KAFKA分布式消息系统[转]

    KAFKA分布式消息系统  转自:http://blog.chinaunix.net/uid-20196318-id-2420884.html Kafka[1]是linkedin用于日志处理的分布式消 ...

  8. 算法系列之图--BFS

    广度优先搜索以源结点s为出发点,算法始终将已发现和未发现结点之间的边界,沿其广度方向向外扩展.也即算法需要在发现所有距离源结点s为k的所有结点之后才会去发现距离源结点距离为k+1的其他结点. talk ...

  9. grunt 合并压缩任务

    module.exports = function(grunt) { // LiveReload的默认端口号,你也可以改成你想要的端口号 var lrPort = 35729; // 使用connec ...

  10. 页面加载完成,但ie进度条一直加载

    页面ajax执行完删除等操作,会刷新当前页面,如果前端框架是左右iframe格式 我的前端页面提示用asyncBox,可能iframe和asyncBox的影响,出现这种情况: 网上大多数的说法是 页面 ...