割り込み可能なシステムコールと、リエントラント関数周りの理解について自信がないため質問いたします。
以下が現時点での大まかな理解となります。
・割り込み可能なシステムコールとは、OS(カーネル)が予め決めている、システムコールの実際の処理プロセスの実行途中で、それに対して割り込むことができるもののこと。
・例えば端末をreadしている最中、該当プロセスに対してシグナル等で割り込みが発生した際、該当シグナルへのシグナルハンドラがある場合にはそれを実行させるために、元のユーザプロセスのシグナルハンドラの位置に処理を戻す。
・上の際に割り込まれたシステムコール処理はシグナルハンドラの実行が終わると同時に、
エラーを返す。(処理は再起動しない代わりにerrnoにEINTRという足がかりを残す。)
つまり再起動させたい場合には以下のようなコードが必要
again: if (( read(fds, buff)) < 0) { // 割り込まれたら、マイナスを返すので、内に入る。 if (errno == EINTR) goto again; }
・リエントラント関数は、シグナルが発せられる直前に実行されていたシステムコールと同じ(若しくは処理性質を持つ)システムコールをシグナルハンドラ内で偶然にも使用してしまった場合に、メモリを破壊したりという副作用を1ミリも生まないことが保証されている関数群のこと。
例えばmallocのようなメモリ等の共有資源を司る関数がリエントラント関数ではない理屈。
シグナル前にmalloc()が実行中、その正にタイミングでシグナルが不運に発行されると、
mallocはまだ処理が中断しているだけでエラーによるロールバック処理すらできていない(本当に止まっている)ため、ハンドラ内で更に実行されるmalloc()と衝突してメモリが高い確立で破壊されてしまう。
よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー