RT-Thread信号量的基本操作

抽象的来讲,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为 0 时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: take ( 获取) 和Release(释放)。当一个线程调用 take 操作时,它要么得到资源然后将信号量减一,要么
一直等下去(指放入阻塞队列),直到信号量大于等于一时。 Release(释放)实际上是在信号量上执行加操作, take(获取)实际上是在信号量上执行减操作。RT-Thread 中的信号量有静态和动态之分(同静态线程、动态线程), 和信号量有关的操作如下:
  初始化—rt_sem_init()( 对应静态信号量) ;
  建立—rt_sem_create()( 对应动态信号量);
  获取—rt_sem_take();
  释放—rt_sem_release();
  脱离—rt_sem_detach()( 对应静态信号量) ;
  删除—rt_sem_delete()( 对应动态信号量) ;

/**********************************************************************************************************
*
*    模块名称 : 功能演示
*    文件名称 : test.c
*    版    本 : V1.0
*    说    明 :
*    修改记录 :
*        版本号  日期        作者                        说明
*
*        v1.0    2013-4-20   jiezhi320(UP MCU 工作室)    演示信号量的基本操作 源码来自官方教程文件
*
*    Copyright (C), 2012-2013,
*   淘宝店:   http://shop73275611.taobao.com
*   QQ交流群: 258043068
*
**********************************************************************************************************/
#include <rtthread.h>
#include <stm32f10x.h>
#include "test.h"

rt_uint32_t  g_tmp;/* 定义一个全局变量*/

/*  变量分配4字节对齐 */
ALIGN(RT_ALIGN_SIZE)

/*  静态线程的 线程堆栈*/
static rt_uint8_t thread1_stack[512];

/* 静态线程的 线程控制块 */
static struct rt_thread thread_test1;

static void test1_thread_entry(void* parameter);

/* 信号量控制块 */
static struct rt_semaphore static_sem;
/* 指向信号量的指针 */
static rt_sem_t dynamic_sem = RT_NULL;

rt_err_t demo_thread_creat(void)
{
    rt_err_t result;

    /* 初始化静态信号量,初始值是0 */
    result = rt_sem_init(&static_sem, "ssem", 0, RT_IPC_FLAG_FIFO);
    if (result != RT_EOK)
    {
        rt_kprintf("init static semaphore failed.\n");
        return -1;
    }

    /* 创建一个动态信号量,初始值是0 */
    dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
    if (dynamic_sem == RT_NULL)
    {
        rt_kprintf("create dynamic semaphore failed.\n");
        return -1;
    }

    /* 创建静态线程 : 优先级 16 ,时间片 5个系统滴答 */
    result = rt_thread_init(&thread_test1,
                            "test1",
                            test1_thread_entry, RT_NULL,
                            (rt_uint8_t*)&thread1_stack[0], sizeof(thread1_stack), 16, 5);

    if (result == RT_EOK)
    {
        rt_thread_startup(&thread_test1);
    }
    return 0;
}

void test1_thread_entry(void* parameter)
{
    rt_err_t result;
    rt_tick_t tick;

    /* 1. staic semaphore demo */
    /* 获得当前的OS Tick */
    tick = rt_tick_get();

    /* 试图持有信号量,最大等待10个OS Tick后返回 */
    result = rt_sem_take(&static_sem, 10);
    if (result == -RT_ETIMEOUT)
    {
        /* 超时后判断是否刚好是10个OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_sem_detach(&static_sem);
            return ;
        }
        rt_kprintf("take semaphore timeout\n");
    }
    else
    {
        /* 因为没有其他地方释放信号量,所以不应该成功持有信号量,否则测试失败 */
        rt_kprintf("take a static semaphore, failed.\n");
        rt_sem_detach(&static_sem);
        return ;
    }

    /* 释放一次信号量 */
    rt_sem_release(&static_sem);

    /* 永久等待方式持有信号量 */
    result = rt_sem_take(&static_sem, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功则测试失败 */
        rt_kprintf("take a static semaphore, failed.\n");
        rt_sem_detach(&static_sem);
        return ;
    }

    rt_kprintf("take a staic semaphore, done.\n");

    /* 脱离信号量对象 */
    rt_sem_detach(&static_sem);

    /* 2. dynamic semaphore test */

    tick = rt_tick_get();

    /* 试图持有信号量,最大等待10个OS Tick后返回 */
    result = rt_sem_take(dynamic_sem, 10);
    if (result == -RT_ETIMEOUT)
    {
        /* 超时后判断是否刚好是10个OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_sem_delete(dynamic_sem);
            return ;
        }
        rt_kprintf("take semaphore timeout\n");
    }
    else
    {
        /* 因为没有其他地方释放信号量,所以不应该成功持有信号量,否则测试失败 */
        rt_kprintf("take a dynamic semaphore, failed.\n");
        rt_sem_delete(dynamic_sem);
        return ;
    }

    /* 释放一次信号量 */
    rt_sem_release(dynamic_sem);

    /* 永久等待方式持有信号量 */
    result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功则测试失败 */
        rt_kprintf("take a dynamic semaphore, failed.\n");
        rt_sem_delete(dynamic_sem);
        return ;
    }

    rt_kprintf("take a dynamic semaphore, done.\n");
    /* 删除信号量对象 */
    rt_sem_delete(dynamic_sem);
}

