小米vela系统(基于开源nuttx内核)——如何使用信号量进行PV操作

如何使用信号量进行PV操作

  • 前言
  • 信号量
    • 1. 信号量简介
    • 2. NuttX中信号量的创建与使用
      • 2.1 Nuttx信号量的初始化和销毁
      • 2.2 信号量的等待和发布
    • 3. 信号量的实际应用:下载任务示例
      • 3.1 实际代码
      • 3.2 代码说明
      • 3.3 执行说明
    • 4. 信号量的优势与应用场景
    • 5. 常见应用场景:
  • 总结

前言

在嵌入式系统中,任务间的同步与通信是非常重要的。NuttX作为一款轻量级实时操作系统,提供了多种同步机制,其中信号量(Semaphore)是一种常见且高效的工具,用于实现线程或任务之间的同步。本文将深入探讨如何在NuttX中使用信号量,并通过一个实例来展示其应用。

在 Vela 操作系统(nuttx内核)中,使用标准的 POSIX接口,信号量的管理也是与linux系统类似的。
在这里插入图片描述

信号量

1. 信号量简介

信号量是一种用于线程间同步的机制,它可以控制多个任务的访问权限。常见的信号量类型有:

二值信号量(Binary Semaphore):信号量的值只有两个状态,0和1,常用于实现互斥锁。
计数信号量(Counting Semaphore):信号量的值可以为任意正整数,适用于控制某些资源的访问数量。
信号量通常由一个线程/任务进行“发布”(sem_post()),另一个线程/任务进行“等待”(sem_wait())。通过这种机制,任务可以在特定条件下进行同步,确保共享资源的安全访问。

在NuttX系统中,信号量的实现和使用与POSIX标准兼容,开发者可以使用标准的API来进行操作。

2. NuttX中信号量的创建与使用

NuttX提供了一些API来操作信号量,常见的函数包括:

  • sem_init():初始化信号量。
  • sem_wait():等待信号量,如果信号量值为0,则阻塞当前线程,直到信号量被发布。
  • sem_post():发布信号量,增加信号量的值,可能会解除一个等待信号量的线程阻塞。
  • sem_destroy():销毁信号量。

这些API非常方便地用于线程同步,特别是在多线程环境下。

2.1 Nuttx信号量的初始化和销毁

这里申明了一个全局的下载标志信号量,初始化为0,表示当调用wait信号量的线程在程序开始时候就会被阻塞住回等待信号量来触发执行

sem_t g_download_sem;  // 声明信号量// 初始化信号量
sem_init(&g_download_sem, 0, 0);  // 初始值为0,表示线程会等待// 销毁信号量
sem_destroy(&g_download_sem);
  • sem_init(&g_download_sem, 0, 0):初始化一个信号量 g_download_sem,第二个参数为0表示信号量在进程间共享,第三个参数为0表示信号量的初始值为0。
  • sem_destroy(&g_download_sem):销毁信号量,释放资源。

2.2 信号量的等待和发布

// 等待信号量
sem_wait(&g_download_sem);// 发布信号量
sem_post(&g_download_sem);
  • sem_wait(&g_download_sem):如果信号量的值为0,调用该函数的线程会被阻塞,直到信号量被发布(sem_post())。
  • sem_post(&g_download_sem):发布信号量,将信号量的值加1。如果有线程在等待该信号量,它将被唤醒,继续执行。

3. 信号量的实际应用:下载任务示例

为了更好地理解信号量的使用,接下来通过一个示例来演示信号量如何用于任务间同步。该示例涉及两个线程,一个是常驻线程(download_thread),等待信号量来触发下载任务,另一个线程(signal_thread)负责发送信号量,触发下载。

3.1 实际代码

