clone(2)
のこの部分だと思います manページは違いを解消するかもしれません。 PID:
CLONE_THREAD (Linux 2.4.0-test8 以降)
CLONE_THREAD が設定されている場合、子プロセスは呼び出しプロセスと同じスレッド グループに配置されます。
スレッド グループは、単一の PID を共有する一連のスレッドの POSIX スレッドの概念をサポートするために、Linux 2.4 で追加された機能です。内部的には、この共有 PID はスレッド グループのいわゆるスレッド グループ識別子 (TGID) です。 Linux2.4 以降、getpid(2) を呼び出すと、呼び出し元の TGID が返されます。
「スレッドはプロセスとして実装される」というフレーズは、過去に個別の PID を持っていたスレッドの問題を指します。基本的に、Linux はもともとプロセス内にスレッドを持っていませんでした。仮想メモリやファイル記述子などの共有リソースを持っていた可能性のある個別のプロセス (個別の PID を持つ) だけでした。 CLONE_THREAD
また、プロセス ID とスレッド ID を分離することで、Linux の動作が他のシステムに似たものになり、この意味で POSIX 要件により似たものになります。技術的には、OS にはまだスレッドとプロセスの個別の実装がありません。
シグナル処理は、古い実装のもう 1 つの問題のある領域でした。これについては、@FooF が回答で参照している論文で詳しく説明されています。
コメントで述べたように、Linux 2.4 も本と同じ 2001 年にリリースされたので、ニュースがその印刷物に届かなかったのは当然のことです。
確かに、「2001 年から現在までの間に何かが変わったに違いない」とのことです。あなたが読んでいる本は、LinuxThreads と呼ばれる Linux での POSIX スレッドの最初の歴史的実装に従って世界を説明しています (一部についてはウィキペディアの記事も参照してください)。
LinuxThreads には、POSIX 標準との互換性の問題 (スレッドが PID を共有しないなど) や、その他の重大な問題がありました。これらの欠陥を修正するために、NPTL (Native POSIX Thread Library) と呼ばれる別の実装が Red Hat によって主導され、必要なカーネルとユーザー空間ライブラリのサポートを追加して、より良い POSIX 準拠を実現しました (NGPT と呼ばれる IBM によるさらに別の競合する再実装プロジェクトから良い部分を取り入れています (" Next Generation Posix Threads")、NPTL に関するウィキペディアの記事を参照)。 clone(2)
に追加された追加フラグ システムコール (特に CLONE_THREAD
その @ikkkachu
彼の回答で指摘) は、おそらくカーネルの変更の最も明白な部分です。作業のユーザー空間部分は、最終的に GNU C ライブラリに組み込まれました。
現在でも、一部の組み込み Linux SDK は古い LinuxThreads 実装を使用しています。これは、uClibc (μClibc とも呼ばれる) と呼ばれるメモリ フットプリントの小さいバージョンの LibC を使用しているためであり、GNU LibC からの NPTL ユーザー空間実装が移植されるまでに何年もかかりました>そして 一般的に言えば、これらの特別なプラットフォームは最新のファッションに超高速で従おうとはしないため、デフォルトの POSIX スレッド実装と見なされます。動作中の LinuxThreads 実装の使用は、実際に、これらのプラットフォーム上の異なるスレッドの PID が、POSIX 標準仕様とは異なり、読んでいる本で説明されているように異なることに気付くことで観察できます。実際、一度 pthread_create()
を呼び出したことがあります 、混乱をまとめるために追加のプロセスが必要だったため、突然プロセス数を 1 から 3 に増やしました。
Linux の pthreads(7) マニュアル ページには、この 2 つの違いに関する包括的で興味深い概要が記載されています。時代遅れではありますが、別の啓発的な違いの説明は、NPTL の設計に関する Ulrich Depper と Ingo Molnar によるこの論文です。
本のその部分をあまり真剣に受け止めないことをお勧めします。代わりに、この件に関する Butenhof の Programming POSIX threads と POSIX および Linux のマニュアル ページをお勧めします。このテーマに関する多くのチュートリアルは不正確です。
(ユーザー空間) スレッドは、Linux ではプロセスとして実装されません。スレッドは独自のプライベート アドレス空間を持たず、親プロセスのアドレス空間を共有します。
ただし、これらのスレッドはカーネル プロセス アカウンティング システムを使用するように実装されているため、独自のスレッド ID (TID) が割り当てられますが、親プロセスと同じ PID と「スレッド グループ ID」(TGID) が与えられます。新しい TGID と PID が作成されるフォークで、TID は PID と同じです。
そのため、最近のカーネルにはクエリ可能な個別の TID があったようです。これはスレッドによって異なります。上記の main() thread_function() のそれぞれでこれを示す適切なコード スニペットは次のとおりです:
long tid = syscall(SYS_gettid);
printf("%ld\n", tid);
したがって、これを含むコード全体は次のようになります:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
void* thread_function (void* arg)
{
long tid = syscall(SYS_gettid);
printf("child thread TID is %ld\n", tid);
fprintf (stderr, "child thread pid is %d\n", (int) getpid ());
/* Spin forever. */
while (1);
return NULL;
}
int main ()
{
pthread_t thread;
long tid = syscall(SYS_gettid);
printf("main TID is %ld\n", tid);
fprintf (stderr, "main thread pid is %d\n", (int) getpid ());
pthread_create (&thread, NULL, &thread_function, NULL);
/* Spin forever. */
while (1);
return 0;
}
出力例:
main TID is 17963
main thread pid is 17963
thread TID is 17964
child thread pid is 17963