演示了静态、动态信号量的各种操作。例程的运行输出如下:

时间: 2024-10-14 03:48:20

RT-Thread信号量的基本操作的相关文章

RT Thread学习历程(1):串口乱码问题

因为学习实时系统,最近接触到RT Thread. 把RT Thread官网上的示例代码烧录到STM32的板子上之后,在串口软件上接收到的全是乱码,一开始以为是串口软件的问题,换了2个软件之后情况都一样,最后发现是晶振的问题,我用的是STM32F407VGT6,晶振要设为8MHz,代码相应的设置晶振的部分也要修改.

STM32 + RT Thread OS 串口通讯

1.   创建项目 a)   禁用Finsh和console b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因此,在运行scons命令生成项目文件之前,修改rtconfig.h,禁用这两项.(下图L65, L70) c)   生成项目文件 运行scons --target=mdk4 –s 打开生成的项目文件,可以看到,文件组finsh已经不再被包含进来了. d)   创建echo.c 新建一个C文件echo

RT thread 设备驱动之串口设备

本文以stm32f4xx平台介绍串口驱动,主要目的是: 1.RTT中如何编写中断处理程序 2.如何编写RTT设备驱动接口代码 3.了解串行设备的常见处理机制 所涉及的主要源码文件有:usart.c,usart.h,serial.c,serial.h 一.RTT的设备驱动程序概述 编写uart的驱动程序,首先需要了解RTT的设备框架,这里以usart的驱动来具体分析RTT的IO设备管理.注:参考<RTT实时操作系统编程指南> I/O设备管理一章. 我们可以将USART的硬件驱动分成两个部分,如下

优先级反转实验,使用信号量实现【RT-Thread学习笔记 5】

RTOS中很经典的问题.就是在使用共享资源的时候,优先级低的进程在优先级高的进程之前执行的问题.这里模拟这种情况. 下面的实验模拟了优先级反转的情况: 先定义三个线程: //优先级反转实验 rt_sem_t sem; rt_uint32_t t1_count = 0,t2_count = 0,worker_count = 0; rt_thread_t t1,t2,worker ; void pri1_entry(void *parameter) { rt_err_t result; while(

java线程管理

java线程管理 参见: http://harmony.apache.org/subcomponents/drlvm/TM.html 1. 修订历史 2. 关于本文档 2.1. 目的 2.2. 面向的读者 2.3. 文档约定 2.4. 文档使用 3. 概览 3.1. 主要特点 3.2. VM中的线程管理器 3.3. 可移植性 4. 体系结构 4.1. 对外接口 4.1.1. Native 接口 4.1.2. Java* 接口 4.2. 数据结构 4.3. 线程控制结构 4.3.1.Native

Linux系统开发9 线程同步

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统编程8 线程同步 多线程共享资源,不加锁,同步互斥演示 多线程共享资源,加锁,同步互斥演示 读写锁:3个写线程,5个读线程,不加锁,并行处理 读写锁:3个写线程,5个读线程,加读写锁,串行处理 条件变量:生产消费者模型 信号量 进程间锁 文件锁: 习题 死锁,哲学家就餐 多线程共享资源,不加锁,同步互斥演示 [email protected]:~/linux_c/thread$ ca

LwIP学习笔记——STM32 ENC28J60移植与入门

0.前言 去年(2013年)的整理了LwIP相关代码,并在STM32上"裸奔"成功.一直没有时间深入整理,在这里借博文整理总结.LwIP的移植过程细节很多,博文也不可能一一详解个别部分只能点到为止. [本文要点] [1]不带操作系统的LwIP移植,LwIP版本为1.4.1. [2]MCU为STM32F103VE,网卡为ENC28J60. [3]移植过程重点描述ethernetif.c和LwIP宏配置等. [4]一个简单的TCP echo例子. [5]力求简单,没有DHCP功能,甚至没有

多线程的两种实现方式

java中多线程可以采用两种方式实现,分别是继承Thread类重写run方法和实现Runnable接口重写run方法. 继承Thread类重写run方法举例如下: /* 需求:在主线程之外继承Thread类创建两独立线程,分别打印1至50. */ class ThreadTest extends Thread{ public void run(){ for(int i = 1; i <= 50; i++) System.out.println(Thread.currentThread().get

MQTT学习笔记——Yeelink MQTT服务 使用mqtt.js和paho-mqtt

0 前言 2014年8月yeelink推出基于MQTT协议的开关类型设备控制API,相比于基于HTTP RESTful的轮训方式,通过订阅相关主题消息,可以远程控制类应用实时性更好.本文使用两种方式实现开关类型设备的远程控制,一种是基于nodeJS的MQTT.js扩展库,另一种是基于python的paho-mqtt扩展库. [相关博文--MQTT] [MQTT学习笔记--MQTT协议体验 Mosquitto安装和使用] [MQTT学习笔记--树莓派MQTT客户端 使用Mosquitto和paho