Linux编程基础 5.4:共享内存

5 共享内存

  • 共享内存允许两个或多个进程访问给定的同一块存储区域。它是效率最高的一种进程通信方式,节省了不同进程间多次读写的时间;
  • 在写进程的操作尚未完成时,不应有进程从共享内存中读取数据。共享内存自身不限制对共享内存的读写次序,程序开发人员应自觉遵循读写规则;
  • 一般情况下,共享内存与信号量一起使用,由信号量帮它实现读写操作的同步;
  • Linux提供了如下系统调用来实现共享内存的申请、管理与释放:
    – shmget
    – shmat
    – shmdt
    – shmctl

5.1 shmget函数

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

功能:创建一个新的共享内存或打开一块已存在的共享内存。

参数说明

  • key:传入参数,共享内存的键值,通常为一个整数;
  • size:设置共享内存的大小;
  • shmflg:设置shmget函数的创建条件(一般设置为IPC_CREAT或IPC_EXCL)及进程对共享内存的读写权限。

返回值说明

  • 成功:返回共享内存的标识符,一个非负整数;
  • 不成功:返回-1并设置errno。

5.2 shmat函数

#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:进行地址映射,将共享内存映射到进程虚拟地址空间中。

参数说明

  • shmid:共享内标识符,通常为shmget函数的返回值;
  • shmaddr:指针类型的传入参数,用于指定共享内存映射到虚拟内存时的虚拟地址,设置为NULL时,映射地址由系统决定;
  • shmflg:设置共享内存的使用方式,如果shmflg = SHM_RDONLY,则共享内存将以只读的方式进行映射,当前进程只能从共享内存中读取数据。

返回值说明

  • 成功:返回映射的地址并更改共享内存shmid_ds结构中的属性信息;
  • 不成功:返回-1并设置errno。

5.3 shmdt函数

#include <sys/shm.h>int shmdt(const void *shmaddr);

功能:解除物理内存与进程虚拟地址空间的映射关系。

参数说明

  • shmaddr:shmat函数返回的虚拟空间地址。

返回值说明

  • 成功:返回映射的地址并更改共享内存shmid_ds结构中的属性信息;
  • 不成功:返回-1并设置errno。

5.4 shmctl函数

#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//为了方便对共享内存进行管理,由内核维护的存储共享内存属性信息的结构体:
struct shmid_ds{struct ipc_perm shm_perm;			/* 操作权限*/size_t shm_segsz;                   /*段的大小(以字节为单位)*/time_t shm_atime;          			/*最后一个进程附加到该段的时间*/time_t shm_dtime;          			/*最后一个进程离开该段的时间*/time_t shm_ctime;          			/*最后一个进程修改该段的时间*/unsigned short shm_cpid;   			/*创建该段进程的pid*/unsigned short shm_lpid;   			/*在该段上操作的最后1个进程的pid*/short shm_nattch;          			/*当前附加到该段的进程的个数*//*下面是私有的*/unsigned short shm_npages;  		/*段的大小(以页为单位)*/unsigned long *shm_pages;   		/*指向frames->SHMMAX的指针数组*/struct vm_area_struct *attaches; 	/*对共享段的描述*/
};

功能:对已存在的共享内存进行操作,具体的操作由参数确定。

参数说明

  • shmid:共享内存标识符;
  • cmd:要执行的操作,常用的设置为IPC_RMID,功能为删除共享内存;
  • buf:对共享内存的管理信息进行设置,该参数是结构体shmid_ds的指针。

返回值说明

  • 成功:返回0;
  • 不成功:返回-1并设置errno。

特殊说明

  • 共享内存与消息队列、信号量相同,在使用完毕后都应该进行释放;
  • 调用fork函数创建子进程时,子进程会继承父进程已绑定的共享内存;
  • 当调用exec函数更改子进程功能及调用exit函数时,子进程都会解除与共享内存的映射关系,因此在必要时仍应使用shmctl函数对共享内存进行删除。

【案例1】使用共享内存机制实现两个进程间的通信。

