linux 共享内存
共享内存是最高效的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 共享内存的更多相关文章
- Linux 程序设计1:深入浅出 Linux 共享内存
笔者最近在阅读Aerospike 论文时,发现了Aerospike是利用了Linux 共享内存机制来实现的存储索引快速重建的.这种方式比传统利用索引文件进行快速重启的方式大大提高了效率.(减少了磁盘 ...
- linux 共享内存shm_open实现进程间大数据交互
linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #includ ...
- Linux共享内存(二)
Linux共享内存编程实例 原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119 /*共享内存允许两个或多个进程进程共享同一块 ...
- linux 共享内存实现
说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享 ...
- Linux共享内存
1.什么是共享内存在前面讲虚拟内存机制时,有讲到Linux的内存映射机制:初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来.由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被多个进 ...
- Linux共享内存(一)
inux系统编程我一直看 <GNU/LINUX编程指南>,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http:/ ...
- 修改linux共享内存大小
这是实际linux系统显示的实际数据: beijibing@bjb-desktop:/proc/sys/kernel$ cat shmmax 33554432 beijibing@bjb-deskt ...
- 【转载】ipcs与Linux共享内存
一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要 ...
- Linux 共享内存 详解
一.什么是共享内存区 共享内存区是最快的可用IPC形式.它允许多个不相关的进程去访问同一部分逻辑内存.如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映射到 ...
随机推荐
- Postman工具——下载与安装(转)
https://blog.csdn.net/water_0815/article/details/53263643 今天给大家分享一款工具,好的工具能够让开发更高效,有时能成倍地提高.接下来会分几篇来 ...
- FlexPaper查看Flash文件
HTML 代码: <head> <meta http-equiv="Content-Type" content="text/html; charset= ...
- MySQL慢查询分析工具pt-query-digest详解
一.简介 pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog.General log.slowlog,也可以通过SHOWPROCESSLIST或者通过tcpdu ...
- jquery的on()方法总结
摘自菜鸟教程 废话不说 直接上demo 实例: 向<p>元素添加click事件处理程序: <html> <head> <script src="ht ...
- Java Knowledge series 4
JVM & Bytecode Has-a or Is-a relationship(inheritance or composition) 如果想利用新类内部一个现有类的特性,而不想使用它的接 ...
- cocos2d-x游戏之2048
学习游戏编程是一件非常有趣的事情,在cocos2dx官网找了几个简单的游戏试试手,感觉也不是那么难,首先来看看2048这款游戏吧,很火的原因之一是因为它简单而易操作.网上这位Legendof1991大 ...
- Linux文件种类与扩展名
一.文件种类 1)普通文件:ls -al第一个字符为[-]的 纯文本文件(ASCII) 二进制文件(binary):Linux中的可执行文件 数据格式文件(data):特定格式的文件,如:Linux登 ...
- CentOS7下SSH服务学习笔记
测试环境: [root@nmserver-7 ~]# uname -aLinux nmserver-7.test.com 3.10.0-514.el7.centos.plus.i686 #1 SMP ...
- PHP 简单调用rest WebServices
<?php $ch = curl_init("http://api.cachk.com:8185/Tech-Trans.esPOS4.PosService.UAT/rest/enqui ...
- c++的bind1st()与bind2nd() 二元算子转一元算子
bind1st()和bind2nd()是两个函数,用于将二元算子转成一元算子. 何谓二元算子? 比如< > =等等这些就是二元算子,即需要两个操作数的运算符. 何谓一元算子? 比如++ - ...