Linux 无名信号量(Semaphore)的使用

目录

  • 一、无名信号量的概念
  • 二、无名信号量相关函数
  • 三、信号量的使用步骤
  • 四、应用场景
  • 五、测试代码

一、无名信号量的概念

Linux无名信号量(Semaphore)
  在Linux操作系统中,信号量(Semaphore)是一种用于进程间或线程间同步和互斥的工具。无名信号量(也被称为POSIX信号量)是POSIX标准的一部分,与System V信号量相比,它提供了更丰富的功能和更好的可移植性。
  无名信号量是一种用于控制多个线程进程对共享资源的访问的计数器。它通常用于实现两个功能。
同步:确保进程或线程以特定的顺序访问资源。
互斥:防止两个或多个进程或线程同时访问共享资源。
  信号量的值是一个非负整数,通常被称为“许可数”或“资源数”。当信号量的值为0时,表示没有资源可用;当信号量的值大于0时,表示有相应数量的资源可用。

二、无名信号量相关函数

无名信号量相关函数如下
sem_init():初始化一个无名信号量。
sem_destroy():销毁一个无名信号量。
sem_wait()(也称为sem_trywait()或sem_timedwait()):尝试减少信号量的值。如果信号量的值大于0,则将其减1并立即返回;如果信号量的值为0,则进程将被阻塞,直到信号量的值变为非零。
sem_post():增加信号量的值。这通常表示释放了一个资源。

头文件

#include <semaphore.h>

函数的详细内容,可查看手册,如 sem_wait() 函数,介绍如下:
在这里插入图片描述

三、信号量的使用步骤

使用信号量的步骤
①在程序全局区定义信号量;
②使用 sem_init()初始化信号量;
③ 使用 sem_wait()和 sem_post()对信号量进行 P/V 操作;
④ 使用 sem_destroy()销毁信号量。

四、应用场景

无名信号量在多线程编程和进程间通信(IPC)中非常有用。以下是一些可能的应用场景:
生产者-消费者问题:生产者生成数据项并将其放入缓冲区,而消费者从缓冲区中取出数据项并处理它们。使用信号量可以确保生产者在缓冲区满时不会写入数据,而消费者在缓冲区空时不会尝试读取数据。
读写锁:多个线程可以同时对共享资源进行读操作,但在写操作期间需要阻止其他线程进行读或写操作。信号量可以用于实现这种读写锁。

五、测试代码

  程序创建了一个生产者线程和一个消费者线程,线程间通过一个固定大小的缓冲区进行通信。生产者生产整数并将其放入缓冲区,而消费者从缓冲区中取出整数并打印。通过使用信号量empty和full,可以确保生产者不会在缓冲区满时写入数据,而消费者不会在缓冲区空时尝试读取数据。

#include <stdio.h>  
#include <stdlib.h>  
#include <pthread.h>  
#include <semaphore.h>  
  
#define BUFFER_SIZE 10  
  
int buffer[BUFFER_SIZE];  
int in = 0, out = 0;  
sem_t empty, full;  
  
void *producer(void *arg) {  
    for (int i = 0; i < 20; i++) {  
        sem_wait(&empty);  // 等待缓冲区有空位  
        buffer[in] = i;  
        printf("Producer produced %d\n", i);  
        in = (in + 1) % BUFFER_SIZE;  
        sem_post(&full);   // 表示缓冲区有一个新项  
    }  
    return NULL;  
}  
  
void *consumer(void *arg) {  
    for (int i = 0; i < 20; i++) {  
        sem_wait(&full);   // 等待缓冲区有项  
        int item = buffer[out];  
        printf("Consumer consumed %d\n", item);  
        out = (out + 1) % BUFFER_SIZE;  
        sem_post(&empty);  // 表示缓冲区有一个空位  
    }  
    return NULL;  
}  
  
int main() {  
    pthread_t p, c;  
    sem_init(&empty, 0, BUFFER_SIZE);  // 初始时缓冲区为空,有BUFFER_SIZE个空位  
    sem_init(&full, 0, 0);             // 初始时缓冲区无项  
  
    pthread_create(&p, NULL, producer, NULL);  
    pthread_create(&c, NULL, consumer, NULL);  
  
    pthread_join(p, NULL);  
    pthread_join(c, NULL);  
  
    sem_destroy(&empty);  
    sem_destroy(&full);  
  
    return 0;  
}

测试结果
在这里插入图片描述
线程中加入 sleep() 函数
在这里插入图片描述

代码如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <pthread.h>  
#include <semaphore.h>  
#include <unistd.h>
  
#define BUFFER_SIZE 10  
  
int buffer[BUFFER_SIZE];  
int in = 0, out = 0;  
sem_t empty, full;  
  
