深入理解和实现Windows进程间通信(信号量)

news2024/11/25 10:31:44

常见的进程间通信方法

常见的进程间通信方法有:

  1. 管道(Pipe)
  2. 消息队列
  3. 共享内存
  4. 信号量
  5. 套接字

下面,我们将详细介绍信号量的原理以及具体实现。

什么是信号量?

信号量(Semaphore)是一个非常重要的同步机制,用于控制多个线程或进程对共享资源的访问。其基本思想是使用一个整数变量来表示可用资源的数量,通过对这个整数的操作来控制资源的分配,从而实现对竞态条件的管理。信号量的操作是原子的,即在一个操作进行的过程中,不会被其他进程或线程中断。

信号量类型

信号量主要有两种类型:

  • 二进制信号量(或互斥锁):它的值只能是0或1,用来实现互斥,即在同一时刻只允许一个线程访问共享资源。
  • 计数信号量:可以取一个整数值,表示可用资源的数量。这允许多个线程同时访问同一资源,但总数不超过最大资源数。

主要操作

信号量有两个基本操作,通常被称为P(等待)操作和V(释放)操作。

  1. P操作(等待)
  • 当线程想要访问资源时,它会执行P操作。
  • 如果信号量的值大于0,表示有资源可用,信号量的值将减一,线程继续执行。
  • 如果信号量的值为0,线程将进入阻塞状态,等待信号量值大于0。
  1. V操作(释放)
  • 当线程释放资源时,执行V操作。
  • 信号量的值加一。
  • 如果有其他线程因信号量的值为0而阻塞,这些线程中的一个将被唤醒。

信号量在线程和进程中的区别

信号量这一概念可以应用在线程通信和进程通信上,基本的操作是一样的,都是PV操作,但在具体的实现和使用场景上还是有很大的区别的:

线程间的信号量

  • 存储位置:线程间使用的信号量通常存储在同一进程的内存空间,因为线程共享同一进程的地址空间。
  • 资源共享:线程信号量主要用于同一个应用程序内部的多个线程之间的同步,因为所有线程可以直接访问到相同的内存变量和数据结构。
  • 实现方式:在多线程环境中,可以使用较轻量级的同步机制,例如C++11提供的std::mutexstd::condition_variable等。

进程间的信号量

  • 存储位置:进程间信号量必须存储在所有相关进程都可以访问到的位置,通常是操作系统的内核空间。这样做是为了保证数据的一致性和安全性。
  • 资源共享:进程间信号量用于不同进程之间的同步,这些进程可能运行相同或不同的应用程序代码,它们彼此之间不共享内存空间。
  • 实现方式:需要操作系统提供的特定API支持,例如Windows的CreateSemaphoreReleaseSemaphore

接口介绍

创建信号量

CreateSemaphore

  • 功能:创建或打开一个命名或无名的信号量对象。
  • 声明
HANDLE CreateSemaphore( 
    LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, 
    LONG lInitialCount, 
    LONG lMaximumCount, 
    LPCWSTR lpName
)
  • 参数
    • lpSemaphoreAttributes:指向一个SECURITY_ATTRIBUTES结构,该结构决定返回的句柄是否可以被子进程继承。如果为NULL,则句柄不可继承。
    • lInitialCount:指定信号的初始计数值。
    • lMaximumCount:指定信号量的最大计数值。
    • lpName:信号量的名称,如果为空,则创建一个无名信号量。

等待信号量

WaitForSingleObject

  • 功能:等待信号量对象变为可用(即信号量的计数大于0),该函数就是信号量的P操作。
  • 声明
DWORD WaitForSingleObject( 
    HANDLE hHandle, 
    DWORD dwMilliseconds 
)
  • 参数
    • hHandle:信号量对象的句柄。
    • dwMilliseconds:等待时间,可以是一个具体的毫秒数,或者使用特殊值INFINITE来表示无限等待。

释放信号量

