乐趣区

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

引言

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

共享内存

线程同步

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

进程同步

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

在学习本篇的共享内存之前,回顾一下之前说到的操作系统是怎么进行过程治理的。
每一个过程都有本人的过程空间,并且他们的过程空间是通过页表通过段页式存储管理和理论的内存建设起映射的。过程之间他们的过程空间是互不烦扰的,互相独立的

因而:

  • 在某种程度上,多过程是独特应用物理内存的(也就是说多过程是共享物理内存的)
  • 因为操作系统的过程治理,过程间的内存空间是独立的 (也就是任意两个过程他们逻辑上的内存空间是齐全没有分割的),这样就 保障了每一个过程它们独立运行的安全性(这也是过程治理的一个作用)

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

然而,共享内存 就能够突破这样的限度,通过共享内存,过程就能够通过页表来映射到同样的一片内存中去,这片内存既能够被过程 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…

在疾速变动的技术中寻找不变,才是一个技术人的外围竞争力。知行合一,实践联合实际

退出移动版