shm_w.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define SEGSIZE 4096			//定义共享内存容量
typedef struct{					//读写数据结构体char name[8];int age;
} Stu;
int main() {int tempShmId, i;key_t tempKey;char tempName[8];Stu *tempSmap;/*ftok函数的作用:系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。*/tempKey = ftok("/", 0);			//获取关键字if (tempKey == -1) {perror("ftok error");return -1;}//of ifprintf("key=%d\n", tempKey);//创建共享内存tempShmId= shmget(tempKey, SEGSIZE, IPC_CREAT | IPC_EXCL | 0664);if (tempShmId == -1) {perror("create shared memory error\n");return -1;}//of ifprintf("shm_id=%d\n", tempShmId);tempSmap = (Stu*)shmat(tempShmId, NULL, 0);	//将进程与共享内存绑定memset(tempName, 0x00, sizeof(tempName));strcpy(tempName, "Jhon");tempName[4] = '0';for (i = 0; i < 3; i++){					//写数据tempName[4] += 1;strncpy((tempSmap+ i)->name, tempName, 5);(tempSmap + i)->age = 20 + i;}//of for iif (shmdt(tempSmap) == -1){					//解除绑定perror("detach error");return -1;}//of ifreturn 0;
}//of mainshm_r.c
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct{char name[8];int age;
} Stu;
int main() {int tempShmId, i;key_t tempKey;Stu *tempSmap;struct shmid_ds tempBuf;tempKey = ftok("/", 0);				//获取关键字if (tempKey == -1) {perror("ftok error");return -1;}//of ifprintf("key=%d\n", tempKey);tempShmId = shmget(tempKey, 0, 0);		//创建共享内存if (tempShmId == -1) {perror("shmget error");return -1;}//of ifprintf("shm_id=%d\n", tempShmId);tempSmap = (Stu*)shmat(tempShmId, NULL, 0);	//将进程与共享内存绑定for (i = 0; i < 3; i++){					//读数据printf("name:%s\n", (*(tempSmap + i)).name);printf("age :%d\n", (*(tempSmap + i)).age);}//of for iif (shmdt(tempSmap) == -1){					//解除绑定perror("detach error");return -1;}//of ifshmctl(tempShmId, IPC_RMID, &tempBuf);			//删除共享内存return 0;
}//of main

6 小结

了解Linux进程间的通信方式是学习Linux编程的基础,也是学习和实现复杂编程的基石。

7 编程题

(1)父进程向无名管道写入小写字母,子进程读出后转换为大写字母写入管道,父进程再将其读出;
(2)父进程向共享内存输入字符,子进程判断是否是自己要接收的信息,是的话,输出共享内存中的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/507414.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

升级浏览器_微软IE11浏览器 最后的升级机会

微软IE10浏览器将很快退出支持&#xff0c;许多Windows用户将没有任何安全或非安全更新&#xff0c;免费或付费辅助支持选项或在线技术内容等。幸运的是&#xff0c;微软正在为Windows用户提供升级到IE11的最后机会&#xff0c;目前IE11仅次于Firefox浏览器&#xff0c;这是互联…

jq如何获取选中option的值_【分享】如何获取变量token的值

一.什么是token客户端使用用户名跟密码请求登录服务端收到请求&#xff0c;去验证用户名与密码验证成功后&#xff0c;服务端会签发一个 Token&#xff0c;再把这个 Token 发送给客户端客户端收到 Token 以后可以把它存储起来&#xff0c;比如放在 Cookie 里或者 LocalStorage …

Linux编程基础 6.1:线程操作

1 线程操作 创建线程 挂起线程 终止线程 其它操作 1.1 创建线程 #include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); 功能&#xff1a;创建线程&#xff1b;线程调用pthread_crea…

灯效控制器和rgb控制器_更具个性的RGB风扇,机箱里的魔术师,九州风神MF120GT开箱...

写在前面不知道在2020年还有多少人会自己装机&#xff0c;相信喜欢个性的DIY玩家还是会陆陆续续跳进这个不小的坑。装机的乐趣在哪里&#xff0c;除了几大硬件&#xff0c;显然个性的灯效才是装机的灵魂。在光污染的道路上&#xff0c;普通的光环&#xff0c;光面等风扇&#x…

华为交换机ssh思科交换机_华为交换机SSH(stelnet)配置实例教程

Stelnet(安全telnet)登陆也成为shh(sercure shell,安全外壳)登陆-----------必要配置---------------1、先根据加密算法生成秘钥对,用于传输数据时加密保护&#xff0c;保存在交换机中但不保存在配置文件中[Huawei]rsa local-key-pair create或[Huawei]dsa local-key-pair crea…

Linux编程基础 6.2:线程同步

2 线程同步 线程同步中的“同步”与生活中大家认知的“同步”略有不同&#xff0c;“同”不指同时&#xff0c;其主旨在于协同步调&#xff0c;按预定的先后次序执行线程&#xff1b;之所以需要实现线程同步&#xff0c;是因为若不对线程的执行次序加以控制&#xff0c;可能会…

电脑开两个微信_电脑怎么登录两个微信

1/4下载并安装微信电脑客户端&#xff0c;保证这台电脑没有登陆微信2/4就像正常打开微信一样&#xff0c;不过不是双击&#xff0c;而是快速连点四次3/4我们可以看到有两个微信登陆界面4/4用两个不同的账号进行扫码登陆即可

idea 查询项目代码行数_idea统计代码行数Statistic的步骤详解

idea统计代码行数Statistic的步骤详解idea统计代码行数可以用到插件&#xff1a;Statistic。步骤&#xff1a;File→Settings进入Plugins点击Marketplace搜索Statistic 安装蓝框标出的插件重启idea后就可以看到效果了(图是拿的别人的&#xff0c;基本就是这效果)如果没有下…