void *producer(void *arg) {  
    for (int i = 0; i < 20; i++) {  
        sem_wait(&empty);  // 等待缓冲区有空位  
        buffer[in] = i;  
        printf("Producer produced %d\n", i);  
        in = (in + 1) % BUFFER_SIZE;  
        sem_post(&full);   // 表示缓冲区有一个新项  
        sleep(1);
    }  
    return NULL;  
}  
  
void *consumer(void *arg) {  
    for (int i = 0; i < 20; i++) {  
        sem_wait(&full);   // 等待缓冲区有项  
        int item = buffer[out];  
        printf("Consumer consumed %d\n", item);  
        out = (out + 1) % BUFFER_SIZE;  
        sem_post(&empty);  // 表示缓冲区有一个空位  
	sleep(1);
    }  
    return NULL;  
}  
  
int main() {  
    pthread_t p, c;  
    sem_init(&empty, 0, BUFFER_SIZE);  // 初始时缓冲区为空,有BUFFER_SIZE个空位  
    sem_init(&full, 0, 0);             // 初始时缓冲区无项  
  
    pthread_create(&p, NULL, producer, NULL);  
    pthread_create(&c, NULL, consumer, NULL);  
  
    pthread_join(p, NULL);  
    pthread_join(c, NULL);  
  
    sem_destroy(&empty);  
    sem_destroy(&full);  
  
    return 0;  
}

测试结果如下:
在这里插入图片描述
可以看到,第一种程序,因为没有sleep()让出 cpu,会一直生产数据,直到 empty 为空,也就是等待缓冲区空位为0 ,程序阻塞,让出 cpu ,消费者开始进行处理,直到 full 为空,处理完毕,让出 cpu。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OSG编程指南<二十三>:基于OSG+ImGui制作模型编辑器,实现三轴方向的实时平移、旋转和缩放变化

1、概述 在OSG的开发应用过程中&#xff0c;我们有时候总会纠结于使用MFC还是Qt来嵌入OSG窗口以便于后续的功能开发&#xff0c;毕竟选择一个合适的UI框架&#xff0c;对于后续的开发还是省去很多麻烦的。但对于初学者来说&#xff0c;可能对框架消息机制的不熟悉&#xff0c;尤…

景源畅信电商:做抖音有哪些未开发的蓝海领域?

在互联网信息爆炸的今天&#xff0c;抖音已经成为人们获取信息和娱乐的重要渠道。然而&#xff0c;随着用户数量的增加和内容的丰富&#xff0c;抖音的红海竞争也日益激烈。在这样的背景下&#xff0c;寻找还未被充分开发的蓝海领域&#xff0c;对于内容创作者来说&#xff0c;…

基于微信小程序+JAVA Springboot 实现的【智慧乡村旅游服务平台】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 基于微信小程序的智慧乡村旅游服务平台的设计与实现 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; Java SSM框架数据库&#xff1a; MySQL前端技术&#xff1a; 微信开发者工具、uni-app其他技术&#xff1a…

Darknet+ros+realsenseD435i+yolo(ubuntu20.04)

一、下载Darknet_ros mkidr -p yolo_ws/src cd yolo_ws/src git clone --recursive https://github.com/leggedrobotics/darknet_ros.git #因为这样克隆的darknet文件夹是空的&#xff0c;将darknet_ros中的darknet的文件替换成如下 cd darknet_ros git clone https://github.…

自定义注解

例如写一个注解PrintTime 如下&#xff1a; import java.lang.annotation.*;//下面的注解属于元注解 Target({ElementType.PARAMETER,ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Inherited Documented public interface PrintTime {/*** 注解的属性*/public S…

JavaScript 进阶(二)

一、深入对象 1. 创建对象的三种方式 利用 new Object 创建对象 2. 构造函数 【注意事项】 【例】 这样子写好之后&#xff0c;想要添加一个新的结构类似的对象&#xff0c;直接照着红圈中写&#xff0c;最后改相应的数据就好了 注意&#xff1a;红色是第一步&#xff0c;黄…

springboot004网页时装购物系统

springboot004网页时装购物系统 亲测完美运行带论文&#xff1a;获取源码&#xff0c;私信评论或者v:niliuapp 运行视频 包含的文件列表&#xff08;含论文&#xff09; 数据库脚本&#xff1a;db.sql其他文件&#xff1a;ppt.pptx论文/文档&#xff1a;开题报告.docx论文&…

如何利用命令提示符列出文件?这里提供了几个实例供你参考

序言 什么命令可以用来列出目录中的文件&#xff1f;如何在命令提示符Windows 10/11中列出文件&#xff1f;很多人对这些问题感到困惑。在这篇文章中&#xff0c;我们详细解释了命令提示符列出文件的主题。 CMD&#xff08;命令提示符&#xff09;是一个功能强大的Windows内置…

