共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输。这种高效带来的问题是,我们必须用其他手段来同步进程对共享内存的访问,否则会产生竞态条件。所以,共享内存通常和其他进程间通信方式一起使用。

linux 共享内存有四个系统调用:shmget, shmat, shmdt, shmctl

shmget

创建一段新的共享内存,或者获取一段已经存在的共享内存:

       #include <sys/ipc.h>
#include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);

key 是一个键值,用来标识一段全局唯一的共享内存。size 指定内存的大小,单位是字节。如果是创建内存,size必须指定,如果是获取已经存在的内存,size 可以设置为0

shmflg 和 semget的 semflg 参数相同。

shmget成功时返回一个正整数,它是共享内存的标识符。失败时返回-1,并设置errno.

shmat

共享内存被创建/获取之后,并不能立即访问它,而是需要先将它关联到进程的地址空间中。使用shmat函数:

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

shmid 参数是有shmget函数返回的标识符。shmaddr指定将共享内存关联到进程的哪块地址空间,如果为NULL,则被关联地址由操作系统选择。

成功时,返回共享内存被关联到的地址,失败则返回(void*)-1,并设置errno

shmdt

int shmdt(const void *shmaddr);

将关联的共享内存从进程分离。

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

shmctl

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

shmid 使用shmget返回的共享内存标识符。cmd指定执行的命令,常用的 IPC_RMID,表示将共享内存打上删除的标记,当最后一个使用它的进程调用shmdt将它从进程中分离时,该共享内存就被删除了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h> union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}; void ErrExit(const char* reason)
{
fprintf(stderr, "%s: %d, %s\n", reason, errno, strerror(errno));
exit();
} int initsem(int key = )
{
int semid = -; if (- == (semid = semget(key, , | IPC_CREAT)))
{
ErrExit("semget");
} union semun un;
un.val = ;
if (- == semctl(semid, , SETVAL, un))
{
ErrExit("semctl");
} return semid;
} void destroysem(int semid)
{
if (- == semctl(semid, , IPC_RMID))
{
ErrExit("semctl del");
}
} void P(int semid)
{
struct sembuf op;
op.sem_num = ;
op.sem_op = -;
op.sem_flg = SEM_UNDO;
if (- == semop(semid, &op, ))
{
ErrExit("semop p");
}
} void V(int semid)
{
struct sembuf op;
op.sem_num = ;
op.sem_op = ;
op.sem_flg = SEM_UNDO;
if (- == semop(semid, &op, ))
{
ErrExit("semop v");
}
} void waitfor0(int semid)
{
struct sembuf op;
op.sem_num = ;
op.sem_op = ;
op.sem_flg = SEM_UNDO;
if (- == semop(semid, &op, ))
{
ErrExit("semop wait");
}
} int main(int argc, char const *argv[])
{
int semid = initsem();
int shmid = -; int pipefd[]; // 管道用来传递 共享内存id
pipe(pipefd); pid_t pid = fork();
if (pid > )
{
P(semid);
close(pipefd[]);
printf("parent process...\n"); shmid = shmget(, , | IPC_CREAT);
if (- == shmid)
{
ErrExit("shmget");
} write(pipefd[], &shmid, ); void* p = shmat(shmid, NULL, );
if ((void*)- == p)
{
ErrExit("shmat");
} char buf[] = "data from parent";
memcpy(p, buf, strlen(buf)); printf("exit parent process...\n");
P(semid);
// P(semid);
waitpid(pid, NULL, ); destroysem(semid);
if (- == shmctl(shmid, IPC_RMID, NULL))
{
ErrExit("shmctl");
}
if (- == shmdt(p))
{
ErrExit("shmdt in parent");
}
}
else if ( == pid)
{
// 等待共享内存集的值变为0
waitfor0(semid);
close(pipefd[]);
printf("child process...\n"); read(pipefd[], &shmid, ); void* p = shmat(shmid, NULL, );
if ((void*)- == p)
{
ErrExit("shmat");
} char buf[] = {};
memcpy(buf, p, );
printf("%s\n", buf); if (- == shmdt(p))
{
ErrExit("shmdt in parent");
} // V(semid);
} return ;
}