Linux编程基础 7.1:套接字通信流程及编程接口

1 socket通信流程 2 socket编程接口 Linux系统中常用的socket网络编程接口有&#xff1a; socket()bind()listen()accept()connect()send()recv()close()其中connect()与send()为客户端专用接口&#xff1b;bind()、listen()、accept()及recv()为服务器端专用接口&#xff1b…

cad2016中选择全图字体怎么操作_cad教程分享CAD中如何删除顽固图层?

Autocad教程公众号&#xff0c;专注于cad教程、cad教程视频的分享&#xff0c;欢迎关注&#xff0c;下载你所需的教程资源&#xff01;如你还未关注&#xff0c;请点击文章标题下方蓝色字体的"Autocad教程"进行关注。cad教程分享-CAD中如何删除顽固图层&#xff1f;方…

python开启多个端口服务_python bottle使用多个端口(多个进程)提高并发

我的程序是用python结合bottle框架写的&#xff0c;但bottle自带wsgi原本只是单进程单线程运行模式(Bottle 默认运行在内置的 wsgiref 服务器上面。这个单线程的 HTTP 服务器在开发的时候特别有用&#xff0c;但其性能低下&#xff0c;在服务器负载不断增加的时候也许会是性能瓶…

Linux编程基础 7.2:服务器和客户端编程案例

1 网络字节序 大端模式&#xff1a;若将数据的高字节保存在内存的低地址&#xff0c;将数据的低字节保存在内存的高地址&#xff1b; 小端模式&#xff1a;若将数据的高字节保存在内存的高地址&#xff0c;将数据的低字节保存在内存的低地址。 网络数据流&#xff1a;大端模式…

div 隐藏_div的position属性

如果你想把div放到合适的位置&#xff0c;请看看这篇文章。<!-- div的position属性--><html><style>.red{height:100px;background:red;}.green{height:100px;background:green;position:relative;left:50px;top:50px;}.black{height:100px;background:black…

苹果笔记本python怎么换行_python怎么换行,我的换行就是执行啊

展开全部首先运行终端或者cmd命令行(windows下)。e69da5e887aa62616964757a686964616f31333433646338执行python3.5的命令。然后输入如下图所示的内容。这种换行方法也可以在编辑器中进行&#xff0c;这里以vim为例&#xff0c;输入与上图类似的代码&#xff0c;保存为t.py脚本…

Linux编程基础 7.3:套接字本地通信

1 socket本地通信 socket原本是为网络通讯设计的&#xff0c;但后来在socket框架的基础上发展出了一种IPC&#xff08;进程通信&#xff09;机制&#xff0c;即UNIX Domain Socket&#xff0c;专门用来实现使用socket实现的本地进程通信。 本地通信的流程与使用的接口与基于TC…

乔布斯在斯坦福大学演讲稿英文_西方大文豪最爱的10个英文单词,写尽人世间细腻情感!...

从小浸染在汉语中的我们&#xff0c;常被汉字的意象美震撼到&#xff0c;一字就是一世界。汉字有种无与伦比的美丽&#xff0c;寥寥数字就能营造“只可意会不可言传”的意境&#xff0c;很多人感慨英文就是一串拉丁字母&#xff0c;无法传递细腻的情感。比如很多人说像「缘分」…

dorado 刷新_dorado7常用内容

tabControl").set("currentTab","tab2");// 通过tab的索引(index)属性切换view.get("#tabControl").set("currentIndex",1);//根据名字切换tabvar tab self.get("currentTab").get("name");if(tab!"ta…

web前端开发论文写作_外语论文文献引言格式—MLA Style

我们之前讨论了外语论文文献引用格式—APA Style和Chicago Style—芝加哥论文脚注引注格式&#xff0c;今天我们来介绍在Essay写作中如何使用APA格式引用文献。MLA格式是英文论文写作最常用的一种参考文献格式。很多留学小伙伴都觉得MLA引用格式很复杂&#xff0c;今天译然小编…

Linux编程基础--目录

本系列教程以《Linux编程基础》为基础&#xff0c;希望在大家的帮助下&#xff0c;逐步完善Linux下系统级程序设计。 1 初识Linux 1.1 课程简介及Linux介绍 2 Linux文件操作 2.1 文件I/O 2.2 文件操作 3 进程管理 3.1 进程控制 3.2 exec家族 3.3 进程同步 4 信号 4.1 系…

100999凑整到万位进一_四年级数学专项练习

填空题1、当除数是34时&#xff0c;试商时可以把除数看作( )&#xff0c;这样初商容易偏( )。2、()个26相加的和是468&#xff1b;()比12个15多20。3、34&#xff1d;21……&#xff0c;余数最大是()&#xff0c;这时被除数是()。4、在括号里填上合适的数。480秒()分540厘米()分…