4.IPC之信号量 //依据RT-Thread内核编程的学习记录(非内核实现)

IPC: Inter proess communication   大的任务中的各任务信息交互配合,内容包括信号量互斥锁消息队列邮箱,事件
    本篇文章,只讨论第一个内容,信号量

1.信号量的创建

和线程的创建方式类似,信号量的创建也分动态dynamic和静态static的分别,分别由两个函数实现。

/*静态信号量的线程控制块*/
static struct rt_semaphore static_sem;
/*指向动态信号量的指针*/
static rt_sem_t dynamic_sem;

/*静态创建*/
rt_sem_init(&static_sem,"name","number",“time”);
/*动态创建*/
dynamic_sem = rt_sem_creat("name","number",“time”);

"number"是设置信号量的初始值,如果设置为0就证明没有可以用得信号量,只有等待信号量被释放才能获取到信号量。

具体内容可以参看文末的例程。

2.信号量的获取和释放

/*信号量的获取函数*/
rt_sem_take(xx,"waitting time");

/*信号量的释放函数*/
rt_sem_release(xx);

rt_sem_take()函数会有一个返回值,我们一般不对这个返回值忽略,因为这个函数中包含rt_schedule()片段,"waiting time"参数可以设置为你需要等待的时间,当然不能超出rt_uint32_t的数据限制,超出等待时间后,获取失败的反馈,向下一段函数执行;也可以设置为RT_WARTING_FOREVER,用来一直获取信号量,除非获取到信号量才开始向下一段函数执行。

rt_sem_release()函数中,也包含rt_schedule()片段。而且是刚释放完一个信号量,便开启任务调度。所以在这两个线程中,你基本没有发现rt_thread_delay()类似的任务挂起的函数,而且两个任务都可以正常的完成,原因就在于此。

 

3.信号量的删除

/*删除静态函数*/
rt_sem_detach();

/*删除动态函数*/
rt_sem_delete();

有创建就会有删除,删除函数也是类似的。

4.例程

#include <rtthread.h>

#define THREAD_PRIORITY         25
#define THREAD_TIMESLICE        5

/* 指向信号量的指针 */
static rt_sem_t dynamic_sem = RT_NULL;
/* 指向信号量的线程控制块 */
static struct rt_semaphore static_sem;

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);
        rt_sem_release(&static_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, 100);
//        result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);//一直等待
            result = rt_sem_take(&static_sem, 100);
//        result = rt_sem_take(&static_sem, RT_WAITING_FOREVER);
        if (result != RT_EOK)
        {        
            rt_kprintf("t2 take a dynamic semaphore, failed.\n");
//            rt_sem_delete(dynamic_sem);
						rt_sem_detach(&static_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");
//    }
		
		/* 初始化一个静态信号量,初始值是0 */
		rt_err_t result;
		result = rt_sem_init(&static_sem,"ssem",0,RT_IPC_FLAG_FIFO);
		if(RT_EOK != result)
		{
			rt_kprintf("init static semaphore failed.\n");
			return -1;
		}
		else
		{
				rt_kprintf("init done static 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;
}

里面的代码,按照需要看是否注释某些部分。

猜你喜欢

转载自blog.csdn.net/xiangxistu/article/details/82810603
今日推荐