TA的每日心情 | 开心 2021-12-13 21:45 |
---|
签到天数: 15 天 [LV.4]偶尔看看III
|
Linux进程IPC浅析[进程间通信SystemV共享内存]
共享内存概念,概述
共享内存的相关函数
共享内存概念,概述:
共享内存区域是被多个进程共享的一部分物理内存
多个进程都可把该共享内存映射到自己的虚拟内存空间,全部用户空间的进程若要操作共享内存。都要将其映射到自己的虚拟内存空间中。通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信
共享内存是进程间共享数据的一种最快的方法。一个进程向共享内存区域写入了数据。共享这个内存区域的全部进程就能够立马看到当中的内容
本身不提供同步机制,可通过信号量进行同步(用信号量进行通知)
提升数据处理效率。一种效率最高的IPC机制
共享内存的属性信息:
- [code]struct shmid_ds{
- struct ipc_perm shm_perm;
- size_t shm_segsz; //共享内存大小
- pid_t shm_lpid; //最后一次调用系统调用的进程的pid
- pid_t shm_cpid; //创建者pid
- shmatt_t shm_nattch;//当前成功映射的进程的数量
- time_t shm_atime; //最后一个成功映射的时间
- time_t shm_dtime; //最后一个解除映射的时间
- time_t shm_ctime; //最后一次改变的时间
- ....;
- }
复制代码 [/code]
共享内存的使用步骤:
- [code]使用shmget函数创建共享内存
- 使用shmat函数映射共享内存。将这段创建的共享内存映射到详细的进程虚拟内存空间中
复制代码 [/code]
创建共享内存
- [code]#include<sys/shm.h>
- int shmget(key_t key,size_t size,int shmflg);
- 返回:假设成功。返回内核中共享内存的表示ID,假设失败,则返回-1
- 參数:
- key:用户制定的共享内存键值
- size_t:共享内存的大小
- shmflg:IPC_CREAT,IPC_EXCL等权限
- errno:
- EINVAL(无效的内存段)
- EEXIST(内存段已经存在。无法创建)
- EIDRM(内存段已经被删除)
- ENOENT(内存段不存在)
- EACCES(权限不够)
- ENOMEN(没有足够的内存来创建内存段)
复制代码 [/code]
对共享内存的控制:
- [code]#include<sys/shm.h>
- int shmctl(int shmid,int cmd,struct shmid_ds *buf);
- 返回:成功返回0,出错返回-1
- 參数:
- shmid:共享内存ID
- buf:共享内存属性指针
- cmd:
- IPC_STAT 获取共享内存段属性
- IPC_SET 设置共享内存段属性
- IPC_RMID 删除共享内存段
- SHM_LOCK 锁定共享内存段页面
- SHM_UNLOCK 解除共享内存段页面的锁定
复制代码 [/code]
共享内存的映射和映射的解除:
- [code]#include<sys/shm.h>
- void* shmat(int shmid,char *shmaddr,int shmflag);
- 返回:成功返回共享内存映射到进程虚拟内存空间中的地址。失败返回-1,然后通过操作共享内存的地址来进行写操作
- int shmdt(char *shmaddr);
- 返回:假设失败,返回-1
- 參数:
- shmid:共享内存ID
- shmaddr:映射到进程虚拟内存空间的地址,建议设置为0,由系统分配
- shmflg:若shmaddr设置为0,则shmflag也设置为0
- SHM_RND
- SHMLBA 地址为2的乘方
- SHM_RDONLY 仅仅读方式链接
- errno
- EINVAL 无效的IPC ID值或者无效的地址
- ENOMEN 没有足够内存
- EACCESS 权限不够
- 子进程不继承父进程创建的共享内存,大家是共享的,子进程继承父进程映射的地址
复制代码 [/code]
下面的代码是通过管道的形式来对共享内存实现同步,一个进程实现对共享内存的写后,通过管道通知另外一个进程去从共享内存中去读取:
- [code]/*
- * ===========================================================================
- *
- * Filename: tell.h
- * Description:
- * Version: 1.0
- * Created: 2017年04月16日 10时40分31秒
- * Revision: none
- * Compiler: gcc
- * Author: (),
- * Company:
- *
- * ===========================================================================
- */
- #ifndef __TELL_H_
- #define __TELL_H_
- //初始化管道
- extern void pipe_init();
- //通知管道
- extern void pipe_notify();
- //管道堵塞等待
- extern void pipe_wait();
- //销毁管道
- extern void pipe_destory();
- #endif
复制代码 [/code]
- [code]/*
- * ===========================================================================
- *
- * Filename: tell.c
- * Description:
- * Version: 1.0
- * Created: 2017年04月16日 10时42分23秒
- * Revision: none
- * Compiler: gcc
- * Author: (),
- * Company:
- *
- * ===========================================================================
- */
- #include<stdio.h>
- #include<stdlib.h>
- #include"tell.h"
- #include<unistd.h>
- #define BUFFER_SIZE 1024
- //管道的文件描写叙述符号
- static int pipe_fd[2];
- //初始化管道
- extern void pipe_init(){
- if(pipe(pipe_fd) < 0){
- perror("create pipe error\n");
- }
- }
- //管道等待
- extern void pipe_wait(){
- char buffer[BUFFER_SIZE];
- if((read(pipe_fd[0],&buffer,sizeof(buffer))) != 0){
- printf("read content:%s\n",buffer);
- }
- }
- //通知管道
- extern void pipe_notify(){
- ssize_t size;
- char content[] = "notify";
- if((size = write(pipe_fd[1],content,sizeof(content))) !=sizeof(content)){
- perror("write error");
- }
- }
- //销毁管道
- extern void pipe_destory(){
- close(pipe_fd[0]);
- close(pipe_fd[1]);
- }
复制代码 [/code]
- [code]/*
- * ===========================================================================
- *
- * Filename: shmtest.c
- * Description:
- * Version: 1.0
- * Created: 2017年04月16日 10时51分54秒
- * Revision: none
- * Compiler: gcc
- * Author: (),
- * Company:
- *
- * ===========================================================================
- */
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<string.h>
- #include"tell.h"
- #include<sys/shm.h>
- #define SHM_BUFFER_SIZE 1024
- int main(int argc,char*argv[]){
- pid_t pid;
- int shmid;
- //创建共享内存
- shmid = shmget(IPC_PRIVATE,SHM_BUFFER_SIZE,IPC_CREAT | IPC_EXCL | 0777);
- if(shmid < 0){
- perror("create share memory error");
- }
- //初始化管道
- pipe_init();
- if((pid = fork()) < 0){
- }else if(pid > 0){
- //父进程运行的时间片
- //父进程进行共享内存的映射
- int* shm_int_pointer = shmat(shmid,0,0);
- if(shm_int_pointer == (int *)-1){
- perror("error");
- }
- //父进程往共享内存中写数据
- *shm_int_pointer = 10;
- *(shm_int_pointer + 1)= 100;
- *(shm_int_pointer + 2) = 1000;
- //取消共享内存的映射
- shmdt(shm_int_pointer);
- //通知子进程
- pipe_notify();
- //管道进行销毁
- pipe_destory();
- wait(0);
- }else{
- //子进程运行的时间片
- //子进程堵塞
- pipe_wait();
- int *shm_int_pointer = shmat(shmid,0,0);
- if(shm_int_pointer == (int *)-1){
- perror("error");
- exit(1);
- }
- int num1 = *shm_int_pointer;
- int num2 = *(shm_int_pointer+1);
- int num3 = *(shm_int_pointer+2);
- printf("num1:%d,num2:%d,num3:%d\n",num1,num2,num3);
- shmdt(shm_int_pointer);
- //删除共享内存
- int shm_ctl_result = shmctl(shmid,IPC_RMID,NULL);
- if(shm_ctl_result == -1){
- perror("delete shmctl error");
- }
- pipe_destory();
- }
- return 0;
- }
复制代码 [/code]
以上部分就是关于共享内存部分的相关简单的调用,代码调试过
欢迎持续訪问博客
|
|