コンパイラまたはOSは、sig_atomic_t型と通常のint型変数をどのように区別し、操作がアトミックであることをどのように保証しますか?両方を使用するプログラムは、同じアセンブラコードを持っています。操作をアトミックにするためにどのように特別な注意が払われていますか?
sig_atomic_t
はアトミックデータ型ではありません。シグナルハンドラーのコンテキストで使用できるのは、データ型だけです。そのため、名前を「シグナル処理に関連するアトミック」と読みやすくします。
シグナルハンドラーとの通信を保証するには、アトミックデータ型のプロパティの1つだけが必要です。つまり、読み取りと更新では常に一貫した値が表示されるという事実です。その他のデータ型(おそらくlong long
など)は、下位部分と上位部分のいくつかのアセンブラー命令で記述できます。 sig_atomic_t
は、一度に読み書きできることが保証されています。
したがって、プラットフォームはsig_atomic_t
として整数の基本型を選択できます。これにより、volatile sig_atomic_t
がシグナルハンドラーで安全に使用できることが保証されます。多くのプラットフォームがint
を選択した理由は、int
が単一の命令で記述されているためです。
最新のC標準であるC11にはアトミックタイプがありますが、これは完全に異なるものです。それらのいくつか(「ロックフリー」のもの)はシグナルハンドラーでも使用できますが、これもまったく別の話です。
ご了承ください sig_atomic_t
はスレッドセーフではなく、非同期シグナルセーフのみです。
アトミックには2種類の障壁があります。
volatile
キーワードの機能です。対象の時計の包括的な扱いについて アトミックウェポン:C++メモリモデルと最新のハードウェア 。
sig_atomic_t
は、単なるtypedef
です(システム固有の整数型には、通常int
またはlong
)。そして、volatile sig_atomic_t
(だけでなく sig_atomic_t
のみ)。
volatile
キーワードを追加すると、コンパイラーは多くの最適化を回避する必要があります。
最近の C11 標準が追加されました_Atomic
および<stdatomic.h>
。サポートするには、最新の [〜#〜] gcc [〜#〜] (例 4.9 )が必要です。
両方を使用するプログラムは、同じアセンブラコードを持っています。操作をアトミックにするためにどのように特別な注意が払われていますか?
これは古い質問ですが、質問のこの部分に具体的に取り組む価値はあると思います。 Linuxでは、sig_atomic_t
はglibcによって提供されます。 glibcのsig_atomic_t
はint
のtypedefであり、(この投稿の時点では)特別な扱いはありません。 glibc docs はこれに対処します:
実際には、intはアトミックであると想定できます。ポインタ型はアトミックであると想定することもできます。とても便利です。これらの両方の仮定は、GNU Cライブラリがサポートするすべてのマシンと、私たちが知っているすべてのPOSIXシステムで当てはまります。
つまり、通常のint
は、glibcがサポートするすべてのプラットフォームでsig_atomic_t
の要件をすでに満たしているため、特別なサポートは必要ありません。それにもかかわらず、CおよびPOSIX標準ではsig_atomic_t
を義務付けています。これは、CおよびPOSIXを実装するエキゾチックなマシンでint
がsig_atomic_t
の要件を満たさない場合があるためです。
このデータ型はアトミックなようです。
From here :
24.4.7.2アトミックタイプ変数へのアクセスの中断に関する不確実性を回避するために、アクセスが常にアトミックである特定のデータタイプsig_atomic_tを使用できます。このデータ型の読み取りと書き込みは単一の命令で行われることが保証されているため、ハンドラーがアクセスの「途中」で実行することはできません。
型sig_atomic_tは常に整数データ型ですが、どのデータ型であり、それに含まれるビット数は、マシンによって異なります。
データ型:sig_atomic_tこれは整数データ型です。このタイプのオブジェクトは常にアトミックにアクセスされます。
実際には、intはアトミックであると想定できます。ポインタ型はアトミックであると想定することもできます。とても便利です。これらの両方の仮定は、GNU Cライブラリがサポートするすべてのマシンと、私たちが知っているすべてのPOSIXシステムで当てはまります。