管理员相当于信号量 ,空车位个数为信号量的值 车辆相当于线程
关于IPC讲解参考
https://www.cnblogs.com/freyluo/p/10986664.html
信号量控制块结构体
//semaphore 信号量
struct rt_semaphore//
{
struct rt_ipc_object parent; /**< inherit from ipc_object */
rt_uint16_t value; /**< value of semaphore. */
};
typedef struct rt_semaphore *rt_sem_t;
定义静态信号量:struct rt_semaphore static_sem;
定义动态信号量: rt_sem_t dynamic_sem;//定义一个信号量控制块指针,之后可以通过动态创建的方法创建一个信号量控制块,并将信号量控制块指针返回赋值给该指针。
初始化与脱离 是对静态信号量来说的 需要以下API 函数
1.初始化信号量:
rt_err_t rt_sem_init ( rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag
)
解释参见RT-thread API参考手册 :
该函数将初始化信号量并将其置于内核管理器的控制之下。
sem | 指定的信号量对象句柄 ------静态信号量的指针 |
name | 信号量的名称 |
value | 信号量初始化时的值 |
flag | 信号量的标志位 -----信号量的标志,可选(RT_IPC_FLAG_FIFO、RT_IPC_FLAG_PRIO) |
备注:RT_IPC_FLAG_FIFO 等待的线程按照先进先出的方式排队,先进入等待列表的线程,优先获得信号量
RT_IPC_FLAG_PRIO) 线程 按照优先级的方式排队等候
脱离信号量
rt_err_t rt_sem_detach ( rt_sem_t sem )
作用:脱离静态信号量 该函数将把指定的静态信号量从内核对 象管理器中移除。(如果不在使用xx静态信号量的时候可调用该函数)
参数:
sem | 指定的信号量对象 |
返回
脱离成功返回 RT_EOK
对动态信号量的操作需要 rt_err_t rt_sem_creat(); rt_err_t rt_sem_detech();
创建动态信号量
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)
创建信号量(动态的申请内存空间,会返回semaphore的指针值, 如果不为null 则创建成功)
调用该函数时,系统将先从对象管理器中分配一个semaphore对象,并初始化这个对象, 然后初始化 IPC 对象以及与 semaphore 相关的部分。
rt_err_t rt_sem_delete(rt_sem_t sem)
删除信号量
系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。 调用该函数将删除一个信号量对象,并释放其占用的内存空间
参数
sem | 信号量指针 |
返回
RT_EOK删除成功
获取信号量
rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
通过take函数 rt_sem_take获取信号量指向的资源 ,当信号量的值大于0.线程成功获得信号量,然后value的值-1,
当调用 take函数 rt_sem_take;信号量的值=0,信号量所指向的共享资源不可用,申请该信号量的线程,会根据take参数做出相应的动作, t=0 立即返回, t>0 按照时间等待 ,t是根据系统的滴答时钟为计数单位,(t*一个滴答时钟周期) 。t<0 线程永远在
信号量上等待
#define RT_WAITING_FOREVER -1 /**< Block forever until get resource. */
无等待获取信号量-----时间参数为0 的rt_sem_take
rt_err_t rt_sem_trytake(rt_sem_t sem)//无时间参数
{
return rt_sem_take(sem, 0);
}
rt_sem_trytake 获取到或则获取不到就立马返回, 不去做 任何等待
当用户不想在申请的信号量上挂起线程进行等待时,可以调用该函数以无等待方式获取信号量
备注: take 函数可以导致线程挂起 ,只能在线程中调用 不能在中断中调用(ISR)
rt_err_t rt_sem_release(rt_sem_t sem)
REALSE 函数 , 不会导致线程挂起 ,能在线程中调用 也能在中断中调用(ISR)
/*
* 程序清单:信号量例程
*
* 该例程创建了一个动态信号量,初始化两个线程,线程1在count每计数10次时,
* 发送一个信号量,线程2在接收信号量后,对number进行加1操作
*/
#include <rtthread.h>
#define THREAD_PRIORITY 25
#define THREAD_TIMESLICE 5
/* 指向信号量的指针 */
static rt_sem_t dynamic_sem = RT_NULL;
//这样低位全是0,可以在特殊场合,增加寻址范围等。
ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
static void rt_thread1_entry(void *parameter)
{
static rt_uint8_t count = 0;
while(1)
{
if(count <= 100)
{
count++;
}
else
return;
/* count每计数10次,就释放一次信号量 */
if(0 == (count % 10))
{
rt_kprintf("t1 release a dynamic semaphore.\n" );
rt_sem_release(dynamic_sem);
}
}
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
static void rt_thread2_entry(void *parameter)
{
static rt_err_t result;
static rt_uint8_t number = 0;
while(1)
{
/* 永久方式等待信号量,获取到信号量,则执行number自加的操作 */
result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);
if (result != RT_EOK)
{
rt_kprintf("t2 take a dynamic semaphore, failed.\n");
rt_sem_delete(dynamic_sem);
return;
}
else
{
number++;
rt_kprintf("t2 take a dynamic semaphore. number = %d\n" ,number);
}
}
}
/* 信号量示例的初始化 */
int semaphore_sample()
{
/* 创建一个动态信号量,初始值是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;
}
else
{
rt_kprintf("create done. dynamic semaphore value = 0.\n");
}
rt_thread_init(&thread1,
"thread1",
rt_thread1_entry,
RT_NULL,
&thread1_stack[0],
sizeof(thread1_stack),
THREAD_PRIORITY, THREAD_TIMESLICE);
rt_thread_startup(&thread1);
rt_thread_init(&thread2,
"thread2",
rt_thread2_entry,
RT_NULL,
&thread2_stack[0],
sizeof(thread2_stack),
THREAD_PRIORITY-1, THREAD_TIMESLICE);
rt_thread_startup(&thread2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(semaphore_sample, semaphore sample);