60年近く半導体業界を支配してきたムーアの法則について聞いたことがありますか?ムーアの法則が法則ではなく、観察であることをご存知ですか?この法律になじみのない人のために、これはそれがどのように表現されているかです。
ムーアの法則によれば、高密度集積回路のトランジスタ数は 2 年ごとに 2 倍になります。
このルールはエレクトロニクスの観点から書かれていますが、コンピューターの観点から見ると、計算能力は 2 年ごとに 2 倍になることを示しています。基本的に、単一チップの計算能力は指数関数的に増加します。素晴らしいですね。
驚くべきことは、この観察がなされて以来、それが真実であることが証明され、現在では規則と見なされていることです.
しかし、誰もが知っているように、良いものは必ずしも無料ではありません。この例では、より強力な計算は過度の加熱を犠牲にして行われました。 2010 年に到着した時点で、プロセッサーはパスタを調理するのに十分な温度に達していました。 (このYouTubeビデオをチェックして、自分で体験してください)。
さらに、チップ上のトランジスタの数が増えるにつれて、材料の物理的限界に達し始めました。この時点で素粒子の力が活発になり始め、ムーアの法則の軌跡を維持することが難しくなりました。
コンピュータがこれまで以上に高速化する時代は終わったように感じました。しかし、エンジニアには別の計画がありました。彼らは、単一の超強力なコアの代わりに、複数の強力なコアを使用し始めました。
ハードウェアの問題は解決したかもしれませんが、ソフトウェア エンジニアにとっては新たな課題となりました。エンジニアは、現在コンピューターに搭載されている複数のコアを活用するソフトウェアを開発する必要がありました。その結果、並列プログラミングとも呼ばれる並行プログラミングが生まれました。プログラミングのこの分野では、スレッドが脚光を浴びています。しかし、スレッドについて話す前に、プロセスとは何かを理解する必要があります。
Linux プロセスは、プログラムの実行中のインスタンスとして定義されます。
したがって、システムは、プログラムの実行中に、スタック メモリ、ソース コード、レジスタなど、さまざまな項目を追跡する必要があります。 Linux では、これらすべての集合体をプロセスと呼びます。 Linux はプロセスの基盤の上に構築されています。
マシンで実行されているさまざまなプロセスを確認するには、次のコマンドを実行してみてください。これにより、プロセス ID とともにすべてのプロセスが実行されます。
$ ps
サンプルのスナップショットを次に示します。
デフォルトでは、上記のコマンドは現在のユーザーに関連付けられているプロセスのみを表示します。すべてのプロセスを一覧表示するには、次のオプションを指定してコマンドを使用できます。
$ ps -aux
サンプルのスナップショットを次に示します。
これらの追加オプションをps
コマンドに適用すると、追加情報も得られます。さまざまなフラグの意味は次のとおりです-
a
はすべてのユーザーを表しますu
は現在のユーザーを表しますx
は端末外で実行されたプロセスを表示します
kill
コマンドを使用して一部のプロセスを強制終了することもできます。使用方法は次のとおりです-
$ kill PID
ここで、 PID
はps
コマンドから取得できるプロセス ID です。 Linux システムの各プロセスには、それを識別するために使用される一意のPID
があります。コマンドpidof
を使用して、プロセスのPID
を見つけることもできます。
$ pidof bash
プログラムを起動したり、コマンドを発行したりすると、プロセスが形成されます。ターミナルからコマンドを実行すると、新しいプロセスが開始されます。この新しいプロセスを生成するために端末が使用されたため、端末プロセスが新しいコマンド プロセスを開始したと言えます。つまり、新しいコマンド プロセスは端末プロセスの子プロセスです。
Linux エコシステムのすべてのプロセスには、それを作成した親プロセスがあります。次のコマンドを使用して、特定のPID
を持つプロセスの親プロセスを確認できます。
$ ps -o ppid= -p PID
Linux のすべてのプロセスは、直接的または間接的に、PID 1 のプロセスの子プロセスです。これは偶然ではありません。 PID 1 のプロセスは init プロセスであり、起動時にシステムによって最初に開始されるプロセスです。後続のプロセスは、このプロセスの子として作成されます。
したがって、プロセス間のこれらの関係から構築されたツリーがあります。これをプロセスツリーと呼びます。
プロセスは Linux で非常に便利であり、プロセスなしでは生きていくことはできません。しかし、それらには欠点が 1 つあります。または、まったく欠点ではなく、単に機能する方法だけです。手続きが重い。新しいプロセスが起動されるたびに、データ、メモリ、および変数が転送されます。同じプログラムを実行する各プロセスには、ソース コードの独自のコピーがあります。その結果、多数のプロセスを生成することは賢明な考えではありません。
ただし、プロセスは複数の要求を同時に処理するためのメカニズムであるため、この不愉快な事実に制約されます。システムでは限られた数のプロセスしか起動できないため、多くの共通点を持つ少数の同時ユーザーにのみサービスを提供できます。多数の同時ユーザーにサービスを提供する必要がある Web サーバーを考えてみましょう。ユーザーごとに新しいプロセスを作成することは、コストのかかる操作です。その結果、手順よりも安価なものが必要になります。ここでスレッドが機能します。
スレッドは単なる軽量プロセスです。スレッドは、親プロセスおよびそれが作成したすべてのスレッドとメモリを共有します。この共有メモリがあるため、新しいスレッドを生成するコストが低くなります。これにより、スレッド通信とコンテキスト切り替えが高速化されるという追加の利点が得られます。スレッドを使用すると、プロセスは複数のタスクを同時に実行できます。
プロセスの数と比較して、かなりの数のスレッドを生成できます。複数のコア マシンでは、これらのスレッドは並列で実行されます。多くのプロセスを生成したり、すべてのタスクを順番に実行したりするのではなく、これによりプログラムの全体的なパフォーマンスが向上します。
最初のスレッドを開始してみましょう。 bash では新しいスレッドを開始できないことに注意してください。 bash コマンドは、サブプロセスの作成にのみ使用できます。したがって、これから行うことは、2 つのスレッドを起動する C コードを作成することです。次に、bash を使用して、この C コードをサブプロセスとして実行します。次に、この新しいプロセスによって 2 つのスレッドが作成されます。
いくつかのコードを手に入れましょう。新しいファイルを作成し、 threads.c
という名前を付けます。お気に入りの IDE で開いてください。
最初のステップは、必要なヘッダー ファイルをインポートすることです。
#include <pthread.h> #include <stdio.h>
2 つのスレッドを作成し、それぞれが同じ関数を実行しますが、パラメーターは異なります。その関数を書きましょう。
void* print_multiple_messages(void* ptr) { char* message = (char*) ptr; for(int i=0; i<1000; ++i) { printf("%s \n", message); } }
ご覧のとおり、この関数は大したことはしません。入力パラメーターとしてメッセージを受け取り、それを何千回も出力します。
メイン関数を書きましょう。
int main() { // Continue writing from here }
プロセスと同様に、スレッドにも ID があり、スレッドを一意に識別するために使用されます。これらの ID を保持する 2 つの変数を作成します。
pthread_t thread1, thread2;
スレッドごとに異なるメッセージを使用します。異なるメッセージを保持する 2 つの文字列 (文字配列) を作成します。
char* message1 = "Thread 1"; char* message2 = "Thread 2";
次のステップは、2 つのスレッドを作成することです。そのためにpthread_create
メソッドを使用します。
pthread_create(&thread1, NULL, print_multiple_messages, (void*) message1); pthread_create(&thread2, NULL, print_multiple_messages, (void*) message2);
これにより、2 つの新しいスレッドが開始されます。 2 つのスレッドが作業を完了するまで待機するようにメイン プロセスに指示しましょう。
pthread_join(thread1, NULL); pthread_join(thread2, NULL);
それだけです。コードをコンパイルして実行します。 2 つのスレッドからのメッセージが混同されることに気付くでしょう。これは、それらが並行して実行されていることを示しています。
おめでとうございます。最初のスレッドを作成しました。
そのため、この記事では、スレッドとプロセスについて説明しました。これらは Linux の最も魅力的な機能の一部であり、それらを習得することが重要です。これにより、ハードウェアを認識するソフトウェアの開発と、自由に使えるリソースの効率的な使用が可能になります。
ここで、この記事の結論を導き出します。私たちはあなたが理解できるように十分に詳細に説明するよう努めましたが、それだけではありません。だからもっと学び続けてください。コンテンツを楽しんだ場合は、コメントしたり、感情を表現したりすることができます。
楽しく学びましょう!