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

news2024/11/16 5:42:32

目录

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

一、无名信号量的概念

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。

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

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

相关文章

sqlite3命令行工具无法退出问题处理

一、背景&#xff1a; 软件使用的后台数据库为sqlite&#xff0c;linux主机系统层面使用sqlite3命令行工具登录数据库后&#xff0c;无法执行sql脚本&#xff0c;无法退出sqlite3。无法执行ctrlc&#xff0c;执行ctrlz后sqlite3前台进程被中断&#xff0c;但是该进程没有退出。…

字节发布文生图模型PuLID:高效身份ID特征定制,单张图像克隆AI虚拟分身

前言 字节研究团队近日提出了一种新型的文生图身份ID定制方法PuLID(Pure and Lightning ID Customization)。相较于传统的微调方法&#xff0c;PuLID无需复杂的参数优化就可以实现高效的身份ID定制&#xff0c;且能最大程度减少对原始模型行为的干扰。 PuLID是通过将轻量级的…

docker学习-docker常用其他命令整理

随便写写&#xff0c;后面有空再更新 镜像命令&#xff0c;容器命令已在之前略有更新&#xff0c;这次不写&#xff0c; 一、后台启动命令 # 命令 docker run -d 容器名 # 例子 docker run -d centos # 启动centos&#xff0c;使用后台方式启动 # 问题&#xff1a; 使用doc…

Electron学习笔记(一)

文章目录 相关笔记笔记说明 一、轻松入门 1、搭建开发环境2、创建窗口界面3、调试主进程 二、主进程和渲染进程1、进程互访2、渲染进程访问主进程类型3、渲染进程访问主进程自定义内容4、渲染进程向主进程发送消息5、主进程向渲染进程发送消息6、多个窗口的渲染进程接收主进程发…

OSError: image file is truncated (36 bytes not processed)解决方案

错误原因&#xff1a; 图像文件被损坏 解决方案&#xff1a; 代码开头添加如下两行代码&#xff1a; from PIL import ImageFile ImageFile.LOAD_TRUNCATED_IMAGES True

[华为OD] B卷 树状结构查询 200

题目&#xff1a; 通常使用多行的节点、父节点表示一棵树&#xff0c;比如 西安 陕西 陕西 中国 江西 中国 中国 亚洲 泰国 亚洲 输入一个节点之后&#xff0c;请打印出来树中他的所有下层节点 输入描述 第一行输入行数&#xff0c;下面是多行数据&#xff0c;每行以空…

远程开机与远程唤醒BIOS设置

远程开机与远程唤醒BIOS设置 在现代计算机应用中&#xff0c;远程管理和控制已成为许多企业和个人的基本需求。其中&#xff0c;远程开机和远程唤醒是两项非常实用的功能。要实现这些功能&#xff0c;通常需要在计算机的BIOS中进行一些特定的设置。以下是对远程开机和远程唤醒…

《深入解析阿里电商:数据中台与业务的双中台系统架构》

阿里巴巴作为全球领先的电商巨头&#xff0c;其技术架构一直是业界关注的焦点。特别是阿里电商的双中台系统架构——数据中台和业务中台&#xff0c;这两个平台在提升数据处理效率和业务响应速度方面起到了至关重要的作用。本文将深入探讨这一架构的设计理念、核心组件及其在实…

Androidstudio报错

现象&#xff1a; org.gradle.api.plugins.UnknownPluginException: Plugin [id: ‘com.android.application‘ 解决 方案&#xff0c;看是不是工具处于离线环境&#xff0c;是的话打开联网就好

【新手指南】Android Studio中应用App的相关配置

前言&#xff1a; 注意这是一个对于Android开发入门学习者而言的一个教程&#xff0c;因为自己平时很少使用Android进行原生应用的开发&#xff0c;对于使用Android Studio配置Android App应用的一些参数&#xff08;如版本号&#xff0c;应用包名&#xff0c;应用图标&#x…

