共享内存是最高效的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. poj 3107 删点最大分支最小

    http://poj.org/problem?id=3107 这实际上就是找重心,在之前有做过:http://www.cnblogs.com/qlky/p/5780933.html #include ...

  2. fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤)(转)

    fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤) Fiddler 有一个filters可以很好的帮助我们只显示我们关系的请求或 ...

  3. 织梦channelartlist标签内使用currentstyle

    找到文件\include\taglib\channelartlist.lib.php 找到代码 $pv->Fields['typeurl'] = GetOneTypeUrlA($typeids[ ...

  4. 栅格那点儿事(二)---细看Raster属性

    细看Raster属性 如果你已经看完了上一章,你已经了解了栅格数据是由一个个像元(Cell)按照行列方式构成的,每一个像元都有自己的像元值,并且这些像元值根据栅格类型的不同,可以代表反射值,或高程值, ...

  5. android listview 加载遇到的问题

    http://blog.csdn.net/l_serein/article/details/7706338 转载: 描述一下场景: 菜单栏上有若干分类,点击每一个分类,ListView下分根据分类显示 ...

  6. sql数据库常用操作

    string connectionString = @"Data Source=(local)\sql2008r2;Initial Catalog=Movies;Uid=sa;Pwd=sql ...

  7. Markdown快速上手指南

    Markdown快速上手指南 1.Markdown介绍 markdown可以实现快速html文档编辑,格式优没,并且不需要使用html元素. markdown采用普通文本的形式,例如读书笔记等易于使用 ...

  8. 如何通过C#实现网页信息采集的方法总结

    Internet上有着极其庞大的资源信息,各行各业的信息无所不有.网页的信息搜集就是获取网页的数据,然后通过程序分析,将有用的数据提取分离出来.搜索引擎工作的一部分就是网页数据抽取.比如编制程序抽取新 ...

  9. 笨办法学Python(二十五)

    习题 25: 更多更多的练习 我们将做一些关于函数和变量的练习,以确认你真正掌握了这些知识.这节练习对你来说可以说是一本道:写程序,逐行研究,弄懂它. 不过这节练习还是有些不同,你不需要运行它,取而代 ...

  10. ubuntu linux 使用命令行安装 google chrome

    原帖地址: https://www.cyberciti.biz/faq/how-to-install-google-chrome-in-ubuntu-linux-12-xx-13-xx/ $ wget ...