河南广电与LiblibAI签署战略合作协议

5月15日&#xff0c;河南广电科技与LiblibAI战略签约仪式在郑州中原福塔新闻发布厅隆重举行。双方将本着“共商、共享、共建、共赢”原则&#xff0c;基于全面、可持续的战略合作伙伴关系&#xff0c;发挥各自优势&#xff0c;共同聚焦生成式AI领域&#xff0c;围绕内容创作、商…

【永洪BI】管理系统

管理系统模块包括系统设置、认证授权、日志管理、监控预警、资源部署、VooltDB管理、数据库管理、企业应用配置、系统检查、应用管理模块。 系统设置界面&#xff1a; 可以进行清除系统缓存、配置系统主题、配置系统邮箱、配置门户主页、配置权限管理系统、配置密码策略、配置…

音乐的力量

常听音乐的好处可以让人消除工作紧张、减轻生活压力、避免各类慢性疾病等等&#xff0c;其实这些都是有医学根据的。‍ 在医学研究中发现&#xff0c;经常的接触音乐节 奏、旋律会对人体的脑波、心跳、肠胃蠕动、神经感应等等&#xff0c;产生某些作用&#xff0c;进而促进身心…

【MySQl】MySQL概述 | 数据库的操作 | MySQL的编码问题 | 连接器的工作流程

文章目录 一、MySQL概述1.数据库的概念MySQLMySQL中支持的数据类型&#xff1a; 2.数据库的操作1.创建数据库2.查看数据库3.选中数据库4.删除数据库 3.数据表的操作1.创建表2.查看当前数据库中的所有表3.查看指定表的结构4.删除表 二、MySQL的编码问题常见的编码类型 连接器的工…

Linux文件:重定向底层实现原理(输入重定向、输出重定向、追加重定向)

Linux文件&#xff1a;重定向底层实现原理&#xff08;输入重定向、输出重定向、追加重定向&#xff09; 前言一、文件描述符fd的分配规则二、输出重定向&#xff08;>&#xff09;三、输出重定向底层实现原理四、追加重定向&#xff08;>>&#xff09;五、输入重定向…

邦注科技 工业冷水机的风冷和水冷的区别介绍

工业冷水机在工业生产中扮演着重要角色&#xff0c;特别是在需要精确控制温度的应用中。风冷式冷水机和水冷式冷水机是两种常见的类型&#xff0c;它们之间存在一些显著的区别。 热交换的来源不同&#xff1a; 风冷式冷水机&#xff1a;热交换的来源是气体。它采用空气冷却方…

java技术:nacos

目录 一、docker安装 1、创建一个nacos 2、复制配置信息出来&#xff08;方便修改配置文件&#xff09; 3、删除nacos 4、修改配置文件&#xff08;主要是一下几个&#xff09; 6、创建数据库 nacos 7、重启nacos mysql 一、docker安装 1、创建一个nacos docker run …

随笔:棋友们

我是在小学二年级学会中国象棋的&#xff0c;准确说&#xff0c;是学会象棋的下棋规则的&#xff0c;师傅是二舅。我最早的对手就是同学波仔。波仔比我略早学会象棋&#xff0c;总用连珠炮欺负我&#xff0c;开局几步棋就把我将死。我不知道怎么破解。轮到我先走时&#xff0c;…

几个排序器的verilog及其资源占用、延时分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 因为课题需要&#xff0c;调研了几个快速排序方法&#xff0c;并手写或者改进了若干待测试对象&#xff0c;包括记分板型冒泡排序&#xff08;这个是别人的&#xff09…

Spring Security实现用户认证二:前后端分离时自定义返回Json内容

Spring Security实现用户认证二&#xff1a;前后端分离时自定义返回Json内容 1 前后端分离2 准备工作依赖WebSecurityConfig配置类 2 自定义登录页面2.1 Spring Security的默认登录页面2.2 自定义配置formLogin 3 自定义登录成功处理器4 自定义登录失败处理器5 自定义登出处理器…

如何快速找出文件夹里的全部带有中文纯中文的文件

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 步骤 1、打开工具&#xff0c;切换到批量复制文件 2、鼠标移到右侧&#xff0c;点击搜索添加 3、设定查找范围、指定为文件、勾选 包含全部子文件夹&#x…

254 基于matlab的钢筋混凝土非线性分析

基于matlab的钢筋混凝土非线性分析&#xff0c;根据梁本构关系&#xff0c;然后进行非线性分析&#xff0c;绘制弯矩-曲率曲线。可设置梁的截面尺寸、混凝土本构&#xff0c;钢筋截面面积等相关参数&#xff0c;程序已调通&#xff0c;可直接运行。 254 钢筋混凝土非线性分析 弯…