进程间通信笔记(9)—Posix共享内存
来源:互联网 发布:哪个软件有鱼眼效果 编辑:程序博客网 时间:2024/05/01 17:34
1.概述
对于非亲缘关系的进程间使用共享内存的方式进行通信一般有两种情况:
1.内存映射文件
2.共享内存区对象
对于内存映射文件来说,参考mmap详解,其一般步骤为:
fd = open()ptr= mmap(fd,...)
对于后者来说,其一般步骤为:
1.创建或打开一个新的共享内存区对象(
shm_open()
)
2.用mmmp将这个文件映射到调用进程的空间。
共享内存区对象
这个抽象的概念,创建于虚拟文件系统,通常挂在/dev/shm
目录中,当我们创建一个共享内存区对象后,可以直接ls /dev/shm
查看。
2.Posix共享内存编程
涉及的函数不多,但是非亲缘关系的进程间进行通信,则要考虑同步问题。
shm_open()、shm_unlink()
创建和删除IPC对象。
#include <sys/mman.h>#include <sys/stat.h> /* For mode constants */#include <fcntl.h> /* For O_* constants */int shm_open(const char *name, int oflag, mode_t mode);int shm_unlink(const char *name);Link with -lrt.
关于shm_open
的参数
第二个参数:oflag 可以是 O_CREAT|O_EXCL|O_RDWR(这个套路已经很多次了,如果IPC对象存在,则O_EXCL|O_CREAT会返回一个Segment Fault。
第三个参数:mode 可以是0644
ftruncate函数
调整共享内存区的大小。
#include <unistd.h>#include <sys/types.h>int ftruncate(int fd, off_t length);
第一个参数:文件描述符
第二个参数:修改后的大小
客户服务模型
两个进程,共享内存区,客户端不停往buffer里面放东西,服务端输出共享内存区的内容(消费)。两个进程通过Posix共享内存区进行通信,使用Posix信号量和Phtread Mutex进行同步。
头文件
//shm.h#include <sys/mman.h>#include <sys/stat.h> /* For mode constants */#include <fcntl.h> /* For O_* constants */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <semaphore.h>#include <time.h>#include <assert.h>#include <errno.h>#include <signal.h>#include <pthread.h>#define MESGSIZE 256#define NMESG 16struct shmstruct{//这里既可以用二值信号量也可以用互斥锁(需要设置互斥锁属性,否则会死锁) pthread_mutex_t mutex; // sem_t mutex; sem_t nempty; sem_t nstored; int nput; long noverflow; sem_t noverflowmutex; /* mutex for noverflow counter */ long msgoff[NMESG]; /* offset in shared memory of each message */ char msgdata[NMESG * MESGSIZE]; /* the actual messages */};
服务端
//shmserver.c#include "shm.h"int main(int argc,char **argv){ int fd, index, lastnoverflow, temp; long offset; struct shmstruct *ptr; int flag = O_RDWR|O_CREAT|O_EXCL; if (argc != 2) { printf("usage: server2 <name>\r\n"); return -1; } shm_unlink(argv[1]); fd = shm_open(argv[1],O_RDWR|O_CREAT|O_EXCL,0644);//创建共享内存区 ptr=mmap(NULL,sizeof(struct shmstruct),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);// ftruncate(fd,sizeof(struct shmstruct));//调整大小 close(fd); for (index = 0; index < NMESG; index++)//计算数据的偏移量 ptr->msgoff[index] = index * MESGSIZE;//初始化 pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);//进程间通信需要该属性,否则会死锁 pthread_mutex_init(&ptr->mutex,&attr); // sem_init(&ptr->mutex, 1, 1); sem_init(&ptr->nempty, 1, NMESG); sem_init(&ptr->nstored, 1, 0); sem_init(&ptr->noverflowmutex, 1, 1); index =0; lastnoverflow=0; for(;;) { sem_wait(&ptr->nstored);//同步 pthread_mutex_lock(&ptr->mutex); // sem_wait(&ptr->mutex); offset=ptr->msgoff[index];//获取偏移量 printf("index = %d: %s\n", index, &ptr->msgdata[offset]); if (++index >= NMESG) index = 0; /* circular buffer */ pthread_mutex_unlock(&ptr->mutex); // sem_post(&ptr->mutex); sem_post(&ptr->nempty); sem_wait(&ptr->noverflowmutex);//这里为了计算超出buffer后还发送了多少内容(有多少内容丢失) temp = ptr->noverflow; /* don't printf while mutex held */ sem_post(&ptr->noverflowmutex); if (temp != lastnoverflow) { printf("noverflow = %d\n", temp); lastnoverflow = temp; } } return 0;}
客户端
#include "shm.h"int main(int argc,char**argv){ int fd, i, nloop, nusec; pid_t pid; char mesg[MESGSIZE]; long offset; struct shmstruct *ptr; if (argc != 4) printf("usage: client2 <name> <#loops> <#usec>"); nloop = atoi(argv[2]); nusec = atoi(argv[3]); fd = shm_open(argv[1],O_RDWR,0644); ptr = mmap(NULL,sizeof(struct shmstruct),PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); close(fd); pid=getpid(); for(i=0;i<nloop;i++) { snprintf(mesg, MESGSIZE, "pid %ld: message %d", (long) pid, i); if(sem_trywait(&ptr->nempty)==-1) { if(errno==EAGAIN) { sem_wait(&ptr->noverflowmutex);//表示已经满了 ptr->noverflow++; sem_post(&ptr->noverflowmutex); continue; } else { printf("try wait error\r\n"); } } pthread_mutex_lock(&ptr->mutex); //sem_wait(&ptr->mutex); offset = ptr->msgoff[ptr->nput]; if (++(ptr->nput) >= NMESG) ptr->nput = 0; /* circular buffer */ pthread_mutex_unlock(&ptr->mutex); //sem_post(&ptr->mutex); strcpy(&ptr->msgdata[offset],mesg); sem_post(&ptr->nstored); } return 0;}
Makefile
PROGS =Client ServerCLEANFILES = core core.* *.core *.o temp.* *.out typescript* \ *.lc *.lh *.bsdi *.sparc *.uwall :${PROGS}CFLAGS+=-g LIBS+=-lpthread -lrtClient: shmclient.o ${CC} ${CFLAGS} ${LIBPATH} $^ -o $@ ${LIBS} @rm *.oServer: shmserver.o ${CC} ${CFLAGS} ${LIBPATH} $^ -o $@ ${LIBS} @rm *.oclean: rm -f ${PROGS} ${CLEANFILES}
1 0
- 进程间通信笔记(9)—Posix共享内存
- 进程间通信(8) - 共享内存(posix)
- linux进程间通信(posix信号灯+posix共享内存)实例
- UNP(卷2:进程间通信)—— 第13章:Posix共享内存区
- 15章 进程间通信之共享内存区(Posix、System V共享内存)
- APUE读书笔记---进程间通信之POSIX共享内存区
- Linux进程间通信之POSIX共享内存
- Linux进程通信之POSIX共享内存
- Linux进程通信之POSIX共享内存
- Linux进程通信之POSIX共享内存
- 进程间通信笔记(10)—SystemV共享内存
- 缓冲区设计—进程间通讯(POSIX 共享内存)
- linux进程间通信(system v信号灯+posix共享内存)实例
- 深入理解Linux进程间通信(IPC)-- Posix共享内存
- Linux进程间通信(IPC)编程实践(八)共享内存的使用-POSIX 共享内存(API)
- 进程间通信笔记(3)—POSIX消息队列
- 进程间通信笔记(6)—POSIX信号量
- 进程间通信学习笔记三(共享内存通信)
- 通信信号与系统分析(二)
- 利用wireshark破解网站密码
- JAVA JDK 简单下载说明
- LeetCode-Intersection of Two Linked Lists
- 进程间通信之管道
- 进程间通信笔记(9)—Posix共享内存
- 操作系统学习(WEEK1-WEEK5)
- 国内植保无人机尚缺四大核心技术
- Java 代理学习笔记 —— 从反射开始
- nor flash和nand flash的区别!!!!
- intent 启动系统闹钟
- Python数据可视化:饼状图
- zookeeper介绍
- Android 开发之下拉刷新+ViewPager的banner滚动