信号量
信号量就是你创建一个信号量,给他赋初值,比如1,然后rt_sem_take获取信号量的时候,信号量减1,变成了0,如果为0,再次rt_sem_take会使线程挂起,等待rt_sem_release释放信号量,即加1。
初始化与脱离
静态信号量:
rt_err_t rt_sem_init( rt_sem_t sem, const char* name, rt_uint32_t value, rt_uint8_t flag );//flag:RT_IPC_FLAG_FIFO,RT_IPC_FLAG_PRIO;
rt_err_t rt_sem_detach( rt_sem_t sem );
创建与删除
动态信号量:
rt_sem_t rt_sem_create( const char* name, rt_uint32_t value, rt_uint8_t flag );
rt_err_t rt_sem_delete( rt_sem_t sem );
获取信号量
rt_err_t rt_sem_take( rt_sem_t sem, rt_int32_t time );//第二个参数,正数:等待时间;0:直接返回;-1:一直等待。
rt_err_t rt_sem_trytake( rt_sem_t sem );
释放信号量
rt_err_t rt_sem_release( rt_sem_t sem );
生产者消费者
互斥量
初始化与脱离
静态互斥量:
rt_err_t rt_mutex_init( rt_mutex_t mutex, const char* name, rt_uint8_t flag );//flag:RT_IPC_FLAG_FIFO,RT_IPC_FLAG_PRIO;
rt_err_t rt_mutex_detach( rt_mutex_t mutex );
创建与删除
动态互斥量:
rt_err_t rt_mutex_create( const char* name, rt_uint8_t flag );
rt_err_t rt_mutex_delete( rt_mutex_t mutex );
获取互斥量
rt_err_t rt_mutex_take( rt_mutex_t mutex, rt_int32_t time );//第二个参数,正数:等待时间;0:直接返回;-1:一直等待。
释放互斥量
rt_err_t rt_mutex_release( rt_mutex_t mutex );
优先级翻转
优先级翻转(使用二值信号量会产生):
现有3个线程,线程优先级由高到低为A,B,C。假如低优先级线程C先持有信号量访问共享资源,而高优先级线程A要等待C释放信号量,A访问共享资源肯定是失败的,这时,如果中优先级线程B运行(不访问共享资源),CPU会被B这个比A优先级低的线程给抢占,所以高优先级线程A的实时性得不到保证。这种现象叫优先级翻转。
互斥量的优先级继承算法
互斥量的优先级继承算法:使用互斥量对临界资源的访问,可以把低优先级线程的优先级,拉高至和另一个等待该临界资源的线程同样的优先级,这样继承优先级的线程避免了系统共享资源被任何中间优先级的线程抢占。
信号量与互斥量比较
1)信号量:有限资源的使用数量控制 (停车场-车位)可能有n个线程可执行。
2)互斥量:信号量+锁=优先级反转 (篮球运动-球权)只能有一个线程运行。
事件集
事件就是创建一个事件集,一个事件集可以有32个事件,一共32位,每一位代表一个事件,然后发送对应的事件给事件集,如果接收到对应的事件,这里的接收可以OR/AND,接收到随便一个还是都接收到,然后根据等待时间,完成接下来的操作。
接收事件中 rt_uint8_t option:
RT_EVENT_FLAG_OR, RT_EVENT_FLAG_AND , RT_EVENT_FLAG_CLEAR。
邮箱
邮箱中一封邮件的最大长度是 4 字节,所以邮箱能够用于不超过 4 字节的消息传递, 当传送的消息长度大于这个数目时就不能再采用邮箱的方式。
消息队列
消息队列可以应用于发送不定长消息的场合,包括线程与线程间的消息交换,以及中断服务例程中 发送给线程的消息(中断服务例程不可能接收消息)。
void * msg_pool//消息队列的起始地址
rt_uint16_t msg_size//每条消息的消息大小
rt_uint16_t max_msgs//最大消息数
/*max_msgs = sizeof(msg_pool)/( msg_size + 4(链表指针大小) ); 其中msg_size与rtconfig.h中的#define RT_ALIGN_SIZE 4 有关,例如,msg_size为1,则计算时要算为4,msg_size为5,计算时要算为8*/
发送消息会一个一个放在链表尾部,但其中紧急消息会放在链表头,接收消息从链表头接收。
定时器
定时器管理接口
rt_uint8_t flag;
RT-Thread的定时器提供两类定时器机制:第一类是单次触发定时器RT_TIMER_FLAG_ONE_SHOT,这类定时器在启动后只会触发一次定时器事件, 然后定时器自动停止。第二类是周期触发定时器RT_TIMER_FLAG_PERIODIC,这类定时器会周期性的触发定时器事件, 直到用户手动的停止,否则将永远持续执行下去。
另外,根据超时函数执行时所处的上下文环境,RT-Thread的定时器可以分为软件定时器和硬件定时器。 硬件定时器的超时函数在中断上下文环境中执行,可以在初始化/创建定时器时使用参数RT_TIMER_FLAG_HARD_TIMER来指定。 软件定时器的超时函数在timer线程的上下文环境中执行。可以在初始化/创建定时器时使用参数RT_TIMER_FLAG_SOFT_TIMER来指定。
内存池管理
内存池(Memory Pool)是一种内存分配方式,用于分配大量大小相同的小内存块。 它可以极大地加快内存分配与释放的速度,且能尽量避免内存碎片化。当内存池为空时, 可以阻止分配的线程(或者立即返回,或者等待一段时间返回,这由timeout参数确定)。 当其他线程向此内存池释放内存块时,被阻塞的线程将被唤醒。
内存池中内存块的数目:
rt_mp_init(&mp, "mp1", &mempool[0], sizeof(mempool), 80);//80内存块大小,都要优化成4的整数倍,内存块数目= sizeof(mempool)/(80 + 4);4是链表指针大小