ReleaseSemaphore

  • 功能:释放信号量对象,增加信号量的计数,相当于信号量的V操作。
  • 声明
BOOL ReleaseSemaphore( 
    HANDLE hSemaphore, 
    LONG lReleaseCount, 
    LPLONG lpPreviousCount 
)
  • 参数
    • hSemaphore:信号量对象的句柄。
    • lReleaseCount:要增加的信号量计数。
    • lpPreviousCount:可选参数,用于接收调用前的信号量计数。

关闭信号量句柄

CloseHandle

  • 功能:关闭一个打开的对象句柄,例如信号量句柄。
  • 声明:
BOOL CloseHandle( HANDLE hObject )
  • 参数:
    • hObject:需要关闭的信号量句柄对象。

实现

两个进程分别对一个存储在共享内存的整数进行累加,代码如下:

#pragma once
// 进程1
#include <windows.h>
#include <iostream>
#include <ctime>

int semaphoreImpl() {
	srand((unsigned)time(NULL));

	// 创建或打开共享内存
	HANDLE fileMapping = CreateFileMapping(
		INVALID_HANDLE_VALUE,
		NULL,
		PAGE_READWRITE,
		0,
		sizeof(int),
		L"SharedMemoryForInteger");

	if (fileMapping == NULL) {
		std::cerr << "Could not create file mapping object: " << GetLastError() << std::endl;
		return 1;
	}

	// 映射共享内存区域
	int* sharedInt = (int*)MapViewOfFile(
		fileMapping,
		FILE_MAP_ALL_ACCESS,
		0,
		0,
		sizeof(int));

	if (sharedInt == NULL) {
		std::cerr << "Could not map view of file: " << GetLastError() << std::endl;
		CloseHandle(fileMapping);
		return 1;
	}

	// 初始化共享整数
	*sharedInt = 0;

	// 创建或打开信号量
	HANDLE semaphore = CreateSemaphore(
		NULL,
		1,
		1,
		L"MySemaphore");

	if (semaphore == NULL) {
		std::cerr << "CreateSemaphore error: " << GetLastError() << std::endl;
		UnmapViewOfFile(sharedInt);
		CloseHandle(fileMapping);
		return 1;
	}

	while (*sharedInt < 10) {
		WaitForSingleObject(semaphore, INFINITE); // 等待信号量, 即P操作

		std::cout << "Incrementor1: Current value = " << *sharedInt << ". Incrementing..." << std::endl;
		(*sharedInt)++;
		Sleep(rand() % 1000 + 500); // 随机延时500到1500毫秒

		ReleaseSemaphore(semaphore, 1, NULL); // 释放信号量,即V操作
	}

	// 清理
	UnmapViewOfFile(sharedInt);
	CloseHandle(fileMapping);
	CloseHandle(semaphore);

	return 0;
}

进程2的代码和上面代码几乎一致,除了下面这行代码:
std::cout << "Incrementor2: Current value = " << *sharedInt << ". Incrementing..." << std::endl;

结果

进程1输出:
image.png
进程2输出:
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1845986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据库】数据库脚本编写规范(Word原件)

编写本文档的目的是保证在开发过程中产出高效、格式统一、易阅读、易维护的SQL代码。 1 编写目的 2 SQL书写规范 3 SQL编写原则 软件全套资料获取进主页或者本文末个人名片直接获取。

OPPO布局自动驾驶?基于语义地图的自动驾驶汽车单目定位

论文标题&#xff1a; Monocular Localization with Semantics Map for Autonomous Vehicles 论文作者&#xff1a; Jixiang Wan, Xudong Zhang, Shuzhou Dong, Yuwei Zhang, Yuchen Yang, Ruoxi Wu, Ye Jiang, Jijunnan Li, Jinquan Lin, Ming Yang 作者单位&#xff1a;O…

CoAP协议详解:物联网通信的轻量级解决方案

