ドライバでの典型的な使用方法は、attach(9E) でタスクキューを作成することです。taskq_dispatch() 呼び出しの大部分は、割り込みコンテキストから行われます。
このセクションでは、タスクキューで消費されるシステムリソースをモニターするために使用可能な 2 つの手法について説明します。タスクキューは、タスクキュースレッドによるシステム時間の使用量に関する統計情報をエクスポートします。さらにタスクキューは、DTrace SDT プローブを使用してタスクキューがタスクの実行を開始した時刻と終了した時刻を判定します。
すべてのタスクキューに一連の kstat カウンタが関連付けられます。次のkstat (1M) コマンドの出力を確認してください。
$ kstat -c taskq module: unix instance: 0 name: ata_nexus_enum_tq class: taskq crtime 53.877907833 executed 0 maxtasks 0 nactive 1 nalloc 0 priority 60 snaptime 258059.249256749 tasks 0 threads 1 totaltime 0 module: unix instance: 0 name: callout_taskq class: taskq crtime 0 executed 13956358 maxtasks 4 nactive 4 nalloc 0 priority 99 snaptime 258059.24981709 tasks 13956358 threads 2 totaltime 120247890619
上で示した kstat 出力には、次の情報が含まれています。
タスクキューの名前とそのインスタンス番号
スケジュールされたタスクの数 (tasks) と実行されたタスクの数 (executed)
タスクキューを処理するカーネルスレッドの数 (threads) とその優先順位 (priority)
すべてのタスクの処理に費やされた合計時間 (ナノ秒) (totaltime)
次の例は、kstat コマンドを使用してあるカウンタ (スケジュールされたタスクの数) が時間の経過とともに増加する様子を監視する方法について示したものです。
$ kstat -p unix:0:callout_taskq:tasks 1 5 unix:0:callout_taskq:tasks 13994642 unix:0:callout_taskq:tasks 13994711 unix:0:callout_taskq:tasks 13994784 unix:0:callout_taskq:tasks 13994855 unix:0:callout_taskq:tasks 13994926
タスクキューは便利な SDT プローブをいくつか提供します。このセクションで説明するプローブはすべて、次の 2 つの引数を持ちます。
ddi_taskq_create() から返されるタスクキューポインタ
taskq_ent_t 構造体へのポインタ。このポインタを D スクリプト内で使用することで関数や引数を抽出します。
これらのプローブを使用すると、個々のタスクキューやそれらを通じて実行される個々のタスクに関する高精度のタイミング情報を収集できます。たとえば、次のスクリプトは、タスクキュー経由でスケジュールされた関数を 10 秒に 1 度出力します。
# !/usr/sbin/dtrace -qs sdt:genunix::taskq-enqueue { this->tq = (taskq_t *)arg0; this->tqe = (taskq_ent_t *) arg1; @[this->tq->tq_name, this->tq->tq_instance, this->tqe->tqent_func] = count(); } tick-10s { printa ("%s(%d): %a called %@d times\n", @); trunc(@); }
特定のマシン上で上の D スクリプトを実行すると、次のような出力が生成されます。
callout_taskq(1): genunix`callout_execute called 51 times callout_taskq(0): genunix`callout_execute called 701 times kmem_taskq(0): genunix`kmem_update_timeout called 1 times kmem_taskq(0): genunix`kmem_hash_rescale called 4 times callout_taskq(1): genunix`callout_execute called 40 times USB_hid_81_pipehndl_tq_1(14): usba`hcdi_cb_thread called 256 times callout_taskq(0): genunix`callout_execute called 702 times kmem_taskq(0): genunix`kmem_update_timeout called 1 times kmem_taskq(0): genunix`kmem_hash_rescale called 4 times callout_taskq(1): genunix`callout_execute called 28 times USB_hid_81_pipehndl_tq_1(14): usba`hcdi_cb_thread called 228 times callout_taskq(0): genunix`callout_execute called 706 times callout_taskq(1): genunix`callout_execute called 24 times USB_hid_81_pipehndl_tq_1(14): usba`hcdi_cb_thread called 141 times callout_taskq(0): genunix`callout_execute called 708 times