首页 > 其他分享 >操作系统(6) (Named /Unnamed Semaphore信号量详解)

操作系统(6) (Named /Unnamed Semaphore信号量详解)

时间:2024-10-19 16:47:58浏览次数:9  
标签:Named sema 无名 信号量 线程 Semaphore 进程 sem

目录

1: 信号量的基本概念

2: 命名信号量的示例代码

3. 无名信号量(Unnamed Semaphore)

背景(Background)

示例代码讲解

初始化无名信号量

线程函数

创建线程并等待完成

销毁信号量

总结

4. 对比


1: 信号量的基本概念

  1. 背景介绍

    • 信号量是一种并发编程中的同步原语,它用于协调多个进程对共享资源的访问。
    • 信号量可以控制资源的访问,例如,在多个进程尝试写入同一文件时,使用信号量可以确保只有一个进程能够在某一时刻执行写操作。
  2. 命名信号量(Named Semaphore)的工作方式

    • 命名信号量是共享在多个进程之间的信号量,可以通过名称来访问。
    • 要使用信号量,首先需要包含 <semaphore.h> 头文件。
  3. 创建命名信号量

    • 使用 sem_open 函数创建或打开信号量。例如,sem_open("/semaphore_name", O_CREAT, 0666, initial_value)
    • 参数解释:
      • "/semaphore_name":信号量的名称,需要唯一。
      • O_CREAT:表示如果信号量不存在则创建它。
      • 0666:权限标识(可读写)。
      • initial_value:信号量的初始值,表示可用的资源数。
  4. 获取和释放信号量

    • sem_wait:获取信号量。如果信号量值为0,则进程会阻塞,直到其他进程释放信号量。
    • sem_post:释放信号量,使信号量值加1,允许其他阻塞的进程继续执行。
  5. 关闭和删除信号量

    • sem_close:关闭信号量,表示不再需要使用它。
    • sem_unlink:删除信号量,使其不再在系统中存在。

2: 命名信号量的示例代码

sem_t *sema;
sema = sem_open(name, O_CREAT, 0666, VALUE);
sem_wait(sema);  // 获取信号量
printf("减少信号量\n");
sem_post(sema);  // 释放信号量
printf("增加信号量\n");
sem_close(sema); // 关闭信号量
sem_unlink(name); // 删除信号量
    •    代码解释:
      • sem_open:创建一个新的命名信号量。
      • sem_wait:等待并获取信号量(进入临界区)。
      • sem_post:释放信号量(离开临界区)。
      • sem_closesem_unlink:分别用于关闭和删除信号量。
    • 编译:
      • gcc semaphore_example.c -pthread -o semaphore_example
        

                                


3. 无名信号量(Unnamed Semaphore)

使用方法,重点是如何在线程中使用无名信号量来控制对共享资源的访问。

背景(Background)

无名信号量与具名信号量的区别在于,具名信号量通过sem_open创建,有一个名字可以在不同的进程间共享。无名信号量则存在于内存中,仅在同一进程内的多个线程或已映射相同共享内存的进程之间共享。

  • 无名信号量的创建:我们需要通过sem_init()函数来初始化无名信号量,而不是使用sem_open

  • sem_init() 函数定义如下:

int sem_init(sem_t *sem, int pshared, unsigned int value);
    • sem:指向信号量的指针。
    • pshared:如果为0,信号量只在线程间共享;如果为非零,信号量可以在进程间共享。
    • value:信号量的初始值。
  • 使用信号量:使用sem_wait()来等待信号量,sem_post()来释放信号量。

  • 销毁信号量:通过sem_destroy()函数销毁无名信号量。销毁后,不能再使用此信号量,除非重新初始化。

示例代码讲解

初始化无名信号量
sem_init(&unnamed_sema, 0, VALUE);

这里初始化了一个信号量unnamed_sema,初始值为VALUEpshared值为0,表示此信号量仅在线程之间共享。

线程函数
void* thread_function(void *arg) {
    sem_wait(&unnamed_sema); // 等待信号量
    printf("Decrease semaphore by 1\n");
    
    counter += 1; // 修改共享变量
    printf("Job %d started\n", counter);
    sleep(2); // 模拟任务执行
    printf("Job %d finished\n", counter);

    sem_post(&unnamed_sema); // 增加信号量
    return NULL;
}
  1. sem_wait:等待并减小信号量值。线程进入临界区之前,信号量的值会减1,如果信号量值为0,线程会阻塞,直到其他线程释放信号量。
  2. 临界区操作counter是共享资源,多个线程要互斥地访问它。这里通过信号量确保只有一个线程可以进入临界区。
  3. sem_post:离开临界区后,释放信号量,将信号量的值加1,允许其他线程进入临界区。
创建线程并等待完成
pthread_create(&tid[0], NULL, &thread_function, NULL);
pthread_create(&tid[1], NULL, &thread_function, NULL);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);

创建两个线程并执行thread_function函数。pthread_join用于等待线程完成。

