消息队列,遵从先进先出的原则,我们利用正点原子的水星开发板STM32F767IG为实验开发板,进行RT-Thread操作系统的消息队列实验。
static rt_thread_t receive_thread=RT_NULL;
static rt_thread_t send_thread=RT_NULL;
static rt_mq_t test_mq=RT_NULL;
static void receive_thread_entry(void* parameter);
static void send_thread_entry(void* parameter);
int main(void)
{
rt_pin_mode(KEY0_PIN,PIN_MODE_INPUT);
rt_pin_mode(KEY1_PIN,PIN_MODE_INPUT);
test_mq = rt_mq_create("test_mq",4,20,RT_IPC_FLAG_FIFO);
if(test_mq!=RT_NULL)
{
rt_kprintf("megass success\r\n");
}
receive_thread = rt_thread_create("receive",receive_thread_entry,RT_NULL,512,17,20);
if(receive_thread!=RT_NULL)
{
rt_thread_startup(receive_thread);
}
send_thread=rt_thread_create("send",send_thread_entry,RT_NULL,512,18,20);
if(send_thread!=RT_NULL)
{
rt_thread_startup(send_thread);
}
}
static void receive_thread_entry(void* parameter)
{
rt_err_t uwRet=RT_EOK;
uint32_t r_queue;
while (1)
{
uwRet=rt_mq_recv(test_mq,&r_queue,sizeof(r_queue),RT_WAITING_FOREVER);
if(uwRet==RT_EOK)
{
rt_kprintf("receive:%d\r\n",r_queue);
}
else
{
rt_kprintf("receive fail\r\n");
}
}
}
static void send_thread_entry(void* parameter)
{
rt_err_t uwRet=RT_EOK;
uint32_t send_data1=1;
uint32_t send_data2=2;
while (1)
{
if (rt_pin_read(KEY0_PIN))
{
while (rt_pin_read(KEY0_PIN))
{
/* code */
}
rt_kprintf("key0 press\r\n");
uwRet =rt_mq_send(test_mq,&send_data1,sizeof(send_data1));
if(uwRet!=RT_EOK)
{
rt_kprintf("fail\r\n");
}
/* code */
}
if(rt_pin_read(KEY1_PIN))
{
while (rt_pin_read(KEY1_PIN))
{
/* code */
}
rt_kprintf("key1 press\r\n");
uwRet =rt_mq_send(test_mq,&send_data2,sizeof(send_data2));
if(uwRet!=RT_EOK)
{
rt_kprintf("fail\r\n");
}
}
rt_thread_delay(10);
}
}
对于这两个线程我们可以使接受的线程的优先级大于发送函数的优先级,就会出现每按一下按键就会接收到对应的信息。
然后再修改发送和接受函数的优先级,使得发送的优先级大于发送的优先级。就会出现在两个按键全部按下就会出现俩条消息全部接收。
信号量是一种用于解决线程间同步问题的内核对象,线程可以获取和释放它,从而达到同步和互斥的目的。信号量就像一把钥匙,把一段临界去锁住,只允许有钥匙的线程进行访问,线程拿到了钥匙,才允许他进入临界区,而离开后把钥匙传递给排队在后面的等待线程,让后续线程依次进入临界区,当然这会出现一个小小的问题,就是一个优先级低的线程一直拿着这把钥匙,就是不给你优先级高的线程,让你干等着,我优先级低的一直在这里得瑟,就是不给你,对于创造这个操作系统的工程师怎么可能会允许你一直在这里得瑟,我要制裁你这种行为,当然这已经属于互斥量的问题领域了,我们还是先讲信号量,信号量被人分为二值信号量和计数信号量,我们这里只讲二值信号量,因为他们两个几乎相同,只讲一个就可以了。
static rt_thread_t receive_thread=RT_NULL;
static rt_thread_t send_thread=RT_NULL;
static rt_sem_t test_sem =RT_NULL;
static void receive_thread_entry(void* parameter);
static void send_thread_entry(void* parameter);
int main(void)
{
test_sem=rt_sem_create("test_sem",1,RT_IPC_FLAG_FIFO);
if(test_sem!=RT_NULL)
{
rt_kprintf("sem success\r\n");
}
receive_thread =rt_thread_create("receive",receive_thread_entry,RT_NULL,512,2,20);
if(receive_thread!=RT_NULL)
{
rt_thread_startup(receive_thread);
rt_kprintf("receive success\r\n");
}
send_thread=rt_thread_create("send",send_thread_entry,RT_NULL,512,3,20);
if(send_thread!=RT_NULL)
{
rt_thread_startup(send_thread);
rt_kprintf("send success\r\n");
}
}
static void receive_thread_entry(void* parameter)
{
while (1)
{
rt_sem_take(test_sem,RT_WAITING_FOREVER);
if(ucValue[0]==ucValue[1])
{
rt_kprintf("successful\r\n");
}
rt_sem_release(test_sem);
rt_thread_delay(1000);
}
}
static void send_thread_entry(void* parameter)
{
while (1)
{
rt_sem_take(test_sem,RT_WAITING_FOREVER);
ucValue[0]++;
rt_thread_delay(100);
ucValue[1]++;
rt_sem_release(test_sem);
rt_thread_yield();
}
}
这样我们就可以看见串口一直打印successful。
学习完信号量我们就开始学习互斥量,估计大家看完我上面写的信号量,怕都不使用信号量了,其实只要用的得当,就不会出现这样的问题,要不然互斥量干脆干掉信号量算了,信号量之所以有,肯定有好处的。其实互斥量也属于信号量,是一种相互排斥的信号量,是一种特殊的二值信号量,他和信号量不同的是,他支持互斥量的所有权,递归访问以及优先级翻转的特性。
当然在这里我给大家分享一个学习清华北大课程的好网站,可以让你直接不花钱就学习清华北大的优秀课程。