共享内存和信号量

news/2025/1/15 14:08:03/

共享内存和信号量可以配合起来一起使用。

什么是共享内存?:

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。

共享内存中几个主要的api函数:

  1. shmget——创建/打开共享内存
  2. shmat——将共享内存与当前进程相关联
  3. shmdt——将当前进程与共享内存间脱离关联
  4. shmctl——操控共享内存

因为是共享一块内存,所以其中必然涉及到同步的问题。共享内存如何实现进程间的同步呢?也就是说不同的进程不能同时访问同一块内存》

这个时候就需要使用到信号量。

什么是信号量?

信号量 (Semaphore) 是一种用于进程间同步和互斥的机制,可以防止多个进程同时访问共享资源导致的数据不一致问题。

信号量主要有两种类型:

  • 计数信号量 (Counting Semaphore):用于控制对资源的计数,可以允许多个进程同时访问有限数量的资源。
  • 二进制信号量 (Binary Semaphore):类似于互斥锁,只能取0或1,通常用于实现互斥。

计数信号量主要用于解决生产者-消费者问题。而二进制信号量主要解决互斥的问题。

信号量的两个基本操作:

  • P (Proberen) 操作:也称为 "wait" 或 "down" 操作,尝试获取一个信号量。如果信号量大于0,则将信号量减1;如果信号量为0或负数,进程将进入等待状态,直到其他进程释放资源。
  • V (Verhogen) 操作:也称为 "signal" 或 "up" 操作,释放一个信号量,即将信号量加1。如果有进程在等待资源,则唤醒其中的一个进程。

信号量的实现步骤:

1.创建和初始化信号量
#include <semaphore.h>sem_t semaphore; // 定义信号量// 初始化信号量,0 表示在进程间共享,1 是信号量的初始值
sem_init(&semaphore, 0, 1);
2.使用P操作
// 等待信号量(P 操作)
sem_wait(&semaphore);
3.操作临界区数据
4.使用V操作
// 释放信号量(V 操作)
sem_post(&semaphore);
5.销毁信号量
sem_destroy(&semaphore);

两种信号量的解决的问题:

1.进程间互斥:

#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>sem_t semaphore;void* write_to_file(void* arg) {sem_wait(&semaphore);  // P 操作,等待进入临界区// 临界区,写入文件printf("进程 %d 进入临界区,正在写入文件...\n", (int)arg);// 模拟文件写操作sleep(2);printf("进程 %d 退出临界区\n", (int)arg);sem_post(&semaphore);  // V 操作,释放信号量return NULL;
}int main() {pthread_t t1, t2;sem_init(&semaphore, 0, 1);  // 初始化信号量pthread_create(&t1, NULL, write_to_file, (void*)1);pthread_create(&t2, NULL, write_to_file, (void*)2);pthread_join(t1, NULL);pthread_join(t2, NULL);sem_destroy(&semaphore);  // 销毁信号量return 0;
}