什么是CoAP协议 CoAP&#xff08;Constrained Application Protocol&#xff09;是一种专门为物联网&#xff08;IoT&#xff09;设计的应用层协议。它的目标是为受限设备和网络提供轻量级的通信解决方案。CoAP协议基于REST&#xff08;Representational State Transfer&#x…

云手机群控功能讲解

接触云手机之前&#xff0c;很多企业或者个人卖家都对群控有浓厚的兴趣&#xff0c;云手机群控具体是什么呢&#xff1f;云手机群控&#xff0c;顾名思义&#xff0c;是指能够同时对多台云手机进行集中控制和管理的功能。打破了传统单台手机操作的限制&#xff0c;实现了规模化…

数据资产与企业绩效的紧密关联:深入解析数据资产如何直接影响企业绩效,并探讨如何通过策略性利用数据,优化运营,进而提升企业的整体业绩与竞争力

目录 一、引言 二、数据资产与企业绩效的紧密关联 &#xff08;一&#xff09;数据资产的定义与价值 &#xff08;二&#xff09;数据资产对企业绩效的影响 三、策略性利用数据资产优化运营 &#xff08;一&#xff09;建立数据驱动的企业文化 &#xff08;二&#xff0…

ACM顶会SIGGRAPH 2024最佳论文出炉:英伟达两篇最佳论文,三支国内团队获荣誉提名,浙大周昆获时间检验奖

文章目录 1. 最佳论文最佳论文 1最佳论文 2最佳论文 3最佳论文 4最佳论文 5 2. 最佳论文荣誉提名最佳论文荣誉提名 1最佳论文荣誉提名 2最佳论文荣誉提名 3最佳论文荣誉提名 4最佳论文荣誉提名 5最佳论文荣誉提名 6最佳论文荣誉提名 7最佳论文荣誉提名 8最佳论文荣誉提名 9最佳…

【VS Code 插件】SQLite 可视化插件

VScode 插件分享篇之sqlite可视化工具 项目经常用到SQLite这个轻量型数据库&#xff0c;于是乎&#xff0c;就想着找一个可视化工具&#xff0c;但是我有时候只是想方便预览数据 表&#xff0c;又不想安装额外的程序&#xff0c;那么这款插件很适合你。 用习惯VS Code的小伙伴…

测试的基础知识大全【测试概念、分类、模型、流程、测试用例书写、用例设计、Bug、基础功能测试实战】

测试基础笔记 Day01阶段⽬标⼀、测试介绍⼆、测试常⽤分类2.1 阶段划分单元测试集成测试系统测试验收测试 2.2 代码可⻅度划分⿊盒测试&#xff1a;主要针对功能&#xff08;阶段划分->系统测试&#xff09;灰盒测试&#xff1a;针对接⼝测试&#xff08;阶段划分->集成测…

服务器机柜和网络机柜有什么区别

服务器机柜和网络机柜虽然在外观上可能相似&#xff0c;都遵循19英寸的标准&#xff0c;但它们的设计目的、功能、结构和特性存在明显的区别。下面是两者的主要区别&#xff1a; 1. 用途 服务器机柜&#xff1a;主要用于承载和组织服务器设备&#xff0c;包括主机、存储设备、交…

redis以后台的方式启动

文章目录 1、查看redis安装的目录2、Redis以后台的方式启动3、通过客户端连接redis4、连接后&#xff0c;测试与redis的连通性 1、查看redis安装的目录 [rootlocalhost ~]# cd /usr/local/redis/ [rootlocalhost redis]# ll 总用量 112 drwxr-xr-x. 2 root root 150 12月 6…

人工智能导论 题目

目录 1.人工神经网络参数个数的计算 2.卷积神经网络卷积和池化的计算 知识表示 命题 谓词 谓词公式 1.连接词 2.量词 3.量词的辖域 逻辑等价式 范式 推理规则 全程量词和存在量词之间的关系 产生式 产生式系统 3.命题/谓词逻辑证明 1.​ ​2. 3. 4. 5. 6. …

