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形式.它允许多个不相关的进程去访问同一部分逻辑内存.如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映射到 ...
随机推荐
- Differences or similarities between Java and C++
“作为一名C++程序员,我们早已掌握了面向对象Object-oriented Programming程序设计的基本概念,而且Java的语法无疑是非常熟悉的.事实上,Java本来就是从C++衍生出来的. ...
- [原创] Debian9上配置软件阵列
序言 软阵列是用软件实现的磁盘阵列. 准备工作 1. 更新系统 没啥,就他喵想用个最新的. apt update && apt upgrade 2. 安装mdadm 如果系统没有自带m ...
- 【MATLAB】画信号频谱的子函数
输入信号序列和采样率,该子函数可以画出该信号的频谱图. function [f,spec,NFFT]=spec_fft_plot(sample,L,Fs) % 输入数据说明: % sample:信号序 ...
- Linux命令之查看服务进程(ps aux、ps -aux、ps -ef)的运用
执行ps命令即可列出的是当前服务器进程的快照(时间点),如果想要实时动态的显示进程信息,就可以使用top命令. linux上进程有5种状态: 1. 运行(正在运行或在运行队列中等待) 2. 中断( ...
- Linux安装 NTFS 支持
my system kernel Version is 2.6.18-128.el5 在这个地址下载了 kernel-module-ntfs-2.6.18-128.el5-2.1.27-0.rr.10 ...
- IOS 发布程序(打包上传)
• 发布程序的主要步骤 登录开发者主页 生成cer证书:cer是一个跟电脑相关联的证书文件,让电脑具备发布程序的功能 添加App ID:发布哪些app? 生成MobileProvision文件:生成一 ...
- Android(java)学习笔记59:类继承的 注意事项
1. 类继承的注意事项: /* 继承的注意事项: A:子类只能继承父类所有非私有的成员(成员方法和成员变量) B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法. ...
- 1993: C语言实验——最值
1993: C语言实验——最值 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1541 Solved: 727[Submit][Status][Web ...
- list 用法的随手记
在list 用法中.1. add是直接添加 一个变量.不能添加一个 集合元素,比如数组 这种写法是错误的 ,因为不能添加集合 这种写法是对的,因为直接添加元素 2. 但是addrannge 是添加一个 ...
- Mathematica 讲座
Mathematica 讲座笔记本 [下载] 第一章 Mathematica 简介 [观看] [下载] 第二章 Mathematica 界面和编程语言 [观看] [下载] 第三章 符号运算 [观看] ...