www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > > strongerHuang
[導(dǎo)讀]隊(duì)列(queue)是一種只能在一端插入元素、在另一端刪除元素的數(shù)據(jù)結(jié)構(gòu),遵循先入先出(FIFO)的規(guī)則。


轉(zhuǎn)自 | Mculover666

1. 知識(shí)點(diǎn)回顧

隊(duì)列(queue)是一種只能在一端插入元素、在另一端刪除元素的數(shù)據(jù)結(jié)構(gòu),遵循先入先出(FIFO)的規(guī)則。

環(huán)形隊(duì)列(ring queue)可以方便的重復(fù)利用這段內(nèi)存空間,同樣遵循先入先出(FIFO)的規(guī)則。

優(yōu)先級(jí)隊(duì)列(prio queue)不遵循FIFO,而是根據(jù)元素的優(yōu)先級(jí)進(jìn)行出隊(duì),優(yōu)先級(jí)最高的先出隊(duì)。

「本文的所有內(nèi)容都是基于這兩個(gè)數(shù)據(jù)結(jié)構(gòu)」,TencentOS-tiny中環(huán)形隊(duì)列和優(yōu)先級(jí)隊(duì)列的實(shí)現(xiàn)和使用示例請(qǐng)閱讀文章:

  • 數(shù)據(jù)結(jié)構(gòu) | TencentOS-tiny中隊(duì)列、環(huán)形隊(duì)列、優(yōu)先級(jí)隊(duì)列的實(shí)現(xiàn)及使用

2. 消息隊(duì)列

2.1. 什么是消息隊(duì)列

消息隊(duì)列,Message Queue,顧名思義包含兩部分:消息+隊(duì)列,或者可以理解為消息的隊(duì)列。

① 消息是什么?

兩個(gè)不同的任務(wù)之間傳遞數(shù)據(jù)時(shí),這個(gè)數(shù)據(jù)就稱之為消息,這個(gè)消息可以是一個(gè)整型值,浮點(diǎn)值,甚至一個(gè)結(jié)構(gòu)體,一個(gè)指針……所以,在使用不同的RTOS的消息隊(duì)列時(shí),「一定要注意傳遞的是值還是該值的地址」。

傳遞值的缺點(diǎn)是值的長度有大有小,導(dǎo)致整個(gè)消息隊(duì)列的長度有大有小。

一個(gè)指針的長度是固定的4字節(jié),傳遞值的時(shí)候,無論值是什么類型,只傳遞該值的地址。

傳遞地址當(dāng)然也有缺陷,當(dāng)動(dòng)態(tài)任務(wù)task1中定義了一個(gè)局部變量,然后把該局部變量的地址傳給了task2,隨即task1因?yàn)槟撤N原因被銷毀,內(nèi)存回收,導(dǎo)致指向該局部變量的指針變?yōu)橐爸羔?,非常危險(xiǎn),不過不用慌,小問題,在編程的時(shí)候注意避免即可。

「在TencentOS-tiny中,消息隊(duì)列中傳遞的消息指的是地址,郵箱隊(duì)列傳遞的消息是值」。

② 隊(duì)列是什么?

消息隊(duì)列如果底層使用環(huán)形隊(duì)列存儲(chǔ)消息,則成為消息隊(duì)列,遵循:先送入的消息先被取出。

消息隊(duì)列如果底層使用優(yōu)先級(jí)隊(duì)列存儲(chǔ)消息,則成為優(yōu)先級(jí)消息隊(duì)列,遵循:優(yōu)先級(jí)最高的消息最先被取出。

「在TencentOS-tiny中,這兩種消息隊(duì)列都有,下面一一講述?!?/span>

③ pend-post機(jī)制

無論是什么隊(duì)列,都存在兩種情況:當(dāng)隊(duì)列滿了的時(shí)候,元素再入隊(duì)會(huì)發(fā)生錯(cuò)誤;當(dāng)隊(duì)列為空的時(shí)候,元素出隊(duì)同樣會(huì)發(fā)生錯(cuò)誤。

