操作系统学习提升篇——进程同步

2023-10-29

进程的线程共享进程资源,进程共享计算机资源,因此进程和线程一样都需要信息同步。

共享内存

在某种程度上,多进程是共同使用物理内存的;
由于操作系统的进程管理,进程间的内存空间是独立的;
进程默认是不能访问进程空间之外的内存空间的(一个进程不能访问另一个进程的内存空间)。共享内存可以打破限制。

共享存储允许不相关的进程访问同一片物理内存。实现原理:把这一片物理内存分别映射到不同进程的页表里面去,使得不同进程都能通过页表来访问同一个物理内存。

共享内存是两个进程之间共享和传递数据最快的方式。
共享内存未提供同步机制,需要借助其他机制管理访问。
共享内存是高性能后台开发中最常用的进程同步方式。

实现共享内存的四个步骤:
在这里插入图片描述

共享内存的例子:实现客户端和服务端的通信
在这里插入图片描述

//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;
}

操作步骤:
打开虚拟机,用make命令编译两个cpp文件,然后分别在两个虚拟机中运行。在client文件中输入发送的消息,那么在server中可以接收到。

Unix域套接字

域套接字是一种高级的进程间通信的方法。
Unix域套接字可以用于同一机器进程间通信。
套接字(socket)原是网络通信中使用的术语。
Unix系统提供的域套接字提供了网络套接字类似的功能。

Unix域套接字不需要借助额外的同步机制管理访问。
提供了单机简单可靠的进程通信同步服务。
只能在单机使用,不能跨机器使用。

实现Unix域套接字的步骤:
服务端:
在这里插入图片描述
客户端:
在这里插入图片描述
Unix域套接字的例子:

//server.cpp文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>

// 域套接字,定义域套接字路径,会自动在该路径下创建一个文件用于信息传递
#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048

int main()
{
    int socket_fd, accept_fd;
	int ret = 0;
	socklen_t addr_len;
	char msg[MSG_SIZE];
	struct sockaddr_un server_addr;

    // 1. 创建域套接字
	socket_fd = socket(PF_UNIX,SOCK_STREAM,0);
	if(-1 == socket_fd){
		std::cout << "Socket create failed!" << std::endl;
		return -1;
	}
    // 移除已有域套接字路径
	remove(SOCKET_PATH);
    // 内存区域置0
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sun_family = PF_UNIX;
	strcpy(server_addr.sun_path, SOCKET_PATH);

    // 2. 绑定域套接字
    std::cout << "Binding socket..." << std::endl;
	ret = bind(socket_fd,(sockaddr *)&server_addr,sizeof(server_addr));

	if(0 > ret){
		std::cout << "Bind socket failed." << std::endl;
		return -1;
	}
	
    // 3. 监听套接字
    std::cout << "Listening socket..." << std::endl;
	ret = listen(socket_fd, 10);
	if(-1 == ret){
		std::cout << "Listen failed" << std::endl;
		return -1;
	}
    std::cout << "Waiting for new requests." << std::endl;
    accept_fd = accept(socket_fd, NULL, NULL);
    
    bzero(msg,MSG_SIZE);

    while(true){
        // 4. 接收&处理信息
        recv(accept_fd, msg, MSG_SIZE, 0);
        std::cout << "Received message from remote: " << msg <<std::endl;
    }

    close(accept_fd);
	close(socket_fd);
	return 0;
}
//client.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>

#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048