#include <nuttx/config.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>sem_t g_download_sem;  // 全局信号量// 下载任务函数
void download_task(void)
{printf("Downloading... \n");usleep(2000000);  // 模拟下载过程printf("Download completed!\n");
}// 常驻下载线程,等待信号量并执行下载任务
void *download_thread(void *arg)
{while (1){printf("Download thread waiting for signal...\n");// 等待信号量sem_wait(&g_download_sem);// 收到信号量后执行下载任务download_task();}return NULL;
}// 发送信号量的线程
void *signal_thread(void *arg)
{// 模拟在某个时间点或条件触发信号量sleep(1);  // 模拟等待1秒printf("Signal thread sending signal to download thread...\n");// 给信号量发送信号,触发下载任务sem_post(&g_download_sem);return NULL;
}int main(int argc, char *argv[])
{pthread_t download_tid, signal_tid;// 初始化信号量sem_init(&g_download_sem, 0, 0);  // 初始信号量为0,线程开始时会等待// 创建下载线程pthread_create(&download_tid, NULL, download_thread, NULL);// 创建发送信号量的线程pthread_create(&signal_tid, NULL, signal_thread, NULL);// 等待信号线程完成pthread_join(signal_tid, NULL);// 等待下载线程执行完毕pthread_join(download_tid, NULL);// 清理信号量sem_destroy(&g_download_sem);return 0;
}

3.2 代码说明

  • 常驻下载线程(download_thread
    • 该线程持续运行,并在每次调用 sem_wait(&g_download_sem) 时阻塞,直到接收到信号量。信号量的接收标志着可以开始下载任务。
  • 信号量触发线程(signal_thread
    • 在模拟的条件下(例如延时1秒),该线程会调用 sem_post(&g_download_sem) 来触发下载线程开始执行下载任务。
  • 主线程(main
    • 主线程初始化信号量,创建并启动下载线程和信号量触发线程,最后等待它们的执行完成并清理资源。

3.3 执行说明

  • 程序启动后,main 线程创建两个线程:

    • download_thread 会等待信号量,并在收到信号量后执行下载任务。
    • signal_thread 在延时1秒后触发信号量,使得 download_thread 执行下载任务。
  • signal_thread 发送信号量后,download_thread 被唤醒并开始执行模拟的下载任务。

  • 最后,main 线程等待两个子线程执行完毕,并清理信号量资源。

4. 信号量的优势与应用场景

信号量作为一种同步机制,在多线程或多任务的系统中有广泛的应用。它的优势在于:

  • 简单性:信号量的基本操作非常简单,可以轻松实现任务间的同步。
  • 高效性:信号量的实现通常很轻量,适用于需要低延迟和高效同步的场景。
  • 灵活性:可以通过计数信号量控制资源的访问数量,通过二值信号量实现互斥。

5. 常见应用场景:

  1. 任务同步:当多个任务之间需要协调工作时,可以使用信号量来同步它们的执行。
  2. 资源管理:在有限资源的情况下,信号量可以用来限制并发任务的数量。例如,限制同时访问某个硬件资源的线程数。
  3. 事件通知:一个任务等待某个事件的发生,另一个任务在事件发生时发布信号量来通知等待任务。

总结

NuttX提供了POSIX兼容的信号量API,使得在多线程环境下进行任务同步变得更加简单和高效。通过本文中的示例,我们了解了如何在NuttX中创建和使用信号量,并展示了如何利用信号量控制任务的执行。信号量在嵌入式系统中应用广泛,特别是在需要多任务协作和资源管理的场景中,信号量提供了一种简洁的解决方案。

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

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

相关文章

CMake学习笔记(2)

1. 嵌套的CMake 如果项目很大&#xff0c;或者项目中有很多的源码目录&#xff0c;在通过CMake管理项目的时候如果只使用一个CMakeLists.txt&#xff0c;那么这个文件相对会比较复杂&#xff0c;有一种化繁为简的方式就是给每个源码目录都添加一个CMakeLists.txt文件&#xff…

旅游网站设计与实现

文末附有完整项目代码 在当今数字化时代&#xff0c;旅游网站成为人们获取旅游信息的重要途径。本文将详细介绍旅游网站的设计与实现&#xff0c;让你轻松了解其中的技术奥秘&#xff01; 一、项目背景 随着社会经济的发展&#xff0c;人们对精神消费愈发重视&#xff0c;旅游…

【C++】size_t究竟是什么?全面解析与深入拓展

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;一、什么是size_t&#xff1f;为什么需要size_t&#xff1f; &#x1f4af;二、size_t的特性与用途1. size_t是无符号类型示例&#xff1a; 2. size_t的跨平台适应性示例对…

【物流管理系统 - IDEAJavaSwingMySQL】基于Java实现的物流管理系统导入IDEA教程

有问题请留言或私信 步骤 下载项目源码&#xff1a;项目源码 解压项目源码到本地 打开IDEA 左上角&#xff1a;文件 → 新建 → 来自现有源代码的项目 找到解压在本地的项目源代码文件&#xff0c;点击确定&#xff0c;根据图示步骤继续导入项目 查看项目目录&#xff…

ssh2-sftp-client和ssh2配合使用js脚本快速部署项目到服务器

有时候因为服务器不能实现github或者gitlab的自动部署服务&#xff0c;所以就需要使用脚本来实现自动部署&#xff0c;可以省时省力&#xff0c;一劳永逸。这里就使用ssh2-sftp-client和ssh2来实现&#xff0c;即便是需要sudo权限&#xff0c;也是可以的。 1.先将本地打包后的…

深度解析Linux中的调试器gdb/cgdb的使用

Linux下我们编译好的代码&#xff0c;无法直接调试 gcc/g默认的工作模式是realse模式 程序要调试的话&#xff0c;必须是debug模式&#xff0c;也就是说编译的时候要加-g选项 gdb携带调试信息的exe 我们现在在文件夹里面创建一个文件lesson11 里面创建一个累加的代码&…

【Maui】动态菜单实现(绑定数据视图)

前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创建本机移动和桌面应用。 使用 .NET MAUI&#xff0c;可从单个共享代码库开发可在 Android、iOS、macOS 和 Windows 上运行的应用。 .NET MAUI 是一款开放源代码应用&#xff0c;是 X…

Bash语言的语法糖

Bash语言的语法糖 引言 在现代编程语言中&#xff0c;“语法糖”是一个非常常见的术语&#xff0c;它指的是那些使代码更加易读、易写的语法特性。尽管这些特性并不改变语言的功能&#xff0c;但它们能显著提升开发者的编程体验。在众多编程语言中&#xff0c;Bash&#xff0…

linux---Nginx详细教程(包含安装,网站部署)

Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;也可以用作邮件代理服务器&#xff0c;其以占有内存少、并发能力强、稳定性高、丰富的功能集、低系统资源消耗而闻名。以下是对Nginx的详细教程&#xff1a; 一、Nginx简介 Nginx由俄罗斯人开发&#xff0c;第一个公开版…

RNN之:LSTM 长短期记忆模型-结构-理论详解-及实战(Matlab向)

0.前言 递归&#xff01;循环神经网络Recurrent Neural Network 循环神经网络&#xff08;又称递归神经网络&#xff0c;Recurrent Neural Network&#xff0c;RNN&#xff09;。是一种用于处理序列数据的神经网络结构&#xff0c;具有记忆功能&#xff0c;能够捕捉序列中的时…

泛目录和泛站有什么差别

啥是 SEO 泛目录&#xff1f; 咱先来说说 SEO 泛目录是啥。想象一下&#xff0c;你有一个巨大的图书馆&#xff0c;里面的书架上摆满了各种各样的书&#xff0c;每一本书都代表着一个网页。而 SEO 泛目录呢&#xff0c;就像是一个超级图书管理员&#xff0c;它的任务就是把这些…

初识@ffmpeg/ffmpeg库

前言 FFmpeg是一套可以用来记录、转换数字音频、视频,并且能够利用它们来创建一个新的流媒体格式的自由软件项目,它被广泛应用在视频处理、音频处理以及直播领域。其中,@ffmpeg/ffmpeg 是一个将 FFmpeg 编译为 WebAssembly(WASM)的库,可支持几乎所有的音视频格式。 安装…

【图像去噪】论文复现:反向扩散中加入MAP将扩散模型从高斯去噪推广到真实去噪!DiffusionVI的Pytorch源码复现,跑通源码,梳理理论,单卡可执行!

请先看【专栏介绍文章】:【图像去噪(Image Denoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中) 完整代码和训练好的模型权重文件下载链接见本文底…

Windows 蓝牙驱动开发-简介

蓝牙(英语&#xff1a;Bluetooth)是一种无线通信技术标准&#xff0c;用来让固定与移动设备&#xff0c;在短距离间交换资料&#xff0c;以形成个人局域网(PAN)。其使用短波特高频(UHF)无线电波&#xff0c;经由2.4至2.485 GHz的ISM频段来进行通信。1994年由电信商爱立信(Erics…

【Vue】全局/局部组件使用流程(Vue2为例)

全局组件和局部组件区别 如何使用 全局组件&#xff1a;全局注册后&#xff0c;可以在任意页面中直接使用。局部组件&#xff1a;在页面中需要先导入子组件路径&#xff0c;注册组件才能使用。 适用场景 全局组件&#xff1a;适用于高频使用的组件&#xff0c;如导航栏、业…

【Pytorch实用教程】PyTorch 中如何输出模型参数:全面指南

文章目录 PyTorch 中如何输出模型参数:全面指南1. 为什么需要输出模型参数?2. PyTorch 中输出模型参数的方法2.1 使用 `model.parameters()` 输出所有参数2.2 使用 `model.named_parameters()` 输出参数名称和值2.3 使用 `model.state_dict()` 输出模型的参数字典2.4 输出特定…

vscode vue 自动格式化

vscode vue 自动格式化 安装Prettier和Vetur插件 选择设置&#xff0c;并且转到编辑文件。增加如下内容。 {"editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","[vue]": {"editor.defaultFor…

1、docker概念和基本使用命令

docker概念 微服务&#xff1a;不再是以完整的物理机为基础的服务软件&#xff0c;而是借助于宿主机的性能。以小量的形式&#xff0c;单独部署的应用。 docker&#xff1a;是一个开源的应用容器引擎&#xff0c;基于go语言开发的&#xff0c;使用时apache2.0的协议。docker是…

Genymotion配套VirtualBox所在地址

在 Genymotion打开虚拟机前需要先打开VirtualBox中的虚拟机 C:\Program Files\Oracle\VirtualBox\VirtualBox.exe 再开启genymotion中的虚拟机开关

【Linux】深刻理解软硬链接

一.软硬链接操作 1.软连接 touch 创建一个文件file.txt &#xff0c;对该文件创建对应的软链接改怎么做呢&#xff1f; ln -s file.txt file-soft.link .给对应文件创建软连接。 软连接本质就是一个独立的文件&#xff0c;因为我们对应的软连接有独立的inode&#xff0c;他…