进程间通信--共享内存

来源:互联网 发布:淘宝手机怎么退货退款 编辑:程序博客网 时间:2024/06/05 22:38

进程间通信一般分为

¥1 管道:半双工的方式进行通信,而且范围现定于有亲缘关系的进程间使用,比如父子关系。

¥2 有名管道:和管道一样的通信方式,当时可以允许没有亲缘关系的进程进行通信。

¥3 信号量:相当于一种锁机制,防止不同的进程同时对一个对象进行访问。

¥4 消息队列:是消息的链表。

¥5 信号:通知进程某个事件已经发生。

¥6 共享内存:有一个进程创建,多个进程可以访问,本质是映射一段内被其他进程访问的内存,是最常见的IPC通信方式。

¥7 套接字:套接字也是一种进程间通信的方式。

今天要谈的是共享内存的方式

两个互不相干的正在运行的进程访问同一块逻辑内存,并进行数据传输。

进程可以讲共享内存连接到自己的地址空间中,所有的进程都可以这么做,就好像这块内存就是由malloc分配的原始内存一样,这样就造成了如果某个人进程对其进行写操作,结果将立刻在另一个进程上显示出来。

(共享内存并没有提供同步机制,没法自动产生锁的效果,但是可以通过修好两的方式来达到锁的效果)

共享内存的使用教程

1.相关函数(相关函数参数介绍自己查阅,动动手)

int shmget(key_t key ,size_t size,int shmflg);(创建共享内存)

void *shamat (int shm_id ,const void* shm_addr,int shmflg);(链接共享内存地址到自己的地址空间)

int shmdt(const void *shmaddr)(将内存从被使用的进程中剥离)

int shmctl(int shm_id,iint command,struct shmid_ds *buf);(根据不同的参数来进行)

2.使用中应注意要想让程序安全的执行,就要有一种进程同步机制,保证在进入临界区的操作都是原子操作,例如信号量的操作就是原子操作。

以下是附带的代码,供参考.

 

两个进程相同的数据结构:

就是读写的功能和写的大小
#ifndef _SHMDATA_H_HEADER#define _SHMDATA_H_HEADER#define TEXT_SZ 2048struct shared_use_st{int written;//作为一个标志,非0:表示可读,0表示可写char text[TEXT_SZ];//记录写入和读取的文本};
读进程:
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <sys/shm.h>#include "shmdata.h"int main(){int alive = 1;//程序是否继续运行的标志void *shm = NULL;//分配的共享内存的原始首地址struct shared_use_st *shared;//指向shmint shmid;//共享内存标识符//创建共享内存shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);if(shmid == -1){    fprintf(stderr, "shmget failed\n");    exit(EXIT_FAILURE);}//将共享内存连接到当前进程的地址空间shm = shmat(shmid, 0, 0);//shmid进程的0地址if(shm == (void*)-1){    fprintf(stderr, "shmat failed\n");    exit(EXIT_FAILURE);}printf("\nMemory attached at %X\n", (int)shm);//设置共享内存shared = (struct shared_use_st*)shm;shared->written = 0;//初始化while(alive)//读取共享内存中的数据{    //没有进程向共享内存写数据此时还有数据可读取if(shared->written != 0){printf("You wrote: %s", shared->text);sleep(rand() % 3);//读取完数据,设置written使共享内存段可写shared->written = 0;//输入了over,退出循环(程序)if(strncmp(shared->text, "over", 3) == 0)alive = 0;}else//有其他进程在写数据,不能读取数据sleep(1);}//把共享内存从当前进程中分离if(shmdt(shm) == -1){fprintf(stderr, "shmdt failed\n");exit(EXIT_FAILURE);}//删除共享内存if(shmctl(shmid, IPC_RMID, 0) == -1){fprintf(stderr, "shmctl(IPC_RMID) failed\n");exit(EXIT_FAILURE);}exit(EXIT_SUCCESS);}

写进程:

#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/shm.h>#include "shmdata.h"int main(){int running = 1;void *shm = NULL;struct shared_use_st *shared = NULL;char buffer[BUFSIZ + 1];//用于保存输入的文本int shmid;//创建共享内存shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);if(shmid == -1){fprintf(stderr, "shmget failed\n");exit(EXIT_FAILURE);}//将共享内存连接到当前进程的地址空间shm = shmat(shmid, (void*)0, 0);if(shm == (void*)-1){fprintf(stderr, "shmat failed\n");exit(EXIT_FAILURE);}printf("Memory attached at %X\n", (int)shm);//设置共享内存shared = (struct shared_use_st*)shm;while(alive)//向共享内存中写数据{//数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本while(shared->written == 1){sleep(1);printf("Waiting...\n");}//向共享内存中写入数据printf("Enter some text: ");fgets(buffer, BUFSIZ, stdin);strncpy(shared->text, buffer, TEXT_SZ);//写完数据,设置written使共享内存段可读shared->written = 1;//输入了over,退出循环(程序)if(strncmp(buffer, "over", 3) == 0)alive = 0;}//把共享内存从当前进程中分离if(shmdt(shm) == -1){fprintf(stderr, "shmdt failed\n");exit(EXIT_FAILURE);}sleep(2);exit(EXIT_SUCCESS);}


操作方式为:

gcc -o read read.c

gcc -o write write.c

./write

./read

 

观察结果,如果愿意把结果附在评论上,可以相互交流。


附:ipcs -m 小工具可以用来查看共享内存的情况。