计算机操作系统基础 (十六)--- 进程同步之共享内存

用户头像
书旅
关注
发布于: 2020 年 07 月 09 日
计算机操作系统基础(十六)---进程同步之共享内存

引言

本篇为第十六篇,进程同步之共享内存。前边介绍到的都是解决线程同步的方法,本文为处理进程同步的方法---共享内存



共享内存

线程同步



每个进程可能会有一个或多个线程,线程是共享进程资源的,线程之间也需要通信,又或者说线程之间需要同步一些进程资源的状态,此时就需要线程之间的信息同步



进程同步



一个操作系统中可能有一个或多个进程,进程是共享计算机资源的(包括内存、磁盘等都是共享的),因此在进程之间也同样需要信息同步。在之前的文章中提到的生产者-消费者问题,以及哲学家进餐问题都是进程同步的原因



在学习本篇的共享内存之前,回顾一下之前说到的操作系统是怎样进行进程管理的。

每一个进程都有自己的进程空间,并且他们的进程空间是通过页表通过段页式存储管理和实际的内存建立起映射的。进程之间他们的进程空间是互不干扰的,相互独立的





因此:

  • 在某种程度上,多进程是共同使用物理内存的(也就是说多进程是共享物理内存的)

  • 由于操作系统的进程管理,进程间的内存空间是独立的(也就是任意两个进程他们逻辑上的内存空间是完全没有联系的),这样就保证了每一个进程它们独立运行的安全性(这也是进程管理的一个作用)



进程默认是不能访问进程空间之外的内存空间的(也就是一个进程不能访问另外一个进程的内存空间)



但是,共享内存就可以打破这样的限制,通过共享内存,进程就可以通过页表来映射到同样的一片内存中去,这片内存既可以被进程1所使用,也可以被进程2所使用。也就是这片共享内存可以被进程1所读或者是写,同样也可以被进程2所读或者所写。因此,通过共享内存,进程1和进程2建立了联系。那么共享内存也是操作系统所提供的重要的进程同步的方法





共享内存介绍

  • 共享存储允许不相关的进程访问同一片物理内存(它实现的原理就是把一片相同的物理内存映射到不同进程的页表中去,使得不同的进程通过页表可以访问相同的一块物理内存)

  • 共享内存是两个进程之间共享和传递数据最快的方式

  • 共享内存未提供同步机制,需要借助其它机制管理访问,以避免并发访问所带来的问题



注:同步机制:在并发程序设计中,各进程对公共变量的访问必须加以制约,这种制约称为同步



使用共享内存步骤

  • 申请共享内存

  • 将共享内存连接到进程空间(这样进程就可以通过页表访问共享内存)

  • 使用共享内存

  • 脱离进程空间&删除





代码示例



例子中会有一个客户端和一个服务端,他们之间通过共享内存进行通信



common.h放的是一些公共信息

#ifndef __COMMON_H__
#define __COMMON_H__

//共享内存中的字符串最大长度
#define TEXT_LEN 2048

//共享内存的数据结构
//因为在默认情况下,内存里边存储的方式是没有数据结构的,当程序需要使用共享内存的话,就需要定义数据结构,把结构数据存储到共享内存
struct ShmEntry{
//是否可以读取共享内存,用于进程间同步
bool can_read
//共享内存信息
char msg[2048]
};
#endif



server.cpp

#include "common.h"

#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <iostream>

int main()
{
//定义共享内存结构图
struct ShmEntry *entry;
//1.申请共享内存
int shmid = shmget((key_t)1111, sizeof(struct ShmEntry), 0666|IPC_CREAT);
if(shmid == -1) {
std::cout << "Create share memory error!" << std::endl;
return -1;
}
//2.连接到当前进程空间/使用共享内存
entry = (ShmEntry*)shmat(shmid, 0, 0);
entry->can_read = 0;
while(true){
if(entry->can_read == 1) {
std::cout<< "Received message" << entry->msg << std::endl;
entry->can_read = 0;
} else {
std::cout << "Entry can not read. Sleep 1s" << std::endl;
sleep(1);
}
}
//3.脱离进程空间
shmdt(entry);
//4.删除共享内存
shmctl(shmid, IPC_RMID, 0);
return 0;
}



client.cpp

#include "common.h"

#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <iostream>

int main()
{
//定义共享内存结构图
struct ShmEntry *entry;
//1.申请共享内存
int shmid = shmget((key_t)1111, sizeof(struct ShmEntry), 0666|IPC_CREAT);
if(shmid == -1) {
std::cout << "Create share memory error!" << std::endl;
return -1;
}
//2.连接到当前进程空间/使用共享内存
entry = (ShmEntry*)shmat(shmid, 0, 0);
entry->can_read = 0;
char buffer[TEXT_LEN];
while(true){
if (entry->can_read = 0) {
std::cout << "Input message>>>";
fgets(buffer, TEXT_LEN, stdin);
strncpy(entry->msg, buffer, TEXT_LEN);
std::cout << "Send message:" << entry->msg << std::endl;
entry->can_read = 1;
}
}
//3.脱离进程空间
shmdt(entry);
//4.删除共享内存
shmctl(shmid, IPC_RMID, 0);
return 0;
}



运行server





运行client并发送消息





server收到信息





上边就通过共享内存的方式,实现了两个进程之间的通信。PHP中共享内存相关API地址:https://www.php.net/manual/zh/ref.shmop.php



在快速变化的技术中寻找不变,才是一个技术人的核心竞争力。知行合一,理论结合实践





发布于: 2020 年 07 月 09 日 阅读数: 51
用户头像

书旅

关注

公众号:IT猿圈 2019.04.11 加入

还未添加个人简介

评论

发布
暂无评论
计算机操作系统基础(十六)---进程同步之共享内存