草庐IT

HarmonyOS中信号量实验

ST小智 2023-08-23 原文

     大家好,我是ST,今天主要和大家聊一聊,如何使用鸿蒙系统中的信号量。

目录

第一:HarmonyOS 内核信号量基本简介

第二:信号量API分析

第三:软件设计

第四:编译调试

第五:运行结果

第一:HarmonyOS 内核信号量基本简介

    信号量是基于软件互斥或硬件互斥方法实现的一种用于同步和互斥的机制。信号量是一个确定的二元组(s,q),其中s是一个具有非负初值的整形变量,q是一个初始状态为空的队列。

第二:信号量API分析

    osSemaphoreNew()

osSemaphoreId_t osSemaphoreNew(uint32_t max_count,uint32_t initial_count,const osSemaphoreAttr_t *attr)

功能描述:

函数osMessageQueueNew创建并初始化一个消息队列对象。该函数返回消息队列对象标识符,如果出现错误则返回NULL,可以在RTOS启动(调用 osKernelStart)之前安全地调用该函数,也可以在内核初始化 (调用 osKernelInitialize)之前调用该函数。

参数:

名字描述
max_count可用令牌的最大数量.
initial_count可用令牌的初始数量.
attr信号量的属性;空:默认值.

osSemaphoreRelease()

osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)

功能描述:函数osSemaphoreRelease释放由参数semaphore_id指定的信号量对象的标记

参数:

名字描述
semaphore_id由osSemaphoreNew获得的信号量ID.

osSemaphoreAcquire()

osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id,uint32_t timeout)	

功能描述:阻塞函数osSemaphoreAcquire一直等待,直到由参数semaphore_id指定的信号量对象的标记可用为止。如果一个令牌可用,该函数立即返回并递减令牌计数。

参数:

名字描述
semaphore_id由osSemaphoreNew获得的信号量ID.
timeout超时值.

第三:软件设计

   在Semaphore_example函数中,通过osSemaphoreNew()函数创建了sem1信号量,Thread_Semaphore1()函数中通过osSemaphoreRelease()函数释放两个信号量,Thread_Semaphore2()和Thread_Semaphore3()函数中,先开始阻塞等待sem1信号量。只有当Thread_Semaphore1()函数中增加两次信号量,Thread_Semaphore2()和Thread_Semaphore3()才能继续同步运行。若Thread_Semaphore1()函数中只增加一次信号量,那Thread_Semaphore2()和Thread_Semaphore3()只能轮流执行。

void Thread_Semaphore1(void)
{
    while(1)
	{
		osSemaphoreRelease(sem1);  //释放两次sem1信号量,使得Thread_Semaphore2和Thread_Semaphore3能同步执行
        osSemaphoreRelease(sem1);  //此处若只释放一次信号量,则Thread_Semaphore2和Thread_Semaphore3会交替运行。
        printf("Thread_Semaphore1 Release  Semap \n");
        osDelay(100);
	}

}
void Thread_Semaphore2(void)
{    
    while(1)
	{
		osSemaphoreAcquire(sem1,osWaitForever);//申请sem1信号量
        printf("Thread_Semaphore2 get Semap \n");
        osDelay(1);
	}
}

void Thread_Semaphore3(void)
{    
    while(1)
	{
		osSemaphoreAcquire(sem1,osWaitForever);//等待sem1信号量
        printf("Thread_Semaphore3 get Semap \n");
        osDelay(1);
	}
}

void Semaphore_example (void)
{ 
    osThreadAttr_t attr;  

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024*4;
    attr.priority = 24;
    
    attr.name = "Thread_Semaphore1";
    if (osThreadNew((osThreadFunc_t)Thread_Semaphore1, NULL, &attr) == NULL) 
    {
        printf("Falied to create Thread_Semaphore1!\n");
    }
    attr.name = "Thread_Semaphore2";
    if (osThreadNew((osThreadFunc_t)Thread_Semaphore2, NULL, &attr) == NULL) 
    {
        printf("Falied to create Thread_Semaphore2!\n");
    }
    attr.name = "Thread_Semaphore3";
    if (osThreadNew((osThreadFunc_t)Thread_Semaphore3, NULL, &attr) == NULL) 
    {
        printf("Falied to create Thread_Semaphore3!\n");
    }
    sem1=osSemaphoreNew(4, 0, NULL);  
    if (sem1 == NULL) 
    {
        printf("Falied to create Semaphore1!\n");
    }
}