双阶段目标检测算法

双阶段目标检测算法 本文将系统的过一遍双阶段目标检测的经典算法&#xff0c;文献阅读顺序如下&#xff1a; R-CNN → \rightarrow → SPPnet → \rightarrow → Fast R-CNN → \rightarrow → Faster R-CNN → \rightarrow → Mask R-CNN R-CNN 一、研究背景 R-CNN可…

跟《经济学人》学英文:2024年6月15日这期 Durians

China is going crazy for durians Locals love the pungent fruit. The government sees an opportunity 这是阅读2024年6月15日《经济学人》杂志的China is going crazy for durians这篇文章的学习笔记。 durian&#xff1a;美 [ˈdʊriən] 榴莲 A whiff of diplomacy 一…

适合孩子学习用什么的落地灯?五款精品护眼大路灯分享

适合孩子学习用什么的落地灯&#xff1f;说到护眼落地灯&#xff0c;都会出现两种呼声&#xff1a;一种是认为是“智商税”&#xff0c;而另外一种则是妥妥的照明神器&#xff01;护眼大路灯到底是哪种定义呢&#xff1f;贵的护眼灯一定好吗&#xff1f; 这么年&#xff0c;护…

湖北建筑施工特种作业人员建筑起重信号司索工:年薪多少?

"湖北建筑施工特种作业人员建筑起重信号司索工&#xff1a;年薪多少&#xff1f;前景如何&#xff1f;" 2024湖北建筑施工特种作业人员建筑起重信号司索工 2024年湖北省建筑施工特种作业人员中的建筑起重信号司索工&#xff0c;是一项关键的工种&#xff0c;其在建筑…

5步快速了解电商渠道数字化管理||电商API数据采集|数据分析

随着电商平台的飞速发展&#xff0c;电商渠道占据品牌经销渠道的比重越来越大&#xff0c;以前只有线下经销渠道的时代已经结束&#xff0c;但是随着渠道的拓展&#xff0c;其中出现了很多问题&#xff0c;如线上渠道或者店铺数量更大、扰乱秩序成本更低、日常上线和下线变动价…

数据中心技术:大数据时代的机遇与挑战

在大数据时代&#xff0c;数据中心网络对于存储和处理大量信息至关重要。随着云计算的出现&#xff0c;数据中心已成为现代技术的支柱&#xff0c;支持社交媒体、金融服务等众多行业。然而&#xff0c;生成和处理的大量数据带来了一些挑战&#xff0c;需要创新的解决方案。在这…

【阅读论文】-- SWS:时空核密度可视化的复杂性优化解决方案

SWS: A Complexity-Optimized Solution for Spatial-Temporal Kernel Density Visualization 摘要1 引言2 预备知识2.1 STKDV 问题陈述2.2 基于范围查询的解决方案&#xff08;RQS&#xff09; 3 基于滑动窗口的解决方案&#xff08;SWS&#xff09;3.1 时间维度的滑动窗口3.2 …

HTML(14)——结构伪类选择器和伪元素选择器

结构伪类选择器 作用&#xff1a; 根据元素的结构关系查找元素 选择器说明E:first-child查找第一个E元素E:last-child查找最后一个E元素E:nth-child(N)查找第N个E元素(第一个元素N值为1) 例如&#xff1a;查找第一个li标签&#xff0c;将背景改为绿色 <style> li:fir…

YOLOv10改进 | Conv篇 |YOLOv10引入RepGhost

1. RepGhost介绍 1.1 摘要: 特征重用一直是轻量级卷积神经网络(CNN)设计中的一项关键技术。 当前的方法通常利用串联运算符通过重用其他层的特征图来廉价地保持大量通道数(从而获得大的网络容量)。 尽管串联是无参数和无 FLOP 的,但其在硬件设备上的计算成本是不可忽略的…