Linux IPC实践(9) --System V共享内存
共享内存API
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//System V 共享内存基本数据结构
struct shmid_ds
{
struct ipc_perm shm_perm; /* Ownership and permissions: System V IPC所共有的数据结构 */
size_t shm_segsz; /* Size of segment (bytes): 共享内存段的大小 */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
};
shmget
int shmget(key_t key, size_t size, int shmflg);
创建共享内存,并将该内存的内容初始化为0;
打开一个已经存在共享内存, 如果打开时不知道共享内存的大小, 可以将size指定为0, shmflg可以指定为0(按照默认的权限打开);
参数:
key:这个共享内存段名字;
size:共享内存大小(bytes);
shmflg:用法类似msgget中的msgflg参数;
返回值:
成功返回一个非负整数,即该共享内存段的标识码;失败返回-1
/**示例: 创建并打开一个共享内存 **/
int main(int argc,char **argv)
{
const int SHM_SIZE = 1024;
int shmid = shmget(0x1234, SHM_SIZE, 0666|IPC_CREAT);
if (shmid == -1)
err_exit("shmget error");
cout << "share memory get success" << endl;
}
shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
连接到本进程地址空间, 成功连接之后, 对该内存的操作就与malloc来的一块内存非常类似了, 而且如果这块内存中有数据, 则就可以直接将其中的数据取出来!!
参数:
shmaddr:指定连接的地址(推荐使用NULL)
shmflg:一般指定为0, 表示可读,可写; 而它的另外两个可能取值是SHM_RND和SHM_RDONLY(见下)
返回值:
成功返回一个指针,指向共享内存起始地址;失败返回(void *) -1
|
shmaddr与shmflg组合说明 |
|
|
shmaddr为NULL |
Linux内核自动为进程连接到进程的内存(推荐使用) |
|
shmaddr不为NULL且shmflg无SHM_RND标记 |
以shmaddr为连接地址 |
|
shmaddr不为NULL且shmflg设置了SHM_RND标记 |
连接的地址会自动向下调整为SHMLBA的整数倍; 公式:shmaddr - (shmaddr % SHMLBA) SHMLBA为内存页面的大小(4K) |
|
shmflg=SHM_RDONLY |
只读共享内存, 不然的话就是可读,可写的, 注意: 此处没有可读,可写这个概念 |
shmdt
int shmdt(const void *shmaddr);
参数:
shmaddr: 由shmat所返回的指针
注意:将共享内存段与当前进程脱离不等于删除共享内存段
/** 示例: 将数据写入/读出共享内存
程序write: 将数据写入共享内存
程序read: 将数据读出共享内存(当然, 可以读取N多次)
**/
//write程序
struct Student
{
char name[26];
int age;
};
int main(int argc,char **argv)
{
int shmid = shmget(0x1234, sizeof(Student), 0666|IPC_CREAT);
if (shmid == -1)
err_exit("shmget error");
// 以可读, 可写的方式连接该共享内存
Student *p = (Student *)shmat(shmid, NULL, 0);
if (p == (void *)-1)
err_exit("shmat error");
strcpy(p->name, "xiaofang");
p->age = 22;
shmdt(p);
}
//read程序
int main(int argc,char **argv)
{
int shmid = shmget(0x1234, 0, 0);
if (shmid == -1)
err_exit("shmget error");
// 以只读方式连接该共享内存
Student *p = (Student *)shmat(shmid, NULL, 0);
if (p == (void *)-1)
err_exit("shmat error");
// 直接将其中的内容打印输出
cout << "name: " << p->name << ", age: " << p->age << endl;
shmdt(p);
}
shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
设置/获取共享内存属性
参数:
cmd:将要采取的动作(三个取值见下)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
System V共享内存小结:
1.共享内存被别的程序占用,则删除该共享内存时,不会马上删除(引用计数计数);
2.此时会出现一个现象:该共享内存的key变为0x00000000,变为私有;
3.此时还可以读,但必须还有办法获取该共享内存的ID(shmid),因为此时试图通过该共享内存的key获取该共享内存,是白费的!
/** 示例: 删除共享内存 **/
int main(int argc,char *argv[])
{
int shmid = shmget(0x1234, 0, 0);
if (shmid == -1)
err_exit("shmget error");
if (shmctl(shmid, IPC_RMID, NULL) == -1)
err_exit("shmctl IPC_RMID error");
cout << "share memory remove success" << endl;
}
Linux IPC实践(9) --System V共享内存的更多相关文章
- Linux进程通信之System V共享内存
前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...
- linux网络编程之system v共享内存
接着上次的共享内存继续学习,这次主要是学习system v共享内存的使用,下面继续: 跟消息队列一样,共享内存也是有自己的数据结构的,system v共享内存也是随内核持续的,也就是说当最后一个访问内 ...
- Linux IPC实践(13) --System V IPC综合实践
实践:实现一个先进先出的共享内存shmfifo 使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速; 我们首先完成C语言版本的shmfifo(基于过程调用) ...
- Linux IPC实践(11) --System V信号量(1)
信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...
- Linux IPC实践(6) --System V消息队列(3)
消息队列综合案例 消息队列实现回射客户/服务器 server进程接收时, 指定msgtyp为0, 从队首不断接收消息 server进程发送时, 将mtype指定为接收到的client进程的pid ...
- Linux IPC实践(12) --System V信号量(2)
实践1:信号量实现进程互斥 父子进程执行流程如下: 父进程 子进程 P P O(print) X(print) sleep sleep O(print) X(print) V V sleep slee ...
- Linux IPC实践(4) --System V消息队列(1)
消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足: ...
- Linux IPC实践(5) --System V消息队列(2)
消息发送/接收API msgsnd函数 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数 msgid: 由ms ...
- 阐述linux IPC(五岁以下儿童):system V共享内存
[版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途] system V共享内存和posix ...
随机推荐
- Java不走弯路教程(前言)
本教程的程序基于Windows开发,所以你需要有一台安装Windows操作系统的电脑. 前言本教程将带你完成Java的初学和WEB框架的开发,学完本教程,你将完成对Java的入门并且对下一步不再迷茫. ...
- Python中迭代输出(index,value)的几种方法
需求如下:迭代输出序列的索引(index)和索引值(value). 1.创建测试列表: >>> lst = [1,2,3,4,5] 2.实现方法如下: #方法1:range()+le ...
- MySql配置文件模板
写在开篇: 这个mysql得配置文件my.cnf,是我现在环境里常用得,包含基础配置及一些优化,本来一直在我得有道笔记里记录着,之前一直没有写博客的习惯,最近刚开始注册博客,就将这些东西 ...
- 实验与作业(Python)-04 数据类型、数学函数与字符串
截止日期 实验目标 继续熟悉for循环与turtle 数值运算符 math库常用函数 字符串转化为数值类型(int, float, complex) 字符串常用函数 实验内容 任务1.使用for代替w ...
- git 同步勾子
#!/bin/bash git --git-dir=/var/www/domain/.git --work-tree=/var/www/domain pull uwsgi --reload /tmp/ ...
- 网站开发进阶(四十四)input type="submit" 和"button"的区别
网站开发进阶(四十四)input type="submit" 和"button"的区别 在一个页面上画一个按钮,有四种办法: 这就是一个按钮.如果你不写ja ...
- springMVC源码分析--访问请求执行ServletInvocableHandlerMethod和InvocableHandlerMethod
在之前一篇博客中springMVC源码分析--RequestMappingHandlerAdapter(五)我们已经简单的介绍到具体请求访问的执行某个Controller中的方法是在RequestMa ...
- 【Java二十周年】Delphi转行java的一些小感触
本文纯属一届小码农对java使用过程的体验感触 目录: 初遇java编程语言 与java的擦肩 深入java 跨平台性 开源支持 web的支撑 初遇java编程语言 刚上大学的时候,完全是个电脑盲.刚 ...
- Spring之WEB模块
Spring的WEB模块用于整合Web框架,例如Struts 1.Struts 2.JSF等 整合Struts 1 继承方式 Spring框架提供了ActionSupport类支持Struts 1的A ...
- 打开Voice Over时,CATextLayer的string对象兼容NSString和NSAttributedString导致的Crash(二解决思路3)
续前一篇:打开Voice Over时,CATextLayer的string对象兼容NSString和NSAttributedString导致的Crash(二解决思路2)ok,到这里已经能够锁定范围了, ...