中斷處理分為上半部和下半部
一般來說中斷處理的上半部和下半部都是不允許出現睡眠和阻塞的。但是對於下半部,並不是一刀切,下半部的實現方式有軟中斷和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...