信號(hào)量是線程間同步的一種方式。在rtthread中用于線程間同步的還有互斥量和事件集。
什么是進(jìn)程間同步,簡(jiǎn)單點(diǎn)的類比就是工廠中的生產(chǎn)線,如果想要執(zhí)行B工序就必須等待A工序的完成,那么工序A和工序B就是同步的關(guān)系,在程序中也是一樣。只不過(guò)是工序變成了線程。在RTThread的文檔里有這樣的描述:同步是指按預(yù)定的先后次序進(jìn)行運(yùn)行,線程同步是指多個(gè)線程通過(guò)特定的機(jī)制(如互斥量,事件對(duì)象,臨界區(qū))來(lái)控制線程之間的執(zhí)行順序,也可以說(shuō)是在線程之間通過(guò)同步建立起執(zhí)行順序的關(guān)系,如果沒(méi)有同步,那線程之間將是無(wú)序的。
然后就是解釋一下信號(hào)量,一個(gè)經(jīng)典的解釋
以生活中的停車場(chǎng)為例來(lái)理解信號(hào)量的概念:
①當(dāng)停車場(chǎng)空的時(shí)候,停車場(chǎng)的管理員發(fā)現(xiàn)有很多空車位,此時(shí)會(huì)讓外面的車陸續(xù)進(jìn)入停車場(chǎng)獲得停車位;
②當(dāng)停車場(chǎng)的車位滿的時(shí)候,管理員發(fā)現(xiàn)已經(jīng)沒(méi)有空車位,將禁止外面的車進(jìn)入停車場(chǎng),車輛在外排隊(duì)等候;
③當(dāng)停車場(chǎng)內(nèi)有車離開(kāi)時(shí),管理員發(fā)現(xiàn)有空的車位讓出,允許外面的車進(jìn)入停車場(chǎng);待空車位填滿后,又禁止外部車輛進(jìn)入。
在此例子中,管理員就相當(dāng)于信號(hào)量,管理員手中空車位的個(gè)數(shù)就是信號(hào)量的值(非負(fù)數(shù),動(dòng)態(tài)變化);停車位相當(dāng)于公共資源(臨界區(qū)),車輛相當(dāng)于線程。車輛通過(guò)獲得管理員的允許取得停車位,就類似于線程通過(guò)獲得信號(hào)量訪問(wèn)公共資源。
最后信號(hào)量的使用。其實(shí)如果不追究?jī)?nèi)核的話,操作系統(tǒng)只需要調(diào)用api就可以了。具體就是創(chuàng)建信號(hào)量(rt_sem_create)、刪除信號(hào)量(rt_sem_delete)獲取信號(hào)量( rt_sem_take)、釋放信號(hào)量( rt_sem_release)詳細(xì)使用手冊(cè)可以參考這里
接下來(lái)就是一個(gè)實(shí)驗(yàn),使用信號(hào)量控制LED以500ms的間隔閃爍。
思路:使用一個(gè)定時(shí)器:每500毫秒釋放一次信號(hào)量,在創(chuàng)建一個(gè)線程用來(lái)反轉(zhuǎn)LED燈,當(dāng)有信號(hào)量的時(shí)候就執(zhí)行反轉(zhuǎn)LED燈。
程序部分
/* defined the LED0 pin: PB1 */
#define LED0_PIN GET_PIN(H, 11)
//定義信號(hào)量
static rt_sem_t led_sem = RT_NULL;
//定義線程
static char led_stack[512];
static struct rt_thread led_thread;
//定時(shí)器定義
static rt_timer_t timer_res;
void task_init(void); //線程初始化函數(shù)
static void led_entry(void *parameter);//LED反轉(zhuǎn)線程
static void timer(void *parameter);//定時(shí)器任務(wù)
int main(void)
{
/* set LED0 pin mode to output */
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
task_init();
while (1)
{
rt_thread_mdelay(1000);
}
}
void task_init(void)
{
/* 創(chuàng)建一個(gè)動(dòng)態(tài)信號(hào)量,初始值是 0,先進(jìn)先出*/
led_sem = rt_sem_create("led on sem", 0, RT_IPC_FLAG_FIFO);
if (led_sem == RT_NULL)
{
rt_kprintf("create led on semaphore failed.n");
return ;
}
//靜態(tài)創(chuàng)建任務(wù)
rt_thread_init(&led_thread, //線程句柄
"led on", //線程的描述
led_entry, //線程入口函數(shù)
RT_NULL, //線程入口參數(shù)
&led_stack[0],//線程的棧的起始地址
sizeof(led_stack),//線程的棧大小
3, 10);//線程的優(yōu)先級(jí)和時(shí)間片大小
rt_thread_startup(&led_thread);//啟動(dòng)線程
timer_res = rt_timer_create("led sem",//定時(shí)器描述
timer,//定時(shí)器入口函數(shù)
RT_NULL,//定時(shí)器入口參數(shù)
500,//定時(shí)時(shí)間
RT_TIMER_FLAG_PERIODIC);//循環(huán)
if(timer_res != RT_NULL)
{
rt_timer_start(timer_res);//定時(shí)器開(kāi)始
rt_kprintf("timer start. n");
}
}
static void timer(void *parameter)
{
rt_sem_release(led_sem);//釋放信號(hào)量
}
static void led_entry(void *parameter)
{
while(1)
{
/*以永遠(yuǎn)阻塞的形式等待信號(hào)量*/
if(rt_sem_take (led_sem, RT_WAITING_FOREVER) == RT_EOK)
{
HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_11);//反轉(zhuǎn)LED
rt_kprintf("led toggle.tick:%d n",rt_tick_get());
}
}
}
下面就是運(yùn)行結(jié)果
-
led燈
+關(guān)注
關(guān)注
22文章
1592瀏覽量
107841 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3237瀏覽量
114475 -
GPIO
+關(guān)注
關(guān)注
16文章
1196瀏覽量
51919 -
信號(hào)量
+關(guān)注
關(guān)注
0文章
53瀏覽量
8314 -
RTThread
+關(guān)注
關(guān)注
8文章
132瀏覽量
40811
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論