rt-thread操作系统的IPC(Inter-Process Communication,进程间通信)包含有信号量,互斥锁,事件,邮箱,消息队列.
本文主要针对信号量.信号量是用来解决线程同步和互斥的通用工具,和互斥量类似,信号量也可用作资源互斥访问,但信号量没有所有者的概念,在应用上比互斥量更广泛。信号量比较简单,不能解决优先级翻转问题,但信号量是一种轻量级的对象,比互斥量小巧、灵活。因此在很多对互斥要求不严格的系统中(或者不会造成优先级翻转的情况下),经常使用信号量来管理互斥资源。
1 信号量控制块
/**
* Semaphore structure
*/
struct rt_semaphore
{
struct rt_ipc_object parent; /**< inherit from ipc_object *///派生自IPC对象
rt_uint16_t value; /**< value of semaphore. *///信号量计数器
};
typedef struct rt_semaphore *rt_sem_t;
value为信号计数器,此信号量多次被释放时将会累加,在被获取时则将减1,当其值为0时,再请求获取的线程将会被挂起到挂起链表中。
parent为一rt_ipc_object即IPC对象,其定义如下:
/**
* Base structure of IPC object
*/
struct rt_ipc_object
{
struct rt_object parent; /**< inherit from rt_object *///可知其派生自内核对象
rt_list_t suspend_thread; /**< threads pended on this resource *///线程挂起链表
};
从rt_ipc_object的定义结构可知其派生自rt_object结构,即内核对象的定义(参考http://blog.csdn.net/flydream0/article/details/8568463),而其它IPC,如互斥锁,事件,邮箱,消息队列都是从rt_ipc_object派生。
另外,IPC对象还包含一挂起链表,用来保存因此IPC对象而挂起的线程.
2 信号量的创建与初始化
2.1 初始化
/**
* This function will initialize a semaphore and put it under control of
* resource management.
*
* @param sem the semaphore object
* @param name the name of semaphore
* @param value the init value of semaphore
* @param flag the flag of semaphore
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_sem_init(rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag)
{
RT_ASSERT(sem != RT_NULL);
/* init object */
rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);//初始化信号量的内核对象
/* init ipc object */
rt_ipc_object_init(&(sem->parent));//初始化信号量的IPC对象
/* set init value */
sem->value = value;//设置信号量计数器的值
/* set parent */
sem->parent.parent.flag = flag;//设置信号量的内核对象的标志
return RT_EOK;
}
其中rt_object_init已在之前介绍rt-thread的内核对象中相关文章中已有介绍(参见: http://blog.csdn.net/flydream0/article/details/8568463),rt_ipc_object_init函数见如下:
/**
* @addtogroup IPC
*/
/*@{*/
/**
* This function will initialize an IPC object
*
* @param ipc the IPC object
*
* @return the operation status, RT_EOK on successful
*/
rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc)
{
/* init ipc object */
rt_list_init(&(ipc->suspend_thread));//初始化线程挂起链表
return RT_EOK;
}
初始化及创建信号量很简单,一个是静态初始化,一个是动态分配的然后再初始化,不做过多解释.
2.2 创建信号量
/**
* This function will create a semaphore from system resource
*
* @param name the name of semaphore
* @param value the init value of semaphore
*