MySQL变量的声明与使用

MySQL变量的声明与使用 1、标识符不能以数字开头 2、自能使用_或$符号&#xff0c;不允许使用其他符号。 3、不允许使用系统关键字 将赋值与查询结合 set userName 刘德华; select userName: 刘青云; # 将赋值与查询结合 查询变量/使用变量 select userName as 读取到的u…

Python批量备份华为设备配置到FTP服务器

Excel表格存放交换机信息&#xff1a; 备份文件夹效果图&#xff1a; Windows系统配置计划任务定时执行python脚本&#xff1a; Program/script&#xff1a;C:\Python\python.exe Add arguments (optional)&#xff1a; D:\Python_PycharmProjects\JunLan_pythonProje…

[C/C++] -- DFS搜索迷宫路径

设计一个程序&#xff0c;能够对给定的迷宫进行路径搜索&#xff0c;并输出一条从起点到终点的路径。具体来说&#xff0c;程序需要实现以下功能&#xff1a; 接受用户输入的迷宫地图&#xff0c;包括迷宫的行数和列数&#xff0c;以及每个格子的状态&#xff08;0 表示可通行…

十四五”智慧城市:视频大数据汇聚系统2.0建设方案与特点分析

一、背景需求分析 随着科技的不断发展&#xff0c;智慧城市的建设已经成为城市发展的重要方向。视频汇聚系统作为智慧城市建设的重要组成部分&#xff0c;已经得到了广泛的应用和推广。视频汇聚系统是智慧城市中非常重要的组成部分&#xff0c;它利用摄像头和传感器技术来收集…

Python | Leetcode Python题解之第80题删除有序数组中的重复项II

题目&#xff1a; 题解&#xff1a; class Solution:def removeDuplicates(self, nums: List[int]) -> int:idx, left, right 0, 0, 0while left < len(nums):nums[idx] nums[left]idx 1while right < len(nums) and nums[right] nums[left]:right 1if right - …

【深度学习】时空图卷积网络(STGCN),预测交通流量

论文地址&#xff1a;https://arxiv.org/abs/1709.04875 Spatio-Temporal Graph Convolutional Networks: A Deep Learning Framework for Traffic Forecasting 文章目录 一、摘要二、数据集介绍美国洛杉矶交通数据集 METR-LA 介绍美国加利福尼亚交通数据集 PEMS-BAY 介绍美国…

ASP.NET校园新闻发布系统的设计与实现

摘 要 校园新闻发布系统是在学校区域内为学校教育提供资源共享、信息交流和协同工作的计算机网络信息系统。随着网络技术的发展和Internet应用的普及&#xff0c;互联网已成为人们获取信息的重要来源。由于现在各大学校的教师和学生对信息的需求越来越高&#xff0c;校园信息…

SQL优化详解

目录 插入数据 insert的优化&#xff08;少量数据&#xff09; 批量插入 手动事务提交 主键顺序插入 插入大量数据 主键优化 数据组织方式&#xff1a; 页分裂&#xff1a; 主键顺序插入的方式&#xff1a; 主键乱序插入&#xff1a; 页合并&#xff1a; 主键设计…

软件技术主要学什么课程

软件技术专业主要学习的课程和内容有编程语言、数据结构与算法、数据库技术等&#xff0c;以下是上大学网( www.sdaxue.com)整理的软件技术主要学什么课程&#xff0c;供大家参考&#xff01; 编程语言&#xff1a;掌握一种或多种编程语言&#xff0c;如C#、Java、Python、C等&…

EdgeOne 免费证书快速实现网站 HTTPS 访问

在当今互联网环境下&#xff0c;HTTPS访问已经成为现代网站的必备功能。HTTPS 访问不仅能够更有效地保障用户在访问到网站时的数据安全传输&#xff0c;防止信息泄露、消息劫持等问题&#xff0c;在搜索引擎中&#xff0c;未实现 HTTPS 还会被浏览器提示为不安全网站&#xff0…