這種問題可以巧妙的在隊(duì)列基礎(chǔ)之上用pend-post機(jī)制解決,即等待-釋放機(jī)制。

當(dāng)隊(duì)列「滿了」的時(shí)候,前來入隊(duì)的task1可以選擇pend一段時(shí)間或者永久等待,「一旦有元素被task2出隊(duì)」,調(diào)用post釋放一個(gè)信號(hào),「喚醒等待中的task1」。

同樣,當(dāng)隊(duì)列「空了」的時(shí)候,前來出隊(duì)的task1可以選擇pend一段時(shí)間或者永久等待,「一旦有元素被task2入隊(duì)」,調(diào)用post釋放一個(gè)信號(hào),「喚醒等待中的task1」。

是不是很巧妙?

接下來上源碼!上Demo!一看便知~

2.2. 消息隊(duì)列的實(shí)現(xiàn)

TencentOS-tiny中消息隊(duì)列的實(shí)現(xiàn)在 tos_message_queue.h和tos_message_queue.c中。

typedef struct k_message_queue_st { knl_obj_t knl_obj; pend_obj_t pend_obj; k_ring_q_t ring_q;
} k_msg_q_t;

一個(gè)pend_obj對(duì)象用來實(shí)現(xiàn)pend-post機(jī)制,一個(gè)ring_q環(huán)形隊(duì)列用來存儲(chǔ)消息。

是不是和我講述的沒錯(cuò)?學(xué)透了之后,其實(shí)一切都沒有那么神秘的~

再來看看從消息隊(duì)列中獲取消息的API實(shí)現(xiàn):

__API__ k_err_t tos_msg_q_pend(k_msg_q_t *msg_q, void **msg_ptr, k_tick_t timeout) { //省略了部分源碼 TOS_CPU_INT_DISABLE(); if (tos_ring_q_dequeue(&msg_q->ring_q, msg_ptr, K_NULL) == K_ERR_NONE) {
        TOS_CPU_INT_ENABLE(); return K_ERR_NONE;
    }
    pend_task_block(k_curr_task, &msg_q->pend_obj, timeout);
    TOS_CPU_INT_ENABLE();
    knl_sched(); return err;
}

向消息隊(duì)列中存放消息的API實(shí)現(xiàn)如下:

__STATIC__ k_err_t msg_q_do_post(k_msg_q_t *msg_q, void *msg_ptr, opt_post_t opt) { //省略了部分源碼 TOS_CPU_INT_DISABLE(); if (pend_is_nopending(&msg_q->pend_obj)) {
        err = tos_ring_q_enqueue(&msg_q->ring_q, &msg_ptr, sizeof(void*)); if (err != K_ERR_NONE) {
            TOS_CPU_INT_ENABLE(); return err;
        }
        TOS_CPU_INT_ENABLE(); return K_ERR_NONE;
    } if (opt == OPT_POST_ONE) {
        msg_q_task_recv(TOS_LIST_FIRST_ENTRY(&msg_q->pend_obj.list, k_task_t, pend_list), msg_ptr);
    } else { // OPT_POST_ALL TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &msg_q->pend_obj.list) {
            msg_q_task_recv(task, msg_ptr);
        }
    }
    TOS_CPU_INT_ENABLE();
    knl_sched(); return K_ERR_NONE;
}

從源碼中可以看到,如果opt標(biāo)志為 OPT_POST_ONE,表示喚醒一個(gè),則喚醒該消息隊(duì)列等待列表上任務(wù)優(yōu)先級(jí)最高的那個(gè);如果opt標(biāo)志為 OPT_POST_ALL,則全部喚醒。

2.3. 消息隊(duì)列的使用示例

#define MESSAGE_MAX     10 uint8_t msg_pool[MESSAGE_MAX * sizeof(void *)]; k_msg_q_t msg_q; void entry_task_receiver(void *arg) { k_err_t err; void *msg_received; while (K_TRUE) {
        err = tos_msg_q_pend(&msg_q, &msg_received, TOS_TIME_FOREVER); if (err == K_ERR_NONE) { printf("receiver: msg incoming[%s]\n", (char *)msg_received);
        }
    }
} void entry_task_sender(void *arg) { char *msg_prio_0 = "msg 0 without priority"; char *msg_prio_1 = "msg 1 without priority"; char *msg_prio_2 = "msg 2 without priority"; printf("sender: post a message 2 without priority\n");
    tos_msg_q_post(&msg_q, msg_prio_2); printf("sender: post a message 1 without priority\n");
    tos_msg_q_post(&msg_q, msg_prio_1); printf("sender: post a message 0 without priority\n");
    tos_msg_q_post(&msg_q, msg_prio_0);
}

執(zhí)行結(jié)果如下:

TencentOS-tiny Port on STM32L431RCT6 By Mculover666
sender: post a message 2 without priority
sender: post a message 1 without priority
sender: post a message 0 without priority
receiver: msg incoming[msg 2 without priority]
receiver: msg incoming[msg 1 without priority]
receiver: msg incoming[msg 0 without priority]

3. 優(yōu)先級(jí)消息隊(duì)列

3.1. 優(yōu)先級(jí)消息隊(duì)列的實(shí)現(xiàn)

實(shí)現(xiàn)和消息隊(duì)列類似,通過在優(yōu)先級(jí)隊(duì)列的基礎(chǔ)上加上pend-post機(jī)制來實(shí)現(xiàn)。

TencentOS-tiny中優(yōu)先級(jí)消息隊(duì)列的實(shí)現(xiàn)在tos_priority_message_queue.h和tos_priority_message_queue.c中。

typedef struct k_priority_message_queue_st { knl_obj_t knl_obj; pend_obj_t pend_obj; void *prio_q_mgr_array; k_prio_q_t prio_q;
} k_prio_msg_q_t;

其中pend_obj用于掛載等待該優(yōu)先級(jí)消息隊(duì)列的任務(wù),prio_q和prio_q_mgr_array合起來實(shí)現(xiàn)優(yōu)先級(jí)隊(duì)列。

消息入隊(duì)和消息出隊(duì)的API實(shí)現(xiàn)與消息隊(duì)列的實(shí)現(xiàn)思想一模一樣,這里不再講解。

3.2. 優(yōu)先級(jí)消息隊(duì)列的使用示例

#define MESSAGE_MAX     10 uint8_t msg_pool[MESSAGE_MAX * sizeof(void *)]; k_prio_msg_q_t prio_msg_q; void entry_task_receiver(void *arg) { k_err_t err; void *msg_received; while (K_TRUE) {
        err = tos_prio_msg_q_pend(&prio_msg_q, &msg_received, TOS_TIME_FOREVER); if (err == K_ERR_NONE) { printf("receiver: msg incoming[%s]\n", (char *)msg_received);
        }
    }
} void entry_task_sender(void *arg) { char *msg_prio_0 = "msg with priority 0"; char *msg_prio_1 = "msg with priority 1"; char *msg_prio_2 = "msg with priority 2"; printf("sender: post a message with priority 2\n");
    tos_prio_msg_q_post(&prio_msg_q, msg_prio_2, 2); printf("sender: post a message with priority 1\n");
    tos_prio_msg_q_post(&prio_msg_q, msg_prio_1, 1); printf("sender: post a message with priority 0\n");
    tos_prio_msg_q_post(&prio_msg_q, msg_prio_0, 0);
}

運(yùn)行結(jié)果如下:

TencentOS-tiny Port on STM32L431RCT6 By Mculover666
sender: post a message with priority 2 sender: post a message with priority 1 sender: post a message with priority 0 receiver: msg incoming[msg with priority 0]
receiver: msg incoming[msg with priority 1]
receiver: msg incoming[msg with priority 2]