第四:编译调试

    修改BUILD.gn文件

    修改applications\BearPi\BearPi-HM_Nano\sample路径下 BUILD.gn 文件,指定 semp_example 参与编译。

#"A1_kernal_thread:thread_example",
#"A2_kernel_timer:timer_example",
#"A3_kernel_event:event_example",
#"A4_kernel_mutex:mutex_example",
"A5_kernel_semaphore:semaphore_example",
#"A6_kernel_message:message_example",

第五:运行结果

    示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,Thread_Semaphore1一次释放两个信号量,Thread_Semaphore2和Thread_Semaphore3同步执行。

Thread_Semaphore1 Release  Semap 
Thread_Semaphore2 get Semap 
Thread_Semaphore3 get Semap 
Thread_Semaphore1 Release  Semap 
Thread_Semaphore2 get Semap 
Thread_Semaphore3 get Semap 
Thread_Semaphore1 Release  Semap 
Thread_Semaphore2 get Semap 
Thread_Semaphore3 get Semap 

有关HarmonyOS中信号量实验的更多相关文章

  1. HarmonyOS原子化服务开发相关术语 - 2

    术语中文解释Ability原子化服务帮助用户完成任务的原子化服务,和用户的意图进行关联。Fulfillment服务履行通过图标,卡片,语音等形式呈现用户意图。开发者通过接口的方式,处理用户意图,返回内容。Intent意图用于表达用户想要达成的目标或完成的任务。HUAWEIAssistant智能助手“无微不智”的个人助手,通过不断的学习用户的使用习惯,不断的为用户提供贴心的精准的便捷的个性化服务。AISearch全局搜索用户可快速搜索关键词,与之匹配的原子化服务则会出现在搜索结果中。SmartService智慧服务用户订阅原子化服务,在到达特定触发条件(时间、地点、事件)后,卡片推送至用户智能助

  2. Verilog使用inout信号的方法 - 2

    目录一、inout在设计文件中的使用方法1.1、inout的第一种使用方法1.2、inout实现的第二种使用方法1.3、inout使用总结 二、inout在仿真测试中的使用方法一、inout在设计文件中的使用方法在FPGA的设计过程中,有时候会遇到双向信号(既能作为输出,也能作为输入的信号叫双向信号)。比如,IIC总线中的SDA信号就是一个双向信号,QSPIFlash的四线操作的时候四根信号线均为双向信号。在Verilog中用关键字inout定义双向信号,这里总结一下双向信号的处理方法。1.1、inout的第一种使用方法  实际上,双向信号的本质是由一个三态门组成的,三态门可以输出高电平,低电

  3. ruby - 在 Ruby 中使用 GTK3 自定义信号 - 2

    我想从gtk3中的Widget发出自定义信号。在GTK2中,有一个名为signal_new的函数来创建一个新信号。您可以在此处查看示例:https://github.com/ruby-gnome2/ruby-gnome2/blob/ec373f87e672dbeeaa157f9148d18b34713bb90e/glib2/sample/type-register.rb在GTK3中,这个功能似乎不再可用。那么在ruby​​的GTK3中创建自定义信号的新方法是什么? 最佳答案 GTK3更改为使用define_signal方法而不是si

  4. ruby - QtRuby 使用参数/参数连接信号和槽 - 2

    我想知道如何连接到带参数的信号(使用Rubyblock)。我知道如何连接到一个不带参数的:myCheckbox.connect(SIGNAL:clicked){doStuff}但是,这不起作用:myCheckbox.connect(SIGNAL:toggle){doStuff}它不起作用,因为切换槽采用参数voidQAbstractButton::toggled(boolchecked)。我怎样才能让它与参数一起工作?谢谢。 最佳答案 对您的问题的简短回答是,您必须使用slots方法声明要连接的插槽的方法签名:classMainGU

  5. ruby - 发送信号时运行代码,但不要在 Ruby 中捕获信号 - 2

    我有在服务器上运行的代码,在服务器硬关闭之前,发送了一个信号SIGTERM让我的代码知道它需要清理。我想在发生这种情况时运行代码并将信号发送回同一个程序,以便任何其他需要清理的代码都可以这样做。我不想捕获信号或改变信号行为,我只需要在我的程序的其余部分解释SIGTERM之前运行一些东西。目前我可以做类似的事情Signal.trap('TERM')doputs"Gracefulshutdown"exitend但如果同一个应用中的多段代码试图做同样的事情,它就不起作用了。例如:Signal.trap('TERM')doputs"Gracefulshutdown"exitendSignal.

  6. 网络实验之RIPV2协议(一) - 2

    一、RIPV2协议简介  RIP(RoutingInformationProtocol)路由协议是一种相对古老,在小型以及同介质网络中得到了广泛应用的一种路由协议。RIP采用距离向量算法,是一种距离向量协议。RIP-1是有类别路由协议(ClassfulRoutingProtocol),它只支持以广播方式发布协议报文。RIP-1的协议报文无法携带掩码信息,它只能识别A、B、C类这样的自然网段的路由,因此RIP-1不支持非连续子网(DiscontiguousSubnet)。RIP-2是一种无类别路由协议(ClasslessRoutingProtocol),支持路由标记,在路由策略中可根据路由标记对

  7. 第1部分 实验拓扑、终端服务器 - 2

    目录1.1访问Cisco路由器的方法1.1.1通过Console口访问路由器1.1.2通过Telnet访问路由器1.1.3终端访问服务器1.2终端访问服务器配置命令汇总1.1访问Cisco路由器的方法    路由器没有键盘和鼠标,要初始化路由器需要把计算机的串口和路由器的Console口进行连接。访问Cisco路由器的方法还有Telnet、WebBrowser和网络管理软件(如CiscoWorks)等,本节讨论前2种。1.1.1通过Console口访问路由器    计算机的串口和路由器的Console口是通过反转线(Rollover)进行连接的,反转线的一端接在路由器的Console口上,另一

  8. 【操作系统实验】Ubuntu Linux 虚拟机用户管理 - 2

    文章目录一、用户二、用户分类1、普通用户2、超级用户3、系统用户三、用户相关文件1、/etc/passwd文件2、/etc/shadow文件四、用户管理命令1、useradd2、adduser3、passwd4、usermod5、userdel一、用户Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户都必须先向系统管理员申请一个账号,然后以这个账号的身份进入系统。在Linux系统中,任何文件都属于某一特定用户,而任何用户都隶属于至少一个用户组。用户名(username):每个用户账号都拥有一个惟一的用户名和各自的口令。用户在登录时键入正确的用户名和口令后,就能够进入系

  9. ruby - 如何测试 RSpec 中的信号处理,特别是 SIGTERM 的处理? - 2

    Heroku可能会出于各种原因向您的应用程序发送SIGTERM,因此我创建了一个处理程序来处理一些清理工作,以防发生这种情况。一些谷歌搜索没有给出任何关于如何在RSpec中测试它的答案或示例。这是基本代码:Signal.trap('TERM')docleanupenddefcleanupputs"doingsomecleanupstuff"...exitend当程序收到SIGTERM时,测试调用此清理方法的最佳方法是什么? 最佳答案 使用Process.kill'TERM',0将信号发送到RSpec并测试调用处理程序。确实,如果信号

  10. ruby - 我怎样才能告诉 unicorn 理解 Heroku 的信号? - 2

    也许你已经看到了这个......2012-03-07T15:36:25+00:00heroku[web.1]:StoppingprocesswithSIGTERM2012-03-07T15:36:36+00:00heroku[web.1]:StoppingprocesswithSIGKILL2012-03-07T15:36:36+00:00heroku[web.1]:ErrorR12(Exittimeout)->Processfailedtoexitwithin10secondsofSIGTERM2012-03-07T15:36:38+00:00heroku[web.1]:Proces

随机推荐