rtthread之工作佇列

2021-10-06 15:15:11 字數 3279 閱讀 6424

中斷處理分為上半部和下半部

一般來說中斷處理的上半部和下半部都是不允許出現睡眠和阻塞的。但是對於下半部,並不是一刀切,下半部的實現方式有軟中斷和tasklet(不允許睡眠和阻塞)以及工作佇列(允許睡眠和阻塞)。

上半部:一般中斷的中斷處理函式為上半部,要求做耗時少的動作,盡量迅速,一定不能休眠和阻塞。

下半部:由於上半部只能執行耗時少的操作,所以耗時長的操作就放在下半部,兩個的界限並不是很明顯,取決於我們要將哪個操作放在上半部還是下半部。

下面討論一下工作佇列的原理及實現

實現原理:工作佇列(workqueue)是一種將工作推後執行的形式,工作佇列可以把工作推後,交由乙個核心執行緒去執行,也就是說,這個下半部分可以在程序上下文中執行。最重要的就是工作佇列允許被重新排程甚至是睡眠。工作佇列的本質是建立乙個乙個普通的核心執行緒,我們稱為工作者執行緒。

以下是幾個工作佇列抽象出來的資料結構

1:struct rt_workqueue表示乙個工作佇列物件(包含乙個工作者執行緒)。

2:struct rt_work為工作佇列上的任務。當我們將乙個任務加入乙個工作佇列時候,會將該任務掛接到struct rt_workqueue的任務鍊錶上,當工作執行緒未就緒的時候,這個工作者執行緒就會喚醒,去遍歷這個鍊錶上的所有任務,執行完後,將該任務從鍊錶上拿走,工作者執行緒繼續休眠。

3:雙向鍊錶操作原理請檢視文章(資料結構-------雙向鍊錶),記憶體申請釋放請檢視文章(rtthread之小記憶體演算法)。

資料結構定義

//記憶體申請,實現及原理請參考rtthread之小記憶體演算法

#ifndef rt_kernel_malloc

#define rt_kernel_malloc(sz)            rt_malloc(sz)

#endif

//記憶體釋放

#ifndef rt_kernel_free

#define rt_kernel_free(ptr)             rt_free(ptr)

#endif

//工作佇列物件,包含工作者執行緒

struct rt_workqueue

;//任務物件,包含工作任務及資料

struct rt_work

;

原理實現

1.工作者執行緒

//工作者執行緒,處理掛接到該工作佇列上的任務或者工作

static void _workqueue_thread_entry(void* parameter)

level = rt_hw_interrupt_disable();

//有任務,則獲取對應任務的資訊

work = rt_list_entry(queue->work_list.next, struct rt_work, list);

//從工作佇列任務表中刪除當前任務

rt_list_remove(&(work->list));

rt_hw_interrupt_enable(level);

//執行任務

work->work_func(work, work->work_data);

}}

2.工作佇列初始化及建立工作者執行緒

//建立及初始化工作佇列物件,建立工作者執行緒,返回工作佇列物件

struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority)

//開啟工作者執行緒

rt_thread_startup(queue->work_thread);

}return queue;

}

3.向工作佇列新增任務

//將任務加入到工作佇列中

rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work)

else

rt_hw_interrupt_enable(level);

return rt_eok;

}

4.刪除工作佇列

//刪除工作佇列

rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue)

5.將任務從工作佇列中刪除

//將任務從工作佇列中刪除

rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work)

應用:

在使用spi flash模擬u盤開發過程中,由於spi flash讀寫速度操作比較慢耗時,且在flash操作中封裝了互斥操作,對於作業系統不能在中斷中使用互斥量等操作,需要使用中斷下半部的思想,將讀取操作新增到工作佇列中,從而實現模擬u盤的操作。

修改步驟:

1.建立工作佇列

struct rt_workqueue *usb_irq_workqueue = null;

void usb_cdc_vcp_thread(void* parameter)

.......

}

2.修改usb中斷操作,將任務新增到工作佇列

struct usb_work_data

;//修改usb輸入端點處理任務函式

void usb_msc_data_in(struct rt_work* work, void* work_data)

//修改usb輸出端點處理任務函式

void usb_msc_data_out(struct rt_work* work, void* work_data)

extern struct rt_workqueue *usb_irq_workqueue;

static struct usb_work_data usb_data;

static struct rt_work usb_msc_work;

static uint32_t dcd_handleinep_isr(usb_otg_core_handle *pdev)

......

}......

}static uint32_t dcd_handleoutep_isr(usb_otg_core_handle *pdev)

......

}......

}

工作佇列分析

一 用法 struct cpu workqueue struct cacheline aligned the externally visible workqueue abstraction is an array of per cpu workqueues struct workqueue str...

工作佇列模型

workqueue,中文稱其為工作佇列,是乙個用於建立核心執行緒的介面,通過它建立的核心執行緒來執行核心其他模組排列到佇列裡的工作,建立的核心執行緒被稱為工作者執行緒。要理解工作佇列的實現,重點在於理解相關的三個資料結構的含義及關係。1 表示工作佇列型別的資料結構 struct workqueue ...

工作佇列分析

一 用法 struct cpu workqueue struct cacheline aligned the externally visible workqueue abstraction is an array of per cpu workqueues struct workqueue str...