將第2節(jié)的結(jié)果和第3節(jié)的結(jié)果對(duì)比,就會(huì)發(fā)現(xiàn)同樣的消息發(fā)送順序,因?yàn)槭褂貌煌南㈥?duì)列,任務(wù)獲取到的消息順序截然不同。

4. 郵箱隊(duì)列

4.1. 不同之處

消息隊(duì)列和郵箱隊(duì)列的不同之處,在于底層隊(duì)列每個(gè)元素類型不一樣,看一眼源碼便知。

消息隊(duì)列傳遞的消息是地址,所以在初始化消息隊(duì)列的時(shí)候,環(huán)形隊(duì)列中每個(gè)元素都是空指針類型:

__API__ k_err_t tos_msg_q_create(k_msg_q_t *msg_q, void *pool, size_t msg_cnt) { //部分源碼省略 //重點(diǎn):隊(duì)列中每個(gè)元素類型大小是sizeof(void*) err = tos_ring_q_create(&msg_q->ring_q, pool, msg_cnt, sizeof(void *)); if (err != K_ERR_NONE) { return err;
    } return K_ERR_NONE;
}

而郵箱隊(duì)列傳遞的是值,所以在初始化底層用到的環(huán)形隊(duì)列時(shí),每個(gè)元素的大小是由用戶指定的:

__API__ k_err_t tos_mail_q_create(k_mail_q_t *mail_q, void *pool, size_t mail_cnt, size_t mail_size) { //省略了部分源碼 //重點(diǎn):每個(gè)元素的大小是mail_size,由用戶傳入?yún)?shù)指定 err = tos_ring_q_create(&mail_q->ring_q, pool, mail_cnt, mail_size); if (err != K_ERR_NONE) { return err;
    } return K_ERR_NONE;
}

4.2. 郵箱隊(duì)列的實(shí)現(xiàn)

這有什么好實(shí)現(xiàn)的~一個(gè)環(huán)形隊(duì)列+pend-post對(duì)象即可。

TencentOS-tiny中郵箱隊(duì)列的實(shí)現(xiàn)在tos_mail_queue.h和tos_mail_queue.c中。

typedef struct k_mail_queue_st { knl_obj_t knl_obj; pend_obj_t pend_obj; k_ring_q_t ring_q; } k_mail_q_t;

是不是沒什么區(qū)別~至于操作的API,更沒啥區(qū)別,不寫了,劃水劃水。

4.3. 郵箱隊(duì)列的使用示例


#define MAIL_MAX    10 typedef struct mail_st { char *message; int payload;
} mail_t; uint8_t mail_pool[MAIL_MAX * sizeof(mail_t)]; k_mail_q_t mail_q; void entry_task_receiver_higher_prio(void *arg) { k_err_t err; mail_t mail; size_t mail_size; while (K_TRUE) {
        err = tos_mail_q_pend(&mail_q, &mail, &mail_size, TOS_TIME_FOREVER); if (err == K_ERR_NONE) {
            TOS_ASSERT(mail_size == sizeof(mail_t)); printf("higher: msg incoming[%s], payload[%d]\n", mail.message, mail.payload);
        }
    }
} void entry_task_receiver_lower_prio(void *arg) { k_err_t err; mail_t mail; size_t mail_size; while (K_TRUE) {
        err = tos_mail_q_pend(&mail_q, &mail, &mail_size, TOS_TIME_FOREVER); if (err == K_ERR_NONE) {
            TOS_ASSERT(mail_size == sizeof(mail_t)); printf("lower: msg incoming[%s], payload[%d]\n", mail.message, mail.payload);
        }
    }
} void entry_task_sender(void *arg) { int i = 1; mail_t mail; while (K_TRUE) { if (i == 2) { printf("sender: send a mail to one receiver, and shoud be the highest priority one\n");
            mail.message = "1st time post";
            mail.payload = 1;
            tos_mail_q_post(&mail_q, &mail, sizeof(mail_t));
        } if (i == 3) { printf("sender: send a message to all recevier\n");
            mail.message = "2nd time post";
            mail.payload = 2;
            tos_mail_q_post_all(&mail_q, &mail, sizeof(mail_t));
        } if (i == 4) { printf("sender: send a message to one receiver, and shoud be the highest priority one\n");
            mail.message = "3rd time post";
            mail.payload = 3;
            tos_mail_q_post(&mail_q, &mail, sizeof(mail_t));
        } if (i == 5) { printf("sender: send a message to all recevier\n");
            mail.message = "4th time post";
            mail.payload = 4;
            tos_mail_q_post_all(&mail_q, &mail, sizeof(mail_t));
        }
        tos_task_delay(1000);
        ++i;
    }
}