2. 生产者-消费者问题:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>#define BUFFER_SIZE 5int buffer[BUFFER_SIZE];
int count = 0;sem_t empty_slots;  // 表示空缓冲区的信号量
sem_t full_slots;   // 表示满缓冲区的信号量
sem_t mutex;        // 保护缓冲区访问的互斥信号量void* producer(void* arg) {for (int i = 0; i < 10; ++i) {sem_wait(&empty_slots);  // 等待有空位sem_wait(&mutex);        // 进入临界区buffer[count++] = i;printf("生产者生产了数据 %d\n", i);sem_post(&mutex);        // 离开临界区sem_post(&full_slots);   // 通知有新数据}return NULL;
}void* consumer(void* arg) {for (int i = 0; i < 10; ++i) {sem_wait(&full_slots);   // 等待有新数据sem_wait(&mutex);        // 进入临界区int data = buffer[--count];printf("消费者消费了数据 %d\n", data);sem_post(&mutex);        // 离开临界区sem_post(&empty_slots);  // 通知有空位}return NULL;
}int main() {pthread_t prod, cons;sem_init(&empty_slots, 0, BUFFER_SIZE);  // 初始为空位数sem_init(&full_slots, 0, 0);             // 初始为无满缓冲区sem_init(&mutex, 0, 1);                  // 互斥信号量pthread_create(&prod, NULL, producer, NULL);pthread_create(&cons, NULL, consumer, NULL);pthread_join(prod, NULL);pthread_join(cons, NULL);sem_destroy(&empty_slots);sem_destroy(&full_slots);sem_destroy(&mutex);return 0;
}


http://www.ppmy.cn/news/1522468.html

相关文章

漫谈设计模式 [8]:装饰器模式

引导性开场 菜鸟&#xff1a;老鸟&#xff0c;我最近在项目中遇到一个问题。有些功能&#xff0c;比如日志记录和权限校验&#xff0c;我需要在多个地方使用。代码很冗余&#xff0c;不知道有没有更好的解决办法&#xff1f; 老鸟&#xff1a;菜鸟&#xff0c;这个问题很常见…

FaskAPI Web学习

FaskAPI Web学习 个人笔记使用&#xff0c;感谢阅读&#xff01; # -*- ecoding: utf-8 -*- # Author: SuperLong # Email: miu_zxl163.com # Time: 2024/9/7 11:37 from enum import Enum from typing import Optionalfrom fastapi import FastAPI import uvicorn app FastA…

log4j 多classloader重复加载配置问题解决

最近OneCoder在开发隔离任务运行的沙箱&#xff0c;用于隔离用户不同任务间以及任务和 框架本身运行代码的隔离和解决潜在的jar包冲突问题。 运行发现&#xff0c;隔离的任务正常运行&#xff0c;但是却没有任何日志记录。从控制台可看到如下错误信息&#xff1a; 全文详见个人…

从零开始学习JVM(七)- StringTable字符串常量池

1 概述 String应该是Java使用最多的类吧&#xff0c;很少有Java程序没有使用到String的。在Java中创建对象是一件挺耗费性能的事&#xff0c;而且我们又经常使用相同的String对象&#xff0c;那么创建这些相同的对象不是白白浪费性能吗。所以就有了StringTable这一特殊的存在&…

Spark2.x 入门:逻辑回归分类器

方法简介 逻辑斯蒂回归&#xff08;logistic regression&#xff09;是统计学习中的经典分类方法&#xff0c;属于对数线性模型。logistic回归的因变量可以是二分类的&#xff0c;也可以是多分类的。 示例代码 我们以iris数据集&#xff08;iris&#xff09;为例进行分析。i…

Spring AOP的注解式开发实现

目录 AOP常用注解注解开发实现步骤1. 导入Maven项目依赖2. 准备一个实体类&#xff08;先定义接口再实现&#xff09;3. 定义切面类4. 准备配置文件5. 编写测试类 注意事项 AOP的配置开发方式见&#xff1a;Spring入门之AOP&#xff08;包含实例代码&#xff09;。其他纯注解开…

记忆化搜索【下】

375. 猜数字大小II 题目分析 题目链接&#xff1a;375. 猜数字大小 II - 力扣&#xff08;LeetCode&#xff09; 题目比较长&#xff0c;大致意思就是给一个数&#xff0c;比如说10&#xff0c;定的数字是7&#xff0c;让我们在[1, 10]这个区间猜。 如果猜大或猜小都会说明…

Spring Boot之DevTools介绍

Spring Boot DevTools 是 Spring Boot 提供的一组易于使用的工具&#xff0c;旨在加速开发和测试过程。它通过提供一系列实用的功能&#xff0c;如自动重启、实时属性更新、依赖项的热替换等&#xff0c;极大地提高了开发者的开发效率。本文将详细介绍 Spring Boot DevTools 的…