销毁信号量
sem_destroy(&unnamed_sema);

总结

  1. sem_init:创建和初始化无名信号量。
  2. sem_wait:等待并占用信号量,进入临界区。
  3. sem_post:释放信号量,离开临界区。
  4. sem_destroy:销毁信号量,释放资源。

4. 对比

标识方式通过名字(字符串)通过指针
创建方式sem_open()sem_init()
共享范围跨进程线程之间或共享内存进程间
销毁方式sem_close() + sem_unlink()sem_destroy()
使用场景进程间同步线程间同步,或同内存进程间同步
性能开销稍大,适用于跨进程高效,适用于线程同步

标签:Named,sema,无名,信号量,线程,Semaphore,进程,sem
From: https://blog.csdn.net/2301_80176774/article/details/143080389

相关文章

  • ModuleNotFoundError: No module named 'cv2'
    前言运行 python3req.py 文件时遇到:ModuleNotFoundError:Nomodulenamed'cv2'原因是:环境中缺少 cv2 的包,所以会出现 Nomodulenamed'cv2’ 的问题。cv2 的包名并不叫 cv2 ,所以使用 pipinstallcv2 不能安装。cv2 的包名叫 opencv-python ,使用以下命令即......
  • There is no getter for property named ‘xxxxx’ in ‘class com.xxx.xx.xx.xxxx'”
    原文链接:Thereisnogetterforpropertynamed‘xxxxx’in‘classcom.xxx.xx.xx.xxxx’”,–每天进步一点点(longkui.site) 0.背景SpringMVC架构,使用mybatis执行insert语句,然后开始报错:org.mybatis.spring.MyBatisSystemException:nestedexceptionisorg.apache.......
  • 高可用之限流-03-Semaphore 信号量做限流
    限流系列开源组件rate-limit:限流高可用之限流-01-入门介绍高可用之限流-02-如何设计限流框架高可用之限流-03-Semaphore信号量做限流高可用之限流-04-fixedwindow固定窗口高可用之限流-05-slidewindow滑动窗口高可用之限流-06-slidewindow滑动窗口sentinel源码......
  • Semaphore源码简单解读
    Semaphore源码解读注意,阅读本文需要了解AQS,AQS采用了模板设计模式。后续本人会完善这篇文章Semaphore的方法acquire()阻塞获得一个许可,会阻塞,直到得到一个可用许可或被中断重载版本acquire(n):尝试获取n个许可acquireUninterruptibly()类acquire,但不可中断tryAcquire()......
  • Python,ModuleNotFoundError: No module named 'paho'
     Exceptioninthreaddjango-main-thread:    frompaho.mqttimportclientasmqtt_clientModuleNotFoundError:Nomodulenamed'paho'  解释:ModuleNotFoundError:Nomodulenamed'paho'表示Python解释器无法找到名为paho的模块。这通常意味着paho-mqtt客户端......
  • 深度学习No module named ‘torchvision.transforms.functional_tensor‘问题解决
    问题在进行深度学习训练过程中出现ModuleNotFoundError:Nomodulenamed'torchvision.transforms.functional_tensor'报错,多方查阅资料后得到了解决方案。关于我的环境:CUDA==12.1torch==2.4.1GPU==4090D原先进行深度学习用的CUDA11.3,torch1.2.1,但是在训练时出现nvrtc......
  • Spring JdbcTemplate与NamedJdbcTemplate模板的实战案例与优化解析
    前言基于SpringJdbcTemplate来实现用户的增删改查案例,以及NamedJdbcTemplate模版的优化案例,和SpringJDBC相关支持类使用。 基本案例实现创建JavaWeb项目,使用JDBCTemplate对MySQL用户表进行增删改查操作。第一步:创建JavaWeb项目,创建数据库表,配置pom.xml文件t_user:......
  • Ubuntu20.04安装LabelImg 以及出现(ModuleNotFoundError: No module named libs.resour
    安装Ubuntu系统安装labelImg:sudoaptinstallpyqt5-dev-tools接下来,通过GitHub下载LabelImg:gitclonehttps://github.com/tzutalin/labelImg.gitcdlabelimg-mastercdrequirements/sudopip3install-rrequirements-linux-python3.txt-ihttps://pypi.tuna.tsing......
  • 29. GIL全局解释器锁、信号量、线程池进程池
    1.GIL全局解释器锁 1.1概念'''InCPython,theglobalinterpreterlock,orGIL,isamutexthatpreventsmultiplenativethreadsfromexecutingPythonbytecodesatonce.ThislockisnecessarymainlybecauseCPython’smemorymanagementisnotthrea......
  • STM32F1+HAL库+FreeTOTS学习14——数值信号量
    STM32F1+HAL库+FreeTOTS学习13——数值信号量1.数值信号量2.相关API函数2.1创建计数信号量2.2获取信号量2.3释放信号量2.4删除信号量2.5获取信号量的计数值3.操作实验1.实验内容2.代码实现:运行结果上一期我们学习了二值信号量,这一期学习计数信号量1.......