運(yùn)行結(jié)果為:


TencentOS-tiny Port on STM32L431RCT6 By Mculover666

sender: send a mail to one receiver, and shoud be the highest priority one
higher: msg incoming[1st time post], payload[1]

sender: send a message to all recevier
higher: msg incoming[2nd time post], payload[2]
lower: msg incoming[2nd time post], payload[2]

sender: send a message to one receiver, and shoud be the highest priority one
higher: msg incoming[3rd time post], payload[3]

sender: send a message to all recevier
higher: msg incoming[4th time post], payload[4]
lower: msg incoming[4th time post], payload[4]


此示例主要演示了兩點(diǎn):1. 如何使用郵箱隊(duì)列直接傳遞值;2. 喚醒一個(gè)等待任務(wù)和喚醒所有等待任務(wù)的區(qū)別。

5. 優(yōu)先級(jí)郵箱隊(duì)列

看到這里,這個(gè)不能再講了吧~

TencentOS-tiny中實(shí)現(xiàn)在tos_priority_mail_queue.c和tos_priority_mail_queue.h中。

可以自己嘗試根據(jù)前面的demo,編寫出一個(gè)使用優(yōu)先級(jí)郵箱隊(duì)列的demo,測試高優(yōu)先級(jí)的郵件是否會(huì)被先收到,然后將結(jié)果與第4節(jié)的實(shí)驗(yàn)結(jié)果進(jìn)行對(duì)比。

越到文末我越浪,劃水已經(jīng)不能滿足了,博主要去摸魚~

6. 總結(jié)

按照慣例,對(duì)本文所講的內(nèi)容進(jìn)行一個(gè)總結(jié)。

本文主要講述了用于任務(wù)間通信的一些內(nèi)核對(duì)象,主要有四個(gè):消息隊(duì)列和優(yōu)先級(jí)消息隊(duì)列,郵箱隊(duì)列和優(yōu)先級(jí)郵箱隊(duì)列。

接下來列出一些重要的點(diǎn):

「在使用RTOS中的一些用于任務(wù)間通信的量時(shí),要注意傳遞的是值還是地址。TencentOS-tiny中消息隊(duì)列傳輸?shù)氖堑刂?,而郵箱隊(duì)列傳遞的是值?!?/span>

「消息隊(duì)列和郵箱隊(duì)列基于環(huán)形隊(duì)列實(shí)現(xiàn),遵循FIFO規(guī)則;而優(yōu)先級(jí)消息隊(duì)列和優(yōu)先級(jí)郵箱隊(duì)列基于優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn),遵循按照元素優(yōu)先級(jí)取出的規(guī)則?!?/span>

最后來回答題目中的問題:任務(wù)間通信為什么不使用全局變量?

① 無論是消息隊(duì)列還是郵箱隊(duì)列,都是利用了全局變量可以被隨意訪問的特性,所以使用時(shí)都會(huì)被定義為全局變量。

② 普通全局變量可用于一些簡單的任務(wù)間通信場合。

③ 相較于普通全局變量,加入隊(duì)列機(jī)制可以存儲(chǔ)多個(gè)消息,加入pend-post機(jī)制可以擁有任務(wù)等待和喚醒的機(jī)制,用于解決隊(duì)列已滿或隊(duì)列為空的問題。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