int main()
{
    int socket_fd;
	int ret = 0;
	char msg[MSG_SIZE];
	struct sockaddr_un server_addr;

    // 1. 创建域套接字
	socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
	if(-1 == socket_fd){
		std::cout << "Socket create failed!" << std::endl;
		return -1;
	}
    
    // 内存区域置0
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sun_family = PF_UNIX;
	strcpy(server_addr.sun_path, SOCKET_PATH);

    // 2. 连接域套接字
	ret = connect(socket_fd, (sockaddr *)&server_addr, sizeof(server_addr));

	if(-1 == ret){
		std::cout << "Connect socket failed" << std::endl;
		return -1;
	}

	while(true){
        std::cout << "Input message>>> ";
        fgets(msg, MSG_SIZE, stdin);
		// 3. 发送信息
		ret = send(socket_fd, msg, MSG_SIZE, 0);
	}

	close(socket_fd);
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

操作系统学习提升篇——进程同步 的相关文章

  • MySQL基础(非常全)

    MySQL基础 一 MySQL概述 1 什么是数据库 答 数据的仓库 如 在ATM的示例中我们创建了一个 db 目录 称其为数据库 2 什么是 MySQL Oracle SQLite Access MS SQL Server等 答 他们均是
  • 文件管理系统(操作系统)——9张思维导图

    文件管理系统 1 文件管理 1 1 一个文件的逻辑结构 比如一个文本txt文件 又或者Excel文件 在我们用户看来 它是长什么样的 这个就是逻辑结构 几个概念 逻辑结构 就是指在用户看来 单个文件内部的数据应该是如何组织起来的 物理结构
  • pycharm内存不足时如何修改设置?

    Help gt Find Action gt type VM Options gt Click Edit Custom VM Options Pycharm 2016 2 will open the appropriate vmoption
  • 设备管理过程

    复杂度2 5 机密度2 5 最后更新2021 04 19 AIX中对设备会有如下五个操作 define aix下能看到设备的定义 但驱动程序并没有加载或初始化 该设备不可用 lsdev看到设备时defined 很多逻辑设备 vg lv等 只
  • gpuz怎么看显存颗粒

    gpuz可以帮助一些用户查看电脑的一切显卡参数 对于想要了解显卡的网友来说使用起来是非常方便的 不过有些网友是刚开始使用 还不知道gpuz怎么看显存颗粒 下面小编就教下大家gpuz查看显存颗粒的方法 首先 显存颗粒是显存的物理存储组成单元
  • Linux 磁盘与文件系统管理(鸟哥私房菜)

    本文来自 http vbird dic ksu edu tw linux basic 0230filesystem php 第八章 Linux 磁盘与文件系统管理 系统管理员很重要的任务之一就是管理好自己的磁盘文件系统 每个分割槽不可太大也
  • win10 Enable developer Mode

    经过漫长的安装过程 win10终于装上了vs2015 rc 写个小程序试试 结果提示 根据提示打开 设置 更新 for developer 据说应该有这么个界面 但是这个界面根本出不来 直接闪退的说 翻 MSDN 终于翻出了解决方法 htt
  • CF、SF、OF、ZF标志位

    没学汇编 这种题我真是做一道错一道 OF overflow flag 溢出标志位 溢出标志位 OF 1 表示带符号整数运算时结果发生溢出 对于无符号整数运算 OF没有意义 对于有符号数的溢出判断方式有 1 采用一位符号位 思想为 或 则为溢
  • Linux系统编程:多线程交替打印ABC

    引言 分享关于线程的一道测试题 因为网上基本都是Java的解决方法 决定自己写一篇来记录一下线程的学习 问题描述 编写一个至少具有三个线程的程序 称之为线程 A B 和 C 其中线程 A 输出字符 A 线程 B 输出字符 B 线程 C 输出
  • 红帽7.9部署telnet服务

    升级ssh 为预防万一提前配置telnet服务 安装软件包 yum install telnet server yum install xinetd xinetd加入开机自启 systemctl enable xinetd service
  • LWIP在STM32上的移植

    本文做记录摘抄 加上自己的体会 文章标题 STM32使用LWIP实现DHCP客户端 http www cnblogs com dengxiaojun p 4379545 html 该文章介绍了几点 LWIP源码的内容 关键点 1 inclu
  • Socket编程中的强制关闭与优雅关闭及相关socket选项

    以下描述主要是针对windows平台下的TCP socket而言 首先需要区分一下关闭socket和关闭TCP连接的区别 关闭TCP连接是指TCP协议层的东西 就是两个TCP端之间交换了一些协议包 FIN RST等 具体的交换过程可以看TC
  • Linux系统如何看目录属于哪个磁盘分区

    Linux是先有目录 再有磁盘分区 df h 目录 例如 没有挂载磁盘的目录 显示在系统盘 root iZ2ze57v3n0zma46zqiq8nZ sh 1 5 5 df h alidata Filesystem Size Used Av
  • 操作系统 段页式存储管理

    一 引入 分页系统是以页面作为内存分配的基本单位 能有效地提高内存利用率 但信息共享等不方便 分段系统是以段作为内存分配的基本单位 它能够更好地满足用户多方面的需要 信息共享 动态链接等 但采用分区方式管理物理内存 仍然存在碎片问题 段页式
  • Linux alien命令

    一 简介 alien是一个用于在各种不同的Linux包格式相互转换的工具 其最常见的用法是将 rpm转换成 deb 或者反过来 二 安装 http toutiao com a6188997768449360129 三 实例 http www
  • 自己动手写操作系统(一)

    本系列文章将一步步实现一个简单的操作系统 实验环境是在Linux系统下通过Bochs虚拟机运行我们自己写的操作系统 一 实验环境搭建 1 Ubuntu的安装 Windows用户可以选择在虚拟机中安装Ubuntu 具体安装教程可自行搜索 2
  • 由于回车符引起的shell错误

    今天弟弟写shell时出现一个错误 源代码如下 zip r 1 2 执行时出现错误 我也写了相同的语句 发现是可以执行的 把两个文件对比一看 差别在于 出错shell 正确shell 在linux下的回车是 n 在win下面的回车是 r n
  • 操作系统常见面试题

    1 什么是进程 Process 和线程 Thread 有何区别 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动 进程是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体 是CPU调度和分派的基本单位 它是比进程更小的能
  • 磁盘调度算法笔记和练习题

    磁盘调度算法 先来先服务FCFS 最短寻道时间优先SSTF 扫描调度SCAN 练习题 先来先服务FCFS 最短寻道时间优先SSTF 扫描调度SCAN 它是一次只响应一个方向上的请求 这个方向上的请求都响应完了 再掉头处理另一个方向上的 有点
  • Common块和Bss段的区别

    昨天看 程序员的自我修养 链接 装载与库 发现不是很理解为什么要用common块 然后仔细看了一番 有了自己的理解 common块 用来存放弱符号 而全局未初始化变量是弱符号 但是难道不是应该存放在 bss段吗 为什么要有common块呢

随机推荐

  • 《MySQL实战45讲》读后感 03

    收获到的知识点 事务支持是在引擎层面实现的 但是并不是所有的引擎都支持事务 比如MySQL原生的MyISAM引擎就不支持事务 这也是MyISAM被 InnoDB取代的原因之一 多个事务同时执行的时候 可能出现这3种情况 脏读 dirty r
  • 2018年蓝桥杯省赛-日志统计

    题目 题目链接 题解 贪心 尺取 首先按照时间从小到大 对输入的每一组 t s ts ts和 i d id id进行排序 遍历每一对 取当
  • Vivado 使用过程中问题总结

    关注 星标公众号 及时获取更多技术分享 作者 冰茶奥利奥 微信公众号 嵌入式电子创客街 目录 情况1 在vivado进行一个行为级别仿真时 运行到simulate 步骤时 弹出了如下提示 情况2 综合时 ambiguous clock in
  • Bean name用法

    Spring的bean中有name属性 可以用来区分两个相同 部分属性不一样 的bean 最近我在做influxdb多数据源的时候用到 所以这里已influxdb为示例 仅供参考 看代码 Bean name influx1 public I
  • CSS媒体查询(@media)全面解析

    随着移动设备的快速普及 用户不再只是通过传统的电脑系来浏览 Web 内容 越来越多的用户开始使用各种尺寸的智能手机 平板电脑或者其它设备来浏览 Web 内容 为了确保使用不同设备的用户都能拥有不错的体验就需要用到媒体查询 媒体查询是 CSS
  • 【恒指早盘分析】趋势交易——看懂很简单,做到却很难!

    老子说 盖闻善执生者 陵行不辟兕虎 意思是说 善于保全生命的人 在山陵里走路不轻易干砍劈犀牛或老虎的事情 一个交易者不要轻易涉险 不要因欲望驱使而重仓或急于进场 也不要因为恐惧和疑虑而过早离场 老老实实的控制仓位 老老实实的看准行情之后再行
  • 【Flutter 1-15】Flutter手把手教程Dart语言——包管理工具Pub详解、pub get,pub cache使用

    作者 弗拉德 来源 弗拉德 公众号 fulade me 什么是Pub工具 Dart 生态系统使用包来管理共享软件 比如 库和工具 我们使用Pub包管理工具 来获取Dart包 在Pub上 可以找到公开可用的包 或者从本地文件系统或其他的位置
  • Linux性能监控 -- top命令

    文章目录 示例 参数说明及操作 信息详解 系统运行信息 任务信息 cpu运行信息 内存 swap使用情况 进程消耗资源详情 示例 参数说明及操作 按cpu使用率排序 输入top后 再输入P 按内存使用率排序 输入top后 再输入M 信息详解
  • 关于 XCode ld: library not found for -lcurl clang的解决办法

    有时候项目在自己电脑上运行正常 通过svn提交项目 再checkout下来的时候 再次运行却报错 如 Xcode出现如下错误 一般是因为缺少相关 a等库文件 如 缺少libcurl a 打开 发现少了libcurl a 只需再将相关库文件添
  • Linux学习-17-rpm查询软件包命令(-q、-qa、-i、-p、-l、-f、-R)

    7 4 Linux rpm查询软件包命令 q qa i p l f R rpm 命令还可用来对 RPM 软件包做查询操作 具体包括 查询软件包是否已安装 查询系统中所有已安装的软件包 查看软件包的详细信息 查询软件包的文件列表 查询某系统文
  • JAVA编程基础:第九章 swing类

    如何创建更好看的界面 1 导入swing包 里面有更好看的组件 2 创建各个组件的实例 然后添加到面板 import java awt import javax swing swing包中的组件是从awt包扩展而来的 这些组件更好看 知识点
  • Linux下使用apt安装mysql

    Ubuntu上安装MySQL非常简单只需要几条命令就可以完成 1 sudo apt get install mysql server 2 apt get isntall mysql client 3 sudo apt get install
  • 如何快速制作数据词典

    其实制作数据词典是一件非常麻烦费力的事情 如果有一条SQL能够帮你全都查询出来 那无疑会省力许多 今天呢我就给大家带来一条这样的SQL 源自大佬小梦想的亲笔之作 USE information schema SELECT 字段 字段说明 P
  • Wireshark 使用技巧

    一 数据包过滤 过滤需要的IP地址 ip addr 在数据包过滤的基础上过滤协议ip addr xxx xxx xxx xxx and tcp 过滤端口ip addr xxx xxx xxx xxx and http and tcp por
  • PHPExcel 学习笔记

    首先到phpexcel官网上http phpexcel codeplex com下载最新的phpexcel类 下周解压缩一个classes文件夹 里面包含了PHPExcel php和PHPExcel的文件夹 这个类文件和文件夹是我们需要的
  • 自动控制原理《传递函数》

    目录 文章目录 目录 摘要 1 传递函数的定义 2 传递函数的标准形式 3 传递函数的性质 4 传递函数的局限性 5 总结 摘要 本节主要学习自动控制原理中的传递函数相关知识 大部分内容参考西北工业大学课件 1 传递函数的定义 需要注意的是
  • JEESITE快速开发平台(五)用户-角色-部门-区域-菜单-权限表关系

    一 表关系 一共有8张表分别用来实现用户 角色 部门 区域 菜单 权限管理 详细如下 二 SQL语句 java view plain copy 一共八张表 select from sys user 用户表 select from sys m
  • Vue 打包优化之 生产环境删除 console 日志

    使用 vue cli 3 0 vue cli 脚手架构建的项目 一般在本地开发过程中 会有不少 console 调试信息 如果不处理这些日志信息 默认情况下 即使是构建生产环境的包 这些 console 打印也不会被移除 这显然是不够严谨的
  • 蓝桥杯-时间模拟

    蓝桥杯 时间模拟 引言 时间模拟 是蓝桥杯最常见的题型 我愿意把他称作小白和入门画的界限 接下来就让我来带大家入门把 一 模板 include
  • 操作系统学习提升篇——进程同步

    进程的线程共享进程资源 进程共享计算机资源 因此进程和线程一样都需要信息同步 共享内存 在某种程度上 多进程是共同使用物理内存的 由于操作系统的进程管理 进程间的内存空间是独立的 进程默认是不能访问进程空间之外的内存空间的 一个进程不能访问