ホームページ  >  記事  >  運用・保守  >  Linux ドライバーの下半分を中断する 3 つの方法

Linux ドライバーの下半分を中断する 3 つの方法

嵌入式Linux充电站
嵌入式Linux充电站転載
2023-07-31 14:57:18973ブラウズ

割り込みの下半分とは

割り込みが発生すると、割り込みハンドラーに入ります。

ただし、割り込みハンドラは、ハードウェアに 迅速に応答して、タイム クリティカルな操作を完了できるように、高速、非同期、シンプルである必要があります。

したがって、時間要件が比較的緩やかな他のタスクについては、

実行する前に、割り込みがアクティブになるまで 延期する必要があります。 このように、割り込み処理プロセス全体は 2 つの部分

:

最初の部分は割り込みハンドラー (
    上半分
  • )、カーネルは非同期実行を通じてハードウェア割り込みへの即時応答を完了します。
    割り込み処理フローの他の部分、
  • 下半分
  • (下半分)
  • 次へ半分のタスクは主に割り込み関連の作業を実行するもので、割り込みサービス ルーチン自体では完了しません。

下半分Linux ドライバーの下半分を中断する 3 つの方法 正確な時間を指定する必要はありません。## のときに実行できるように、これらのタスクを少し遅らせてください。 # システムはそれほどビジーではありません
そして

中断と回復の後、 を実行できます。 上半分と下半分の主な違い:

上半分
    は ## を指します。 #割り込みハンドラ
  • 下半分の

    は、割り込みに関連しているものの、延期できるいくつかのタスクを指します。 割り込みの上半分は同じ種類の割り込みによって割り込むことはできませんが、下半分は引き続き割り込みによって割り込まれる可能性があります

  • #通常、下半分は割り込みハンドラーが返されるとすぐに実行されます。

  • 前半はシンプルで高速です

    、実行中の一部またはすべての割り込みを無効にします。
  • #後半は後で実行されます。実行中にすべての割り込みに応答できます。

Linux では、割り込みの下半分を実装する主な方法が 3 つあります。

  • ソフト割り込み
  • タスクレット
  • ##ワークキュー

softirq

softirq

は Softirq で、コードは kernel/ にあります。 Softirq.cファイル内; 各 Softirq は

softirq_action

構造によって表されます: softirq の

Linux ドライバーの下半分を中断する 3 つの方法
.c

Softirq ベクトル配列 softirq_vec が定義されています。 <pre class="brush:php;toolbar:false;">static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; enum { HI_SOFTIRQ=0, /*用于高优先级的tasklet*/ TIMER_SOFTIRQ, /*用于定时器的下半部*/ NET_TX_SOFTIRQ, /*用于网络层发包*/ NET_RX_SOFTIRQ, /*用于网络层收报*/ BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, /*用于低优先级的tasklet*/ SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS };</pre>配列のメンバーの数は、列挙定数である

NR_SOFTIRQS

によって決まります。 ソフト割り込みを追加する場合、ファイル

include/linux/interrupt.h

に列挙定数を追加する必要があります。

ソフト割り込みを使用する際のいくつかの重要なポイント

:

  • 一个软中断不会抢占另外一个软中断。
  • 惟一可以抢占软中断的是中断处理程序。
  • 其他的软中断可以在其他处理器上同时执行。

相关接口

  • 注册软中断
void open_softirq(int nr, void (*action)(struct softirq_action *))

即注册对应类型的处理函数到全局数组softirq_vec中。

  • 触发软中断
void raise_softirq(unsigned int nr)

实际上即以软中断类型nr作为偏移量会置位irq_stat[cpu_id]的成员变量__softirq_pending.

__softirq_pending字段中的每一个bit,对应着某一个软中断,某个bit被置位,说明有相应的软中断等待处理。

这也是同一类型软中断可以在多个cpu上并行运行的根本原因。

软中断实例

以一个按键驱动的中断处理为例,将按键驱动的中断处理分成上下两部分:

  • #上部: キー値を読み取り、ソフト割り込みをトリガーします
  • 下部:ウェイクアッププロセス
Linux ドライバーの下半分を中断する 3 つの方法
#ソフト割り込みの登録、ドライバーのエントリ関数で、ソフト割り込みを登録します:

Linux ドライバーの下半分を中断する 3 つの方法
追加された列挙型定数:

Linux ドライバーの下半分を中断する 3 つの方法
ご覧のとおり、ソフト割り込みを使用するにはカーネルを変更する必要があり、列挙型の追加は少し面倒です。

したがって、通常は

許可なくソフト割り込み の数を増やすことはお勧めしません。新しいソフト割り込みが必要な場合は、 ソフト割り込みベースの として実装するようにしてください。タスクレットフォーム。

タスクレット

##タスクレット

は、ソフト割り込み#を使用します。 ## 実装された下半分のメカニズムの一種です。 ソフト割り込み

タスクレット

のどちらを使用する方が良いですか? softirq

tasklet

のどちらを使用するかを選択するのは、実際には非常に簡単です:

  • 通常你应该用tasklet就像我们在前面看到的,软中断资源有限,也麻烦,而且软中断的使用者屈指可数。它只在那些执行频率很高和连续性要求很高的情况下才需要。
  • tasklet却有更广泛的用途。大多数情况下用tasklet效果都不错,而且它们还非常容易使用。
  • 因为tasklet是通过软中断实现的,所以它们本身也是软中断

tasklet使用

tasklet的使用步骤如下:

1、编写tasklet处理函数(下半部

void my_tasklet_fun (unsigned long data)

2、声明tasklet

//静态 
DECLARE_TASKLET(my_tasklet,my_tasklet_fun,data); 
//动态
Struct  tasklet_struct xxx;
tasklet_init(&xxx,tasklet_handler,dev)

3、调度 tasklet

tasklet_schedule(&my_tasklet);

登记my_tasklet, 然后允许系统在合适的时间调度它。

tasklet实例

以按键中断驱动为例:

Linux ドライバーの下半分を中断する 3 つの方法

まず、DECLARE_TASKLET を使用して tasklet を静的に宣言し、その下位半分の関数を btn_tasklet_func として指定し、タスクを中断します。 service 関数 (上半分) はキー値を取得した後、tasklet_schedulescheduling を呼び出します。

ワーク キュー

ワーク キューワーク キュー、下半分に割り込むタイプでもあります。

ワーク キュー 作業の後半を カーネル スレッド に実行を延期します - work は常に プロセス コンテキストで実行されます.

2 つの重要なポイント:

  • 延期された作業に sleep が必要な場合は、work queues を使用します。それ以外の場合は、softirq または tasklets を使用します。
  • Work queues は、大量のメモリを割り当てて、セマフォ. 、またはブロックされた I/O.

ワーク キューの関連インターフェイス関数:

Linux ドライバーの下半分を中断する 3 つの方法
#使用法に関しては、

ワークキュータスクレットに似ています:

Linux ドライバーの下半分を中断する 3 つの方法

##

以上がLinux ドライバーの下半分を中断する 3 つの方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は嵌入式Linux充电站で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。