抽象的来讲,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为 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