linux 共享内存的更多相关文章

  1. Linux 程序设计1:深入浅出 Linux 共享内存

    笔者最近在阅读Aerospike 论文时,发现了Aerospike是利用了Linux 共享内存机制来实现的存储索引快速重建的.这种方式比传统利用索引文件进行快速重启的方式大大提高了效率.(减少了磁盘 ...

  2. linux 共享内存shm_open实现进程间大数据交互

    linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #includ ...

  3. Linux共享内存(二)

    Linux共享内存编程实例 原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119 /*共享内存允许两个或多个进程进程共享同一块 ...

  4. linux 共享内存实现

    说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享 ...

  5. Linux共享内存

    1.什么是共享内存在前面讲虚拟内存机制时,有讲到Linux的内存映射机制:初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来.由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被多个进 ...

  6. Linux共享内存(一)

    inux系统编程我一直看 <GNU/LINUX编程指南>,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http:/ ...

  7. 修改linux共享内存大小

    这是实际linux系统显示的实际数据: beijibing@bjb-desktop:/proc/sys/kernel$ cat shmmax  33554432 beijibing@bjb-deskt ...

  8. 【转载】ipcs与Linux共享内存

    一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要 ...

  9. Linux 共享内存 详解

    一.什么是共享内存区 共享内存区是最快的可用IPC形式.它允许多个不相关的进程去访问同一部分逻辑内存.如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映射到 ...

随机推荐

  1. <Android 基础(七)> DrawerLayout and NavigationView

    介绍 DrawerLayout是Support Library包中实现了侧滑菜单效果的控件 android.support.v4.widget.DrawerLayout NavigationView是 ...

  2. ArcGIS Desktop中面与面之间空隙填充

    1.前言 再给客户培训过程中被问到这样一个问题,几个面中间有一个空心部分(如下图所示),如何快速绘制中心部分的要素. 2.操作流程 1.打开Editor工具栏,开始编辑操作. 2.点击创建要素按钮,打 ...

  3. Thymeleaf基础知识

    Thymeleaf是一个Java类库,它是一个xml/xhtml/html5的模板引擎,可以作为MVC的Web引用的View层. Thymeleaf还提供了额外的模块与SpringMVC集成,因此推荐 ...

  4. MD5的32位加密方法

    /// <summary> /// MD532位加密方式 /// </summary> /// <param name="str">用户原始密码 ...

  5. httpclient使用head添加cookie

    最近在使用接口时候,我使用get请求时,需要携带登录态,所以在get请求的时候我需要在head里面把cookie给加上,添加方式get和post完全不一样 Post方式添加cookie httpPos ...

  6. POJ-2229 Sumsets---完全背包变形

    题目链接: https://vjudge.net/problem/POJ-2229 题目大意: 给定一个N,只允许使用2的幂次数,问有多少种不同的方案组成N. 思路: 处理出2的幂次方的所有的数字,当 ...

  7. Android(java)学习笔记141:Android下的逐帧动画(Drawable Animation)

    1. 帧动画: 帧动画顾名思义,一帧一帧播放的动画就是帧动画. 帧动画和我们小时候看的动画片的原理是一样的,在相同区域快速切换图片给人们呈现一种视觉的假象感觉像是在播放动画,其实不过是N张图片在一帧一 ...

  8. 2019.03.14 ZJOI2019模拟赛 解题报告

    得分: \(100+100+0=200\)(\(T1\)在最后\(2\)分钟写了出来,\(T2\)在最后\(10\)分钟写了出来,反而\(T3\)写了\(4\)个小时爆\(0\)) \(T1\):风王 ...

  9. Uva 11806 拉拉队

    题目链接:https://uva.onlinejudge.org/external/118/11806.pdf 题意: n行m列的矩阵上放k个棋子,其中要求第一行,最后一行,第一列,最后一列必须要有. ...

  10. UIView的层次调整,及子view布局模式自动布局模式(停靠模式)

    UIView*view1=[[UIView alloc]initWithFrame:CGRectMake(10,30,300,30)]; view1.backgroundColor=[UIColor ...