iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
自我挑戰組

當你凝視linux, linux也在凝視你系列 第 28

Day28 softirq, tasklet, workqueue

前言

昨天連滾帶爬的走出了 interrupt的泥淖,希望之後能夠有空把他弄得更清楚,今天要講的東西是下半部的 interrupt處理。

softirq

softirq 對應hardirq,只是softirq是純軟體的處理。目前softirq的數量已經固定了,並不會有其他增加,底下是在linux的註釋,表示幾乎所有想做的行為都可以利用tasklet完成,請避免增加新的softirq。

PLEASE, avoid to allocate new softirqs, if you need not really high
frequency threaded job scheduling. For almost all the purposes
tasklets are more than enough. F.e. all serial device BHs et
al. should be converted to tasklets, not to softirqs.

以下是在程式碼中利用枚舉靜態聲明softirq

enum
{
	HI_SOFTIRQ=0,
	TIMER_SOFTIRQ,
	NET_TX_SOFTIRQ,
	NET_RX_SOFTIRQ,
	BLOCK_SOFTIRQ,
	IRQ_POLL_SOFTIRQ,
	TASKLET_SOFTIRQ,
	SCHED_SOFTIRQ,
	HRTIMER_SOFTIRQ, /* Unused, but kept as tools rely on the
			    numbering. Sigh! */
	RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

	NR_SOFTIRQS
};

HI_SOFTIRQ=0 : 優先級最高的softirq
TIMER_SOFTIRQ : 用於計時器的softirq
NET_TX_SOFTIRQ: 發送網路封包的softirq
NET_RX_SOFTIRQ: 接收網路封包的softirq
BLOCK_SOFTIRQ: 用於block device的softirq
IRQ_POLL_SOFTIRQ: 用於block device的softirq
TASKLET_SOFTIRQ: 專門給 tasklet 調用的softirq
SCHED_SOFTIRQ: 用在排程與負載平衡
HRTIMER_SOFTIRQ: 高精度的計時器
RCU_SOFTIRQ: 服務RCU的softirq

NR_SOFTIRQS

tasklet

利用軟中斷實現的下半部中斷處理機制,在linux可以看見 tasklet_struct 的結構,在稍後會看見。
tasklet 有幾個性質

  • 可以動態的創建與刪除
  • 使用 tasklet_schedule()函數之後,tasklet至少會在某個CPU上執行一次
    以下是tasklet的結構
struct tasklet_struct
{
	struct tasklet_struct *next;
	unsigned long state;
	atomic_t count;
	void (*func)(unsigned long);
	unsigned long data;
};

next :多個tasklet可以組成鏈表,指向下一個tasklet
stateTASKLET_STATE_SCHED表示tasklet已經被排程,TASKLET_STATE_RUN代表tasklet正在運行。
count : 若不為0代表該tasklet不允許執行。
func :代表tasklet的處理程序。
data :傳遞參數給tasklet。

利用open_softirq可以註冊一個softirq, 利用 raise_softirq 可以主動觸發softirq

void open_softirq(int nr, void (*action)(struct softirq_action *))
{
    softirq_vec[nr].action = action;
}

void raise_softirq(unsigned int nr)
{
    unsigned long flags;

    local_irq_save(flags);
    raise_softirq_irqoff(nr);
    local_irq_restore(flags);
}

workqueue

工作佇列(work queue)是另外一種將工作推後執行的形式,它和前面討論的tasklet有所不同。工作佇列可以把工作推後,交由一個核心執行緒去執行,也就是說,這個下半部分可以在程序上下文中執行。這樣,通過工作佇列執行的程式碼能佔盡程序上下文的所有優勢。最重要的就是工作佇列允許被重新排程甚至是睡眠。


上一篇
Day27 interrupt 的處理程序
下一篇
Day29 procfs, sysfs, debugfs
系列文
當你凝視linux, linux也在凝視你30

尚未有邦友留言

立即登入留言