标签:共享资源 include system linux 操作系统
之前提到了进程间通信的管道,消息队列,信号量,然后其中信号量是PV操作,操控的是一个共享资源。在我们提到的IPC模块中,消息队列针对的是数据单元的信息传送,管道不属于system V IPC的部分,所以按照一个操作系统的整体来说,他应该也有着一个关于字节流的消息传输,并且要比之前都要快,还要跟我们之前所说的信号量利用起来,所以就出现了共享内存的概念。
什么是共享内存?
共享内存是多个进程之间共享内存区域的一种进程间的通信方式,他是在多个进程之间对内存段进行映射的方式实现内存共享的,这是IPC最快捷的方式,因为共享内存的方式的通信没有中间过程,二管道,消息队列等方式则是需要将数据通过中间机制进行转换。
共享内存方式直接将某段内存段进行映射,多个进程间的共享内存是统一快的物理空间,仅仅阿是地址不同而已,因此不需要进行复制,可以直接使用此段空间。
下面我们就来了解Linux下的共享内存相关的函数:
1.创建共享内存函数:
#include<sys/ipc.h> #include<sys/shm.h> int shmget(key_t key,size_t size,int shmflg);
第一个参数是关键字的值,然后,这个值将与内核中现有德1其他共享内存段的关键字值相比较,比较之后,依赖第3个参数,跟前面消息队列的一样。
2.获取共享内存地址函数shmat()
函数shmat()用来获取共享内存的地址,获取共享内存成功后,可以像使用通用内存一样对其进行读写操作,
#include<sys/ipc.h> #include<sys/shm.h> void* shmat(int shmid,const void *shmaddr,int shmflg); int shmdt(const void *shmaddr);
如果shmaddr参数值等于0,则内科将试着查找一个未映射的区域,用户可以指定一个地址,但通常改地址只用于访问所拥有的硬件,或者解决与其他应用程序的冲突。SHM_RND标志可以与标志参数进行OR操作,结果在置为标志参数。SHM_RDONLY标志参数进行OR操作,结果在置为标志参数,这样映射的共享内存端智能标记为只读方式。
shmdt()用于删除一段共享内存,这个函数之中,成功完成了断开连接操作以后,相关的shmid_ds结构的shm_nattch成员的值将减去1。如果这个值减到0.则内核将真正删除这个共享内存。
4.共享内存控制函数shmctl()
#include<sys/ipc.h> #include<sys/shm.h> int shmctl(int shmid,int cmd,struct shmid_ds*buf);
第二个参数为:IPC_SET,获取内存短的shmid_ds结构。并把它存储在buf参数所指定的地址中。设置内存段shmid_ds结构的ipc_pern成员的值,此命令是从buf参数中获得该值。
IPC_RMID:标记某内存段,以被删除。并不是真正的把内存段从内存中删除,相反,它只是标记上该内存段,以备将来删除,最后一个断开,删除操作才会发生。
下面看看实际代码:
//shm.h #pragma once #include <stdlib.h> #include <stdio.h> #include <sys/shm.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #define _PATH_ "." #define _PROJECT_ 0x777 #define _SHM_SIZE_ 4*1024 int get_shm(); void* at_shn(); int delete_shm(); int rm_shm(); //shm.c #include "shm.h" int get_shm() { key_t key = ftok(_PATH_,_PROJECT_); if(key < 0) { perror("ftok"); return -1; } int flag =IPC_EXCL| IPC_CREAT |0666; int shm_id = shmget(key,_SHM_SIZE_,flag); if(shm_id < 0) { printf("shmid error"); } else { printf("shmid success"); } return shm_id; } void* at_shm(int shm_id) { return shmat(shm_id,NULL,0); } int delete_shm(char *addr) { return shmdt(addr); } int rm_shmctl(int shm_id) { return shmctl(shm_id,IPC_RMID,NULL); } //shm_test.c #include "shm.h" int main() { int shm_id = get_shm(); if(shm_id < 0) { printf("HHH"); } pid_t id = fork(); if(id <0) { printf("fork error\n"); return 1; } else if(id == 0) { char *buf = (char *)at_shm(shm_id); printf("child"); int i = 0; while(i < 4095) { buf[i] = ‘A‘; ++i; buf[i] = ‘\0‘; sleep(1); } buf[4095] = ‘\0‘; delete_shm(buf); } else { int i = 0; char *buf = (char *)at_shm(shm_id); printf("father"); while(i<4095) { printf("%s\n",buf); ++i; sleep(1); } delete_shm(buf); waitpid(id,NULL,0); rm_shmctl(shm_id); } return 0; }
运行结果:
总结:
其实共享内存是在IPC进程间通信最快的一种方式,因为他是直接针对物理地址进行的操作,而且对于他的资源控制,我们需要配合信号量进行操作,来防止死锁的产生。
本文出自 “剩蛋君” 博客,请务必保留此出处http://memory73.blog.51cto.com/10530560/1765844
标签:共享资源 include system linux 操作系统
原文地址:http://memory73.blog.51cto.com/10530560/1765844