1. 程式人生 > >4.IPC之訊號量 //依據RT-Thread核心程式設計的學習記錄(非核心實現)

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”);
/*動態建立*/
rt_sem_creat(dynamic_sem,"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;
}

裡面的程式碼,按照需要看是否註釋某些部分。