4.IPC之訊號量 //依據RT-Thread核心程式設計的學習記錄(非核心實現)
阿新 • • 發佈:2018-12-11
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; }
裡面的程式碼,按照需要看是否註釋某些部分。