Linuxの備忘録とか・・・(目次へ)Linuxの備忘録とか・・・(目次へ)ワークキューワークキューはタスクレットと並んで遅延処理を行う手法です。タスクレットはそれをタスクとして起動するksoftirqdがすべてのタスクレット(他のソフト割り込みも)を担っていました。従ってどれか一つのタスクレットで遅延が発生すると、すべてに影響してしまうということです。それを回避する手段としてワークキュが誕生してということでしょうか。(たぶん)IBMのワークキューの使い方のサンプルです。どのようになっているかと言うと、ワークキューを使用するにあたって、まずユーザが定義したworkqueue_structでcreate_workqueue関数でワークキューを作成します。遅延したい処理をwork_struct構造体にまとめてワークキューに登録していくと言う具合です。タスクレットではワークキューに相当するものが無く、いきなりタスクレットのリストに登録しています。ここが大きな違いで、実はワーキュキューというのはそのワークをリスト管理していると同時に、それを処理するスレッドも独自に有しているのです。CPU毎に複数そのスレッドを持たせることも可能なのです。create_workqueue(name)は__create_workqueue_key(name,0,0,&key,name)で呼ばれます。(たぶん)まずwqのworkqueue_struct構造体のkzalloc関数で確保し、wq->cpu_wqにCPU分のcpu_workqueue_struct構造体のインデックスを設定するための領域をalloc_percpu関数で割り当てています。workqueue_struct構造体でなく、このcpu_workqueue_struct構造体に実際の情報が設定されていきます。singlethread==0の時、init_cpu_workqueue関数でのcpu_workqueue_struct構造体を初期化し、create_workqueue_thread関数でこのワークキューの処理を受け持つカーネルスレッドworker_threadを作成し、そのスレッドをcpu_workqueue_struct.threadに設定します。start_workqueue_thread関数でworker_threadを起動させています。singlethread!=0の時、for_each_possible_cpu(cpu)で上の処理をCPU毎に行っています。CPU毎に独自のworker_threadが起動するということです。*work)で登録することでワークが遅延処理として起動されます。&cwq->worklist);が呼ばれ、そこでcpu_workqueue_struct.headをルートとするリストのエンドのワークの実態をリスト追加しています。wake_up(&cwq->more_work);}ワークはworker_threadの延長線上から関数コールされるわけでが。(タスクレットと同じ。)その処理を行うのがrun_workqueue関数です。cpu_workqueue_struct.run_depth>3なら、なにやらスタックをダンプしています。遅延があって、他のCPUから起動されてりして、3回以上再エントリーしたらちょっと問題じゃない。ユーザに警告してくれているんでしょうね?。work->funcで設定したワーク処理を、f(work)でコールすることでワーク処理が行われるようです。spin_unlock_irq(&cwq->lock);}singlethread==0の時(create_workqueue関数でワーク作成時)そのワークキュー内においてスリープするとその影響はそのワークキューで待つすべてのワークに影響します。従ってワークキューがスリープしてもいいと言うのは、linuxとして影響はないですが、そのあたりはユーザに責任でということでしょうか。ワークキューはworkqueue_struct構造体を作成して、それにwork_struct構造体をリストしていました。*work)関数を使用すれば、ワークキューを作成する必要はありません。タスクレットと同じように記述することができます。work);}こうなると考え方はタスクレットと同じです。従ってkeventd_wqのキューを使っているのは、他のユーザも使っているかもしれないので、遅延が発生するとその他のワークにも影響が発生して、他のユーザに怒られます。詳解LINUXカーネルでは、遅延処理は割り込みコンテキスト動作しますが、ワークキューの関数はプロセスコンテキストで動作する。私か理解した遅延処理とワークキューでは???です。言うのは、遅延処理もワークキューも起動要求したところに関係なく、スケジューリングされたカーネルスレッドで起動するということだからです。それと遅延処理の起動要求は、tasklet_schedule関数を呼び出せばいいだけの話で、別に割り込みハンドラから設定する必要もないからです。逆も言えて、ワークキューの起動要求はqueue_work関数で、これを割り込みハンドラから起動しても問題ないはずです。確かに遅延処理は遅延処理実行後に、遅延処理が発生したかチェックして、発生したなら再度、遅延処理が実行されるようになっています。できるだけ遅延処理といえども、できるだけ早く処理をしようということなのでしょう。その点ワークキューはそのような処理はありません。(たぶん)上の詳解LINUXカーネルの記載ですが、割り込みハンドラで使用するには、ワークキューより遅延処理の方がいいですよ。いうことではないかと・・・。ノースAdsense広告情報が設定されていません。