RT-thread(4)RT-Thread的信号 简单例程(基于HAL库,在keil中使用程序框架)

RT-Thread的信号 在keil中使用程序框架

 

按照如下方式,添加信号,使用信号

信号量的原理:

操作系统中的信号量在解决线程之间的同步中起着非常大的作用,那么什么是信号量呢?

百度百科:信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

维基百科:信号量(英语:Semaphore)又称为信号量、旗语,是一个同步对象,用于保持在0至指定最大值之间的一个计数值。当线程完成一次对该semaphore对象的等待(wait)时,该计数值减一;当线程完成一次对semaphore对象的释放(release)时,计数值加一。当计数值为0,则线程等待该semaphore对象不再能成功直至该semaphore对象变成signaled状态。semaphore对象的计数值大于0,为signaled状态;计数值等于0,为nonsignaled状态.

其中,信号量又分为两种:二进制信号量和计数信号量。

信号量的概念是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger W. Dijkstra)发明的,广泛的应用于不同的操作系统中。在系统中,给予每一个进程一个信号量,代表每个进程目前的状态,未得到控制权的进程会在特定地方被强迫停下来,等待可以继续进行的信号到来。如果信号量是一个任意的整数,通常被称为计数信号量(Counting semaphore),或一般信号量(general semaphore);如果信号量只有二进制的0或1,称为二进制信号量(binary semaphore)。在linux系统中,二进制信号量(binary semaphore)又称互斥锁(Mutex)。

其中,信号量又存在着两种操作,分别为V操作与P操作,V操作会增加信号量 S的数值,P操作会减少它。

具体的运作方式如下:

初始化,给与它一个非负数的整数值。
运行 P(wait()),信号量S的值将被减少。企图进入临界区块的进程,需要先运行 P(wait())。当信号量S减为负值时,进程会被挡住,不能继续;当信号量S不为负值时,进程可以获准进入临界区块。
运行 V(又称signal()),信号量S的值会被增加。结束离开临界区块的进程,将会运行 V(又称signal())。当信号量S不为负值时,先前被挡住的其他进程,将可获准进入临界区块。
以上是维基百科对于信号量的具体解释,下面是我自己对于信号量的一个理解。
————————————————
版权声明:本文为CSDN博主「刘扬俊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_19782019/article/details/79746627

 

复制代码
/*main.c     cubemx生成的工程文件*/

/* USER CODE BEGIN PV */
。。。
    /* 定义信号量控制块 */
    static rt_sem_t test_sem = RT_NULL;
。。。
/* USER CODE END PV */


。。。

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    
     /* 在创建线程之前,创建一个信号量 */
 test_sem = rt_sem_create("test_sem",/* 信号量名字 */
                           1, /* 信号量初始值,默认有一个信号量 */
                           RT_IPC_FLAG_FIFO); /* 信号量模式 FIFO(0x00)*/
 if (test_sem != RT_NULL)
    rt_kprintf("信号量创建成功!\n\n");

。。。
  while (1)
  {
  /* USER CODE END WHILE */


/* USER CODE BEGIN 4 */
static void led1_thread_entry(void* parameter)
{
  /* 线程都是一个无限循环,不能返回 */  
    while(1)
        {
            rt_sem_take(test_sem, /* 获取信号量 */
                        RT_WAITING_FOREVER); /* 等待时间:一直等 */
                              。。。。
            rt_sem_release(test_sem); //释放二值信号量
            rt_thread_yield(); //放弃剩余时间片,进行一次线程切换            
        }
}
static void led2_thread_entry(void* parameter)
{
    /* 线程都是一个无限循环,不能返回 */
    while(1)
        {
            rt_sem_take(test_sem, /* 获取信号量 */
            RT_WAITING_FOREVER); /* 等待时间:一直等 */
                  。。。

          rt_sem_release( test_sem ); //释放二值信号量            
          rt_thread_delay(500); /* 延时 500 个 tick, 让出CPU */
        }
}
/* USER CODE END 4 */
复制代码

posted @   辛河  阅读(151)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示