プログラム

プログラム
人が書いた設計図となるソースコードをコンパイルして実行可能な形にしたもの
あるタスクを実行するための一連の命令。
これはテキストファイル、ワードプロセッサ、ウェブブラウザ、ゲームなど、コンピュータで実行可能な任意のソフトウェアを指す。プログラムはディスク上のファイルとして存在し、実行するまでは何もしない(「静的」と表現する)。
これは、本棚にある本のようなもので、読む人が来てそれを開くまで、ただそこに存在しているだけ。
プログラムが動作する仕組み
※https://qiita.com/KenyaSaitoh/items/22f32b9d7aea5844d779 より画像引用
プロセス
①プログラムの実行中のインスタンス(動作中のプログラム)。
これは「動的」であり、プログラムを実行するとき、それはプロセスとしてメモリにロードされ、CPU がその命令を順次実行する。
これは、本棚から取られ、読まれている本のようなもの。
②オペレーティングシステムが管理する実行中のプログラムのインスタンスを指す。
すべてのプロセスには、一意のプロセス ID(PID)が割り当てられ、オペレーティングシステムがプロセスを識別および管理するために使用する。
③ソースコードを実行するための環境や状態全体。
プログラムが実際に動き出すと「プロセス」になる。プロセスは、プログラムを動かすために必要なもの、メモリ・CPU・ファイルやネットワークなどを全部用意する。ソースコードを実行するための箱のようなもの。
プロセスは、ハードウェアやカーネルの機能に直接アクセスできない。代わりに、OSを介して間接的にアクセスする。
※プロセスはプログラムの動作中の「実体」を指すと言える。
プロセスは、そのプログラムが実行される際に必要なリソース(CPU 時間、メモリ空間など)を持っている。
◎プログラム自体は「静的」な存在である一方、それが OS によってメモリにロードされて実行されるとき、それは「プロセス」として動的に活動する。
各プロセスは、独自のメモリ空間とプロセス制御ブロック(PCB)を持っている。
メモリ空間は、プログラムコード、データ、スタックを格納するために使用され、他のプロセスから保護されているため、各プロセスは独自のリソースを持っている。
メモリ空間(memory space)
※https://www.isas.jaxa.jp/docs/PLAINnews/128_contents/128_1.html より画像引用
特定のプロセスに割り当てられるメモリの領域で、プログラムコード、データ、スタックを格納するために使用される。
・プログラムコード:コンピュータに何をすべきかを指示する命令。
・データ:ユーザーからの入力やファイルから読み込まれたデータなど、プログラムが使用する必要のあるすべての情報。
・スタック:関数の呼び出しを追跡するために使用され、プログラム内の現在の位置や使用中の変数の値などの情報を格納する。
※https://zenn.dev/keisuke90/articles/0bb2ed7f3afb72 より画像引用
また、このメモリ領域は他のプロセスから隔離されているため、プロセスごとに専用のリソースが確保されていると言える。これにより、一つのプロセスが他のプロセスのメモリに不用意に触れることを防いで、各プロセスを他から独立して動かすことが可能になる。
※https://zenn.dev/farstep/articles/process-thread-difference より画像引用
※https://zenn.dev/junjunjunjun/articles/6e6ed31167b0ca より画像引用
参照:https://moro-archive.hatenablog.com/entry/2014/09/11/013520
プロセス制御ブロック(process control block, PCB)
※https://www.technologyuk.net/computing/operating-systems/process-management.shtml より画像引用
OS が各プロセスを管理するために使用するデータ構造。
PCB に含まれるプロセスに関する重要な情報
・プロセスの状態(新規、実行中、待機中、準備完了、終了など)
・プロセス ID
・プログラムカウンタ(次に実行する命令のアドレス)
・CPU レジスタの状態
・CPU スケジューリング情報(プロセスの優先度、スケジュールされる時間など)
・メモリ管理情報(ページテーブルやセグメントテーブルへのポインタなど)
・入出力状態情報 など
子プロセス
コンピュータシステムでは、プロセスは他のプロセスを生成(または作成)する能力がある。
これは「フォーク」(fork)と呼ばれる操作を行うことで可能となる。
親プロセスとは、新しいプロセスを生成した元のプロセスを指す。
親プロセスは通常、一つ以上の新しいプロセス子プロセスを生成できる。
os.fork()
Linux システムコールの一つ。現在のプロセスの複製を作成する。
新しく作られたプロセスは「子プロセス」であり、元のプロセスは「親プロセス」となる。
子プロセスは親プロセスのほとんど完全なコピーであり、コード、グローバル変数、ヒープ、スタックなどのメモリレイアウトを含めたほとんど全ての内容が複製される。
※親プロセスと子プロセスはそれぞれが独自のプロセス ID(PID)を持つ。子プロセスの PID はシステムによって新しく割り当てられる。この新しい PID は、システムで一意になるように選ばれる。
・fork()の戻り値は、
親プロセス:新しく作成された子プロセスのプロセスID(PID)が返される
子プロセス:0が返される
・os.fork()が呼び出されると、それまでの1つのプロセスが2つのプロセス(親プロセスと子プロセス)に分裂する。
・これら2つのプロセスはそれぞれ別々に、プログラムの残りの部分を実行する。
・コード内で if pid > 0: を使用することで、親プロセスと子プロセスの動作を異なるものにする。
①pid > 0 の場合:コードは親プロセスで実行される。
②pid == 0 の場合:コードは子プロセスで実行される。
ファイル
OS が管理する保存されたあらゆるデータの断片。データを永続的に保存するための仕組み。
メモリバッファ
※http://ash.jp/linux/unyo/06.htm より画像引用
コンピュータのメモリ上にある、データを一時的に保存するための領域。
メモリバッファは、プロセス内のメモリ空間にも作成され、プログラムの入出力、プロセス間通信、動的なメモリ割り当てなど、様々な場面で利用される。
・ファイルを読み書きするとき、プログラムは「ファイルそのもの」を直接触るのではなく、ファイル記述子を通じてOSに「このファイルを読みたい」「ここに書き込みたい」とお願いする。
※https://gihyo.jp/dev/serial/01/perl-hackers-hub/000602 より画像引用
・ファイル記述子を使うことで、プログラムはファイルの詳細な情報(ディスク上の場所やアクセス権限など)を気にせずに、簡単にファイルを操作できる。詳細情報はOSが管理する。
※https://itmanabi.com/filesystem/ より画像引用
※ファイルシステム:OSの「データ管理」という機能の中にある仕組み。データのまとまりを「ファイル」として扱うことで、データを管理しやすくする。
・プログラムがファイルを読み書きしたり、ネットワーク通信をしたりするとき、直接ハードウェアやディスクを操作するのは大変であり危険。そこで、OSが仲介して、プログラムが簡単に安全にリソースを操作できるようにするために、ファイルディスクリプタを使う。
※ファイル記述子:ファイルやソケットなどの入出力資源を識別するための整数値。データの読み書きに使用される。ファイル記述子の数値は、ファイルディスクリプタそのもの。
※https://ja.wikipedia.org/wiki/ファイル記述子 より画像引用
※ファイルディスクリプタ:ファイル記述子に対応する、OSが管理するデータ構造。
Unix系のOS(LinuxやmacOSなど)で、プログラムがファイルやネットワーク接続などの入出力資源を操作するための小さな整数値のこと
※https://koisuru-computer.hateblo.jp/entry/2023/11/02/222741 より画像引用
※プログラムは、ファイルディスクリプタを引数としてシステムコール(OSの機能)を呼び出すことで、入出力操作を行なう。

プロセス
①プログラムの実行中のインスタンス(動作中のプログラム)。
これは「動的」であり、プログラムを実行するとき、それはプロセスとしてメモリにロードされ、CPU がその命令を順次実行する。
これは、本棚から取られ、読まれている本のようなもの。
②オペレーティングシステムが管理する実行中のプログラムのインスタンスを指す。
すべてのプロセスには、一意のプロセス ID(PID)が割り当てられ、オペレーティングシステムがプロセスを識別および管理するために使用する。
③ソースコードを実行するための環境や状態全体。
プログラムが実際に動き出すと「プロセス」になる。プロセスは、プログラムを動かすために必要なもの、メモリ・CPU・ファイルやネットワークなどを全部用意する。ソースコードを実行するための箱のようなもの。
プロセスは、ハードウェアやカーネルの機能に直接アクセスできない。代わりに、OSを介して間接的にアクセスする。
※プロセスはプログラムの動作中の「実体」を指すと言える。
プロセスは、そのプログラムが実行される際に必要なリソース(CPU 時間、メモリ空間など)を持っている。
◎プログラム自体は「静的」な存在である一方、それが OS によってメモリにロードされて実行されるとき、それは「プロセス」として動的に活動する。
各プロセスは、独自のメモリ空間とプロセス制御ブロック(PCB)を持っている。
メモリ空間は、プログラムコード、データ、スタックを格納するために使用され、他のプロセスから保護されているため、各プロセスは独自のリソースを持っている。
メモリ空間(memory space)
特定のプロセスに割り当てられるメモリの領域で、プログラムコード、データ、スタックを格納するために使用される。
・プログラムコード:コンピュータに何をすべきかを指示する命令。
・データ:ユーザーからの入力やファイルから読み込まれたデータなど、プログラムが使用する必要のあるすべての情報。
・スタック:関数の呼び出しを追跡するために使用され、プログラム内の現在の位置や使用中の変数の値などの情報を格納する。
また、このメモリ領域は他のプロセスから隔離されているため、プロセスごとに専用のリソースが確保されていると言える。これにより、一つのプロセスが他のプロセスのメモリに不用意に触れることを防いで、各プロセスを他から独立して動かすことが可能になる。
プロセスのメモリ空間
※https://www.coins.tsukuba.ac.jp/~yas/coins/os2-2010/2011-01-25/ より画像引用
OSが各プロセスに割り当てる独立した仮想メモリ領域のこと。
これにより、プロセスは他のプロセスから隔離され、安全に動作できる。
・プロセスのメモリ空間の構成要素
- テキストセグメント
・実行可能な機械語コードが格納される領域。
・読み取り専用で、共有可能。 - データセグメント
・グローバル変数や静的変数が格納される領域。
・初期化済みデータと未初期化データ(BSSセグメント)に分かれる。 - ヒープセグメント
・動的に確保されるメモリが格納される領域。
・プログラム実行中にサイズが変動。 - スタックセグメント
・関数呼び出し時のローカル変数や戻りアドレスが格納される領域。
・LIFO方式で管理され、サイズは実行時に変動。 - 共有ライブラリセグメント
・共有ライブラリのコードやデータが格納される領域。
・複数プロセスで共有可能。
各プロセスは独自のメモリ空間を持ち、他のプロセスから隔離される。
仮想メモリ:物理メモリと直接対応せず、仮想アドレスを使用。
ファイルの使用方法に応じて、メモリへの読み込み方法やオーバーヘッドが異なる
・通常のファイル読み込み
ファイルの一部または全体がプロセスの仮想メモリ内のバッファにコピーされる。
・メモリマップトファイル
ファイルが仮想メモリ空間にマッピングされ、オンデマンドで物理メモリに読み込まれる。
・ページキャッシュ
ファイルの内容がカーネルのページキャッシュに保持され、プロセスは間接的にアクセスする。
・ダイレクトI/O
ページキャッシュをバイパスし、直接ディスクとやり取りする。
プロセス制御ブロック(process control block, PCB)
OS が各プロセスを管理するために使用するデータ構造。
PCB に含まれるプロセスに関する重要な情報
・プロセスの状態(新規、実行中、待機中、準備完了、終了など)
・プロセス ID
・プログラムカウンタ(次に実行する命令のアドレス)
・CPU レジスタの状態
・CPU スケジューリング情報(プロセスの優先度、スケジュールされる時間など)
・メモリ管理情報(ページテーブルやセグメントテーブルへのポインタなど)
・入出力状態情報 など
子プロセス
コンピュータシステムでは、プロセスは他のプロセスを生成(または作成)する能力がある。
これは「フォーク」(fork)と呼ばれる操作を行うことで可能となる。
親プロセスとは、新しいプロセスを生成した元のプロセスを指す。
親プロセスは通常、一つ以上の新しいプロセス子プロセスを生成できる。
os.fork() ※Python
Linux システムコールの一つ。現在のプロセスの複製を作成する。
新しく作られたプロセスは「子プロセス」であり、元のプロセスは「親プロセス」となる。
子プロセスは親プロセスのほとんど完全なコピーであり、コード、グローバル変数、ヒープ、スタックなどのメモリレイアウトを含めたほとんど全ての内容が複製される。
※親プロセスと子プロセスはそれぞれが独自のプロセス ID(PID)を持つ。子プロセスの PID はシステムによって新しく割り当てられる。この新しい PID は、システムで一意になるように選ばれる。
・fork()の戻り値は、
親プロセス:新しく作成された子プロセスのプロセスID(PID)が返される
子プロセス:0が返される
・os.fork()が呼び出されると、それまでの1つのプロセスが2つのプロセス(親プロセスと子プロセス)に分裂する。
・これら2つのプロセスはそれぞれ別々に、プログラムの残りの部分を実行する。
・コード内で if pid > 0: を使用することで、親プロセスと子プロセスの動作を異なるものにする。
①pid > 0 の場合:コードは親プロセスで実行される。
②pid == 0 の場合:コードは子プロセスで実行される。
os.pipe() ※Python
読み込み専用と書き込み専用の 2 つのファイル記述子(整数)をタプルとして返す関数。
これらのファイル記述子は、データの読み書きに使用される。読み込み専用のファイル記述子を使用してデータを読み出し、書き込み専用のファイル記述子を使用してデータを書き込むことができる。
これらのファイル記述子は一組で、1 つは読み込み専用(通常 fd[0] と表現される)、もう 1 つは書き込み専用(通常 fd[1] と表現される)。
パイプ(pipe)
※https://www.coins.tsukuba.ac.jp/~syspro/2017/oyama/lecture04.html より画像引用
※https://hogetech.info/linux/kernel/ipc より画像引用
※https://qiita.com/penkopenko/items/f28d0b5ef404afd339fa より画像引用
※https://milestone-of-se.nesuke.com/sv-basic/linux-basic/fd-stdinout-pipe-redirect/ より画像引用
プロセスから別のプロセスへ単方向のデータ転送を可能にする仕組み。
データを一時的に保存するために使用されるメモリバッファの一種。
プロセス同士の標準出力(stdout)を標準入力(stdin)に渡すための仕組み。
stdout → パイプ → stdin の流れでデータを渡す
カーネルの pipe() によって、一時的にデータがバッファされる。
カーネルが作る匿名パイプを介して、プロセス間でデータを受け渡す仕組み。
ファイルディスクリプタを介してアクセスされ、ファイルと同様にデータを読み書きすることができる。
親プロセスと子プロセスの間で通信する場合にも使用される。
パイプは通常、一方向の通信チャネルとして機能し、一つのプロセスがパイプにデータを書き込み、別のプロセスがそのデータを読み出す。
パイプはファイル記述子を通じてしかアクセスできない。
なお、双方向の通信を行うにはパイプが 2 つ必要になる。
データストリームの伝送によく使われる。
※データストリーム:あらかじめ決められたサイズや長さのない大量のデータを、ある場所から別の場所に送ること
※https://www.coins.tsukuba.ac.jp/~syspro/2017/oyama/lecture04.html より画像引用
通常のパイプは、親子関係にあるプロセス間でのみ使用できる。
なぜなら、パイプの作成時に生成されるファイル記述子は、パイプを作成したプロセスとその子プロセスでのみ共有されるから。
そのため、親子関係にないプロセス間では、通常のパイプを使ってデータを共有することができない。
この問題を解決する方法に、名前付きパイプがある。
通常のパイプは、ファイルシステム上に名前を持たず、一時的な通信路として機能する。
ソケット(socket)
※https://til.toshimaru.net/2020-11-06 より画像引用
※http://www.otsu.co.jp/OtsuLibrary/jdoc/otsu/hiNote/hiSocket.TCP.ForObject.html より画像引用
ネットワーク上の別のコンピュータにあるプロセスと通信するための仕組み。
データを一時的に保存するために使用されるメモリバッファの一種。
同一のコンピュータ内のプロセス間通信にも使用される。
パイプと異なり、双方向の通信が可能。ソケットはパイプとしても使用できるが、通信を行うためにさらなるオーバーヘッドが発生することに注意。
※オーバーヘッド:ある処理やタスクを実行する際に発生する追加的なコストやリソース消費のこと
ソケットは、クライアントプログラムとサーバプログラムがストリームを通じてデータを交換する必要があるとき、互いに通信するための簡単な方法を提供する。
一般に、プログラム間の通信を行うためのインターフェースとして使用される。
ソケットは、特定のソケットドメインとタイプに基づいて作成され、それぞれがソケットがどのように通信を行うかを決定する。
異なるコンピュータ上のプログラムが通信するためには、ネットワークを介してデータを送受信するための手段が必要。ソケットはその一つの方法で、インターネットプロトコル(IP)を使用して、異なるコンピュータや同一コンピュータ内の別プロセスと通信するための「端点」を提供する。
ソケットはネットワークを通じてデータをやり取りするための「窓口」のようなもの。
この窓口には「ドメイン」と「タイプ」という2つの重要な要素があり、これによってどのように通信するかが決まる。
ソケット通信
※https://envader.plus/article/27 より画像引用
ソケットドメイン:どのネットワークを使って通信するかを決めるもの。ソケットが使用する通信の形式を定義する。これにより、ソケットがどのようなネットワーク上で通信を行うかが決定される。
※https://envader.plus/article/27 より画像引用
・AF_INET(IPv4) → インターネットで一般的に使われる
IPv4を使用して、異なるコンピュータシステム上のプロセス間で通信を行うためのソケットドメイン。
これらのソケットはネットワークソケットとも呼ばれ、そのアドレスは 32 ビット(4 バイト)の IPv4 アドレス。これは、全世界のネットワークを介して通信を行う能力を提供する。
・AF_INET6(IPv6) → 新しいバージョンのインターネット通信
IPv6を使用して、異なるコンピュータシステム上のプロセス間で通信を行うためのソケットドメイン。
これらもネットワークソケットと呼ばれ、アドレスは 128 ビット(16 バイト)の IPv6 アドレス形式で表される。IPv6 は IPv4 の後継となるプロトコルであり、より多くのデバイスをサポートするための拡張アドレッシング能力を提供する。
・AF_UNIX(ローカル通信) → 同じコンピュータ内での通信
一般的に UNIX ドメインソケットまたは IPC ソケットと呼ばれる。
これらのソケットの通信は、同じマシン上で行われ、アドレスはファイルシステム内のパスとして表される。それはファイルシステムを通じて名前付けされ、そのファイルシステムのエントリへのパスがソケットのアドレスとなる。
同じコンピュータ内でプロセス間通信(IPC)を行うための通信手段で、ネットワークを介さずにローカルでデータを送受信する。ファイルシステムのパスを使ってプロセス間の通信を行なう。
UNIXドメインソケットのパスは、サーバーとクライアントが通信するための名前として使われる。
実際にファイルが存在するかどうかは、通信の成否には影響しない。
UNIXドメインソケットのファイルパスは、ディスク上に実際に存在するファイルを指す必要はない。ファイルパスが存在しなくても、bind() 時にソケットファイルが作成されるため、通信は正常に行われる。
ソケットタイプ:データをどのように送るかを決めるもの
アプリケーションが通信する方法を決定する。特に信頼性、メッセージの順序付け、重複の防止といった特性に影響を与える。
それぞれのソケットタイプは、一般的に特定のトランスポート層プロトコルに対応している。例えば、SOCK_STREAM は TCP と、SOCK_DGRAM は UDP とペアリングされる。
TCP・UDP
※https://coderscat.com/tcp-vs-dup/ より画像引用
※https://www.techscore.com/tech/Java/JavaSE/Network/4/ より画像引用
※『イラスト図解式 この1冊で全部わかるWeb技術の基本 第2版』より画像引用
・SOCK_STREAM(ストリーム型)
→ データを順番通りに、確実に届ける(例:電話のような通信)
→ TCP プロトコルで使われる
※精度重視
(詳細)
ストリーム型ソケットは、データの送受信をストリームとして行い、通信が確立された後は、双方向で連続的にデータを送ることができる。
信頼性の高い、順序通りの、エラーのないバイトストリームの伝送を提供する。
これは通常、トランスポート層の TCP プロトコルを使用する。
ソケットが一度接続されると、データはストリームとして送受信される。さらに、このタイプのソケットは帯域外の機能もサポートしており、通常のデータストリーム以外に緊急のデータを送信することも可能。
※バイトストリーム:データがバイト単位で順番に流れていくこと。データを 1つずつのバイト(8ビット)として送る方法で、主に 連続的に送られるデータの流れを指す。
※ストリームとしてのデータ:連続的に生成・転送されるデータの流れを指す。これは、静的なファイルやデータベースに保存されたデータとは異なり、時間とともに変化し続けるという特徴がある。
・SOCK_DGRAM(データグラム型)
→ データを小さなかたまり(パケット)で送るが、順番保証なし(例:手紙のような通信)
→ UDP プロトコルで使われる
※スピード重視
(詳細)
データグラム(独立したパケット)の送受信を提供する。
これは通常、トランスポート層の UDP プロトコルを使用する。
ソケットが一度接続されると、データは個々のパケットとして送受信される。
パケットが必ず送り先に到達することも保証されていない。データグラムが宛先に到達する前に、順序が入れ替わったり、重複したりする可能性もある
※データグラム:コンピュータネットワークにおけるデータの送受信単位の一つで、宛先アドレスなどの制御情報が付加されたデータの小さなまとまりのこと
・SOCK_RAW
ネットワークレベルの生のデータの送受信を提供する。
これは、通常、IP プロトコルなどのネットワーク層のプロトコルを使用する。
ユーザーは、トランスポート層のヘッダ(TCP、UDP など)を自分で作成し、パケットの内容を完全にコントロールできる。しかし、これは一般的にはネットワークプログラミングの専門家や研究者が使用する高度な機能で、通常のアプリケーション開発ではあまり使用されない。
クライアントとサーバーの通信確立プロセス
※※https://envader.plus/article/27 より画像引用
名前付きパイプ(named pipe)
※https://aes256bit.hatenablog.com/entry/2017/12/05/192629 より画像引用
※https://www.scaler.com/topics/linux-named-pipe/ より画像引用
プロセス間通信(IPC)
プロセス間通信とは、コンピュータ上で動作する複数のプロセスが互いにデータをやり取りしたり、処理を同期したりする仕組みのこと。
名前付きパイプは、ファイルシステム上に名前を持つ特殊なファイルとして作成される。
これにより、関連性のないプロセス同士でも、ファイル名を介して通信を行うことができる。
データはFIFO(先入れ先出し)方式で処理される。
・双方向通信が可能。
・関連性のないプロセス間でも通信できる。
・同一マシン上での通信に最適化されている。
パイプに名前をつけて、いつでも、どこでも、誰とでもメッセージ(データ)をやり取りできる仕組み。
名前付きパイプを使うと、別々の場所で動いているプログラム同士でも、名前を使ってデータをやり取りできる。
ファイルシステム上に名前を持つことで、異なるプロセス間で共通のアクセスポイントを提供し、データ交換を可能にする。
※「ファイルシステム上に名前を持つ」:ファイルがファイルシステムによって管理され、一意の名前を持つということ
※FDTに名前をつけることと、名前付きパイプは異なる概念
パイプへの読み書きを行うことでプロセス間の通信を可能にするもの。
ファイル名を引数にとり、その名前の特殊ファイルをファイルシステム内に作成する。このファイル名がパイプの名前となり、プロセスはこのファイル名を使ってパイプから読み込んだり、パイプに書き込んだりすることで相互に通信することができる。
しかし、通常のファイルとは異なり、名前付きパイプはその内容をファイルシステムに保存しない。
その代わり、他のプロセスによって読み込まれるまでは、データをメモリに保存する。このため、名前付きパイプは容量が限られており、大量のデータを転送するのには適していない。
しかし、少量のデータの転送やプロセス間の簡単なコマンドの通信には便利
これにより、異なるプログラム間で連携してデータを処理したり、クライアント・サーバー間で通信を行ったりすることが可能になる。
特徴
・プロセス間のデータ交換に特化したファイル
・通常のファイルは永続的にデータを保存するが、名前付きパイプは一時的なデータ置き場として機能し、プロセスがデータを読み取るとパイプからはデータが消える
・プロセスが読み込みまたは書き込みのためにオープンする必要がある
名前付きパイプは、ファイルシステム上に特定のパス名を持つ特別なファイルとして作成される。
このパス名が、名前付きパイプにアクセスするためのルートとなる。
ファイルシステム上の位置:名前付きパイプは、ファイルシステム上の特定の場所に作成される。この場所は、通常のファイルやディレクトリと同じように、パス名によって指定される。
名前付きパイプは仮想ファイルシステム(VFS)に格納され、VFS は物理的なファイルの保存場所を抽象化する。VFS の仕組みにより、全てのファイルとディレクトリは単一のファイルツリーとして表現され、その物理的な場所に関わらず統一的にアクセスすることが可能になる。
名前付きパイプがファイルシステム上に存在するとはいえ、そのデータはメモリに保存され、ディスクなどの恒久的な記憶装置には保存されない。
→パイプが一時的なデータ転送メカニズムであり、パイプを通じて送信されたデータは読み取られるとすぐに消去されるため。
JSON を使用することで、名前付きパイプのパスをプログラムコードから分離して設定ファイルに記述することができる。
これにより、パイプのパスを変更したい場合は JSON ファイルを編集するだけで済み、プログラムのコード自体は変更する必要がない。
AF_UNIXソケットとの違い
実装
・名前付きパイプは、ファイルシステムを介して通信を行なう。
・AF_UNIXソケットは、ソケットインターフェースを介して通信を行なう。
通信方式
・名前付きパイプは、FIFO(先入れ先出し)方式でデータをやり取りする。
・AF_UNIXソケットは、ストリーム型またはデータグラム型の通信が可能。
インターフェース
・名前付きパイプは、ファイル操作関数(open(), read(), write() など)を使用してアクセスする。
・AF_UNIXソケットは、ソケット関連関数(socket(), connect(), send(), recv() など)を使用してアクセスする。
パイプと名前付きパイプの例え
パイプ
・パイプを用意
・片方の端 からメッセージを入れる
・もう片方の端 からメッセージを受け取る
この方法だと、メッセージを送る側と受け取る側がいつも一緒にいないといけない。
名前付きパイプ
・パイプに名前をつける(例えば、「ひみつの伝言筒」)
・パイプの入り口(メッセージを入れる場所)をみんなが知っている場所(ファイル名)に置く
・パイプの入り口にメッセージを入れる
・データを受け取る側は名前を知っているので、いつでもパイプの出口(メッセージを取り出す場所)からメッセージを受け取ることができる
名前付きパイプを使うと、メッセージを送る側と受け取る側がいつも一緒にいなくても、秘密のメッセージをやり取りできる。
ネットワークを介したプロセス間通信
ソケット通信
ソケットは、ネットワーク上のプロセス間通信を行うためのインターフェース。
TCP/IPなどのプロトコルを使用して、異なるマシン上のプロセス間でデータをやり取りできる。
リモートプロシージャコール(RPC)
RPCは、ネットワーク上の別のマシンで動作するプログラムの関数を、ローカルの関数のように呼び出すための技術。
分散システムなどでよく使用される。
メッセージキュー
メッセージキューは、プロセス間でメッセージを送受信するための仕組み。
非同期通信や、疎結合なシステムを構築する際に役立つ。
API(Application Programming Interface):
Web APIなどのAPIを利用してHTTPなどのプロトコルでネットワークを経由してプロセス間でデータのやり取りが可能。

ファイル読み込みのプロセス
※https://weekly.ascii.jp/elem/000/001/243/1243667/ より画像引用
①プロセスがファイルを開く:
・プロセスはopen()などのシステムコールを使って、ファイルを開く。
・OSはファイルのメタデータ(サイズ、場所など)を確認し、ファイルへのアクセスを準備する。
②ファイルの内容を読み込む
・プロセスはread()システムコールを使って、ファイルの内容をメモリに読み込む。
・OSはファイルの内容をストレージ(HDDやSSD)から読み取り、プロセスのメモリ空間にコピー。
③ファイルを閉じる
・プロセスはclose()システムコールを使って、ファイルを閉じる。
このプロセスでは、ファイルの内容がストレージから直接プロセスのメモリ空間に読み込まれる。

システムコールの流れ
プロセスがOSに指示を出す仕組み
①プロセスがシステムコールを発行
・プロセスは、read()やwrite()などのシステムコールを呼び出す。
(例)ファイルを読み込むためにread()を呼び出す。
②カーネルモードへの切り替え
・システムコールが発行されると、CPUはユーザーモードからカーネルモードに切り替わる。
・カーネルモードでは、OSがハードウェアやメモリに直接アクセスできる。
③OSがカーネル機能を実行
・OSは、システムコールに応じて適切なカーネル機能を実行する。
(例)read()の場合、OSはファイルの内容をストレージから読み取り、プロセスのメモリ空間にコピー。
④結果をプロセスに返す
・OSは、システムコールの結果(成功/失敗、読み取ったデータなど)をプロセスに返す。
・CPUは再びユーザーモードに切り替わり、プロセスは処理を続行する。
・ユーザーモード:プロセスが動作するモード。
ハードウェアやメモリへの直接アクセスが制限される。
・カーネルモード:OSが動作するモード。
ハードウェアやメモリへの完全なアクセス権を持つ。
システムコールは、ユーザーモードからカーネルモードへの切り替えをトリガーし、OSがプロセスの代わりに特権操作を実行する。

プロセス
コンピュータでプログラムを実行するための仕組み。
プログラムが実行される際に、OSによって作成される実行単位。オペレーティングシステムによって管理され、タスクを実行するために必要なリソースを提供する。
コンピュータがプログラムを実行するためのインスタンス。
プロセスは、メモリ空間やCPU時間などのリソースが割り当てられ、実行中のプログラムの個々の実行インスタンスを表す。
実行中のプログラムは、オペレーティングシステムによって「プロセス」として認識され、メモリー領域が割り当てられる。さらに、このプロセスは「スレッド」という、より小さな実行単位に分割され、CPUによって逐次処理される。
コンピュータがタスクを実行するとき、そのタスクはプロセスと呼ばれる個々の単位に分割される。
プロセスは、タスクを完了するために必要な一連の命令のこと。
各プロセスは、独自のメモリ空間とリソースを持ち、他のプロセスから独立して動作する。
プロセスをさらに小さな単位、スレッドに分割することができる。
スレッドは、単一のプロセス内で実行される独立した実行スレッド。複数のスレッドが同じプロセス内で同時に実行されることで、並列処理が可能になり、アプリケーションのパフォーマンスが向上する。
また、スレッドを使用すると、プロセス内で異なるタスクを別々に管理し、より効率的なコードを作成することができる。
※参考:https://it-notes.stylemap.co.jp/programs/understanding-the-basics-of-the-computer-term-process/

データが表示される流れ
print("こんにちは")
①print 関数が「こんにちは」というメッセージを標準出力ストリームに送る。
②標準出力ストリームがそのメッセージをコンソールに送る。
③コンソールに「こんにちは」と表示される。
・データストリーム:データが流れる通り道。
・標準出力ストリーム(stdout):プログラムが結果を表示するための通り道。
・print 関数:画面に何かを表示するための命令。
・コンソール:プログラムの結果が表示される画面。

バッファオブジェクト:データを一時的にためておくための「入れ物」
プログラムがデータを扱うとき、いちいちデータを直接やり取りするのではなく、まずバッファ(一時的な保存場所)にデータをためて、まとめて処理することがある。これによって、効率的にデータを扱うことができる。
ファイルを読み書きするとき、データをいちいち直接読み書きするのではなく、バッファにためてからまとめて処理する
with open("example.txt", "r") as file:
data = file.read() # ファイルの内容をバッファに読み込む
print(data) # バッファからデータを表示
# file.read() はファイルの内容を一度にバッファに読み込み、その後でデータを処理している
・入力バッファ:データを読み込むときに使われるバッファ。
(例)キーボードからの入力やファイルの読み込み時に使われる。
・出力バッファ:データを書き込むときに使われるバッファ。
(例)画面に表示するデータやファイルに書き込むデータを一時的にためておく。
「標準出力ストリームに直接書き込む」:プログラムが結果を画面に表示するための通り道にデータを送ること
標準出力ストリームに直接書き込むことができる理由
→OSが提供する仕組みによるもの
処理の流れ
(1) ファイル記述子(File Descriptor)
OSは、プログラムがファイルやデバイス(例えば画面やキーボード)にアクセスするために、ファイル記述子という番号を割り当てる。
標準出力ストリーム(stdout)には、通常 ファイル記述子1 が割り当てられている。
プログラムは、このファイル記述子1に対してデータを書き込むことで、標準出力ストリームにデータを送ることができる。
(2) システムコール
プログラムが標準出力ストリームにデータを書き込むとき、内部的にはOSのシステムコールという機能を利用している。
例えば、LinuxやmacOSでは write というシステムコールが使われる。このシステムコールにファイル記述子1とデータを渡すことで、標準出力ストリームにデータを送る。
(3) 高レベルな関数(例: print や sys.stdout.write)
Pythonの print 関数や sys.stdout.write は、内部的にこれらのOSの仕組みを利用している。
つまり、print("こんにちは") と書くと、Pythonが裏でシステムコールを呼び出し、ファイル記述子1にデータを書き込んでいる。
stdout をフラッシュする
標準出力ストリームのバッファを空にすること
これによって、バッファにたまっているデータがすぐにコンソール(画面)やファイルなどに送られる。
バッファにデータがたまっている間は、そのデータはまだ出力されない。
・バッファがいっぱいになるまで待つ:データがバッファにたまると、まとめて出力される。
・改行文字 (\n) でフラッシュされる:改行文字が現れると、バッファの内容が自動的にフラッシュされる
※sys.stdout.buffer.write(b'What is your favorite food?\n') のように、改行文字 (\n) を含むデータを sys.stdout.buffer.write で書き込んだ場合、バッファは自動的にフラッシュされない。
これは、sys.stdout.buffer.write が低レベルな操作であり、自動フラッシュの機能を持たないため。
→sys.stdout.buffer.write を使う場合、sys.stdout.buffer.flush() を呼び出してバッファをフラッシュする必要がある。

スレッド(Thread)
プログラムの中で同時に動く小さな処理の単位
・1つのスレッド → 普通のプログラム
・複数スレッド → 同時に処理を実行(並列処理)
シングルスレッド(Single-thread)
・1つのスレッドのみが実行される
・すべての処理が「順番に」実行される(逐次処理)
マルチスレッド(Multi-thread)
・複数のスレッドが並行して動く
・1つのプログラム内で複数の処理を同時に実行可能
・並行処理(Concurrency)や並列処理(Parallelism)を実現
スレッドセーフ(Thread-safe)
複数のスレッド(並行実行される処理)が同時にアクセスしても、データの整合性が保たれること
非スレッドセーフ(Non-thread-safe)
複数のスレッドが同じデータに同時にアクセスすると、問題が発生する状態
「並行処理を扱うプログラム」では、スレッドセーフを意識する必要がある。
※スレッドセーフにするためには、スレッドセーフなキーワード・クラス・データ構造を使用すること。
並行処理(Concurrency)
・複数の処理を「同時に動いているように」見せる。複数の処理を切り替えながら実行。
・1つのCPUでも実現可能(処理を細かく切り替える)
・例:Aの処理を少し → Bの処理を少し → Aの処理に戻る
並列処理(Parallelism)
・実際に複数の処理を「完全に同時に実行」する。複数の処理を完全に同時に実行。
・複数のCPUコアを使って、それぞれのスレッドを実行
・例:CPUコア1がAを処理し、CPUコア2がBを処理する(本当の同時処理)
比較 | 並行処理(Concurrency) | 並列処理(Parallelism) |
---|---|---|
実行方式 | 順番に切り替えながら実行 | 本当に同時に実行 |
CPUの必要数 | 1つでもOK | 複数コアが必要 |
スレッドプール
複数のスレッドを事前に作成し、それらを再利用してタスクを並行処理する仕組み。
主な特徴とメリット
- スレッドの再利用
タスクごとに新しいスレッドを作成するのではなく、既存のスレッドを再利用するため、リソースの無駄を削減できる。 - スレッド数の制御
スレッドプールのサイズを固定することで、システムリソースを効率的に管理できる。 - タスクのキューイング
スレッドがビジー状態の場合、タスクはキューに追加され、スレッドが空いたときに順次処理される。 - パフォーマンス向上
スレッドの作成・破棄にかかるオーバーヘッドを削減し、並行処理の効率を向上させる。
※スレッドプール参考URL

タプル(tuple)
Pythonの基本的なデータ構造の1つ
複数の値を1つのまとまりとして扱うための型。
リストと似ていますが、いくつかの重要な違いがある。
特徴
-
不変(イミュータブル)
一度作成すると、要素の追加・削除・変更ができない。 -
順序を持つ
要素は順番に並んでおり、インデックス(番号)でアクセスできる。 -
異なる型の要素を格納可能
例えば、整数と文字列を同じタプルに入れることができる。 -
丸括弧()で囲む
タプルは通常、(要素1, 要素2, ...)のように丸括弧で囲んで表現する。
使いどころ
-
複数の値をまとめて返す
例えば、os.pipe()は読み取り用と書き込み用の2つのファイル記述子をタプルで返す。 -
不変なデータを扱う
変更されるべきでないデータ(例:設定値)を保持するのに適している。 -
辞書のキーとして使う
タプルは不変なので、辞書のキーとして利用できる
※リストは辞書のキーとして使用することができない。
特徴 | タプル | リスト |
---|---|---|
変更可能か? | 不変(変更不可) | 可変(変更可能) |
記法 | 丸括弧() | 角括弧[] |
用途 | 固定データ 複数返り値 |
動的データ 頻繁な変更 |

ポーリング
コンピュータのプログラムが定期的に特定の状態をチェックするプロセスのこと。
特に、あるリソース(例えば、ファイルやネットワーク接続)が特定の状態になるのを待つ場合によく使われる。

UNIXソケットを使ったプロセス間通信
※https://ascii.jp/elem/000/001/415/1415088/ より画像引用
・サーバー:特定のパス(/tmp/socket_file ※指定したファイルパス)にソケットファイルを作成し、クライアントからの接続を待つ。
・クライアント:サーバーが作成したソケットファイルと同じパスに接続することで、サーバーとの通信を開始する。
ソケット通信は、2つのプロセス(クライアントとサーバー)がデータをやり取りするための双方向の通信路。この通信路を確立するためには、クライアントとサーバーの両方がそれぞれソケットを作成する必要がある。
(例)
server_address = '/tmp/socket_file' の役割
・サーバー:どのパスにソケットファイルを作成するかを指示する。
・クライアント:どのパスにあるソケットファイルに接続すれば良いかを指示する。
server_address は、サーバーとクライアントが通信するための「待ち合わせ場所」を定義する役割を果たしている。
UNIXソケットの場合、ファイルパスはソケットファイルが作成される場所とファイル名を指定する。このファイルは、プロセス間の通信を仲介する役割を果たす。
※ソケットファイル:UNIXドメインソケットにおけるクライアントとサーバーの「待ち合わせ場所」。プロセス間の通信を仲介する特別なファイル。
・通信の窓口
ソケットファイルは、プロセス間でデータを送受信するための窓口として機能する。
クライアントとサーバーは、このファイルを介して互いに接続し、データをやり取りする。
・待ち合わせ場所
サーバーは、特定のパスにソケットファイルを作成し、クライアントからの接続を待つ。
クライアントは、同じパスにあるソケットファイルに接続することで、サーバーとの通信を開始できる。
・名前空間
UNIXドメインソケットでは、ファイルシステムのパスがソケットファイルの名前として使われる。
これにより、クライアントはどのソケットファイルに接続すれば良いかを特定できる。
sock.bind(server_address) は、ソケットを特定のアドレス(この場合はファイルパス)に関連付ける操作です。
名前付きパイプとの違い
ソケットファイル
・ソケットファイルは、より汎用的な通信メカニズムであり、同一マシン上のプロセス間通信だけでなく、ネットワークを介した異なるマシン上のプロセス間通信も可能。
・ソケットは、ストリーム型(TCP)またはデータグラム型(UDP)の通信を提供し、より柔軟な通信が可能。
名前付きパイプ
・名前付きパイプは、主に同一マシン上のプロセス間通信に特化している。
・名前付きパイプは、FIFO(先入れ先出し)方式でデータをやり取りし、単純なデータストリームの通信に適している。
処理の流れ
※https://qiita.com/t_katsumura/items/a83431671a41d9b6358f より画像引用
サーバー
・socket() でソケットを作成。
・bind() でソケットをファイルパス(例えば /tmp/socket_file)に関連付ける。この時、ファイルシステム上にソケットファイルが作成される。bind() することで、ファイルパスがサーバーとクライアントの間で共有される名前として機能する(待ち合わせ場所が決まる)。
・listen() でクライアントからの接続を待機。
クライアント
・socket() でソケットを作成。
・connect() でサーバーのソケットファイルパス(/tmp/socket_file)に接続を試みる。
※クライアントは、サーバーのファイルパスに接続するが、クライアント自身のソケットは一時的なものであり、ファイルパスを持つ必要はない。クライアントのソケットは、内部的にカーネルによって管理される。
接続確立
・サーバーは accept() を呼び出してクライアントからの接続を受け入れる。
・accept() は、クライアントとの通信に使用する新しいソケットと、クライアントのアドレス情報を返す。この新しいソケットは、クライアントとの通信専用のソケットであり、元のソケットとは異なる。こうすることで複数のクライアントからの同時に処理する必要があるので、各クライアントとの通信を独立して管理できる。
ポイント
・サーバーは、bind() で指定したファイルパスにソケットファイルを作成し、クライアントからの接続を待つ。
・クライアントは、サーバーが作成したソケットファイルと同じパスに接続することで、サーバーとの通信を開始する。
・accept() は、クライアントとの接続が確立した際に、新しいソケットを作成する。このソケットが、クライアントとの実際の通信に使用される。
bind() の役割
ソケットを特定のアドレス(この場合はファイルパス)に関連付ける。
bind() は、作成したソケットにファイルシステム上のパス(例:server_address)という名前を与える。
これにより、他のプロセス(クライアント)がこのパスを通じてソケットにアクセスできるようになる。
待ち受けの準備
サーバー側では、bind() を実行後、listen() を呼び出すことで、クライアントからの接続要求を待てる状態になる。
accept()の役割
connection, client_address = sock.accept()
・connection(新しいソケット)
クライアントとの間に確立された新しいソケットオブジェクト。
このソケットオブジェクトを通じて、クライアントとデータを送受信できる。
サーバーは、クライアントとの通信を行うために新しいソケットを作成する。
・client_address (クライアントのアドレス)
クライアントのアドレス情報。UNIXドメインソケットの場合、クライアントのソケットファイルパスが返される。
サーバーは、どのクライアントからの接続であるかを識別するために、クライアントのアドレス情報を取得する。
ソケット通信では、データはバイト列として送受信される。文字列をそのまま送信することはできない。バイト列は、テキストだけでなく、画像や音声などのバイナリデータも扱うことができる。
※https://zenn.dev/ganariya/articles/socket-slide-illustration-go-implement より画像引用
Unix ドメインソケットは、同じマシン上のプロセス間でデータを交換するために使用される。そのため、データはネットワークを介して転送されるのではなく、Linuxの仮想ファイルシステム(VFS)に一時的に保存される。
プロセスがこのパスにデータを書き込むと、他のプロセスがそのデータを読み出すことができる。この方法で、プロセス間でデータのやり取りが行われる。そして、すべての接続が閉じられると、そのソケットのリソース(メモリなど)も解放され、使用されなくなったデータは削除される。これにより、システムのリソースは無駄に消費されることなく、効率的に利用される。
※通常、ネットワーキングにおけるソケットはネットワーク上の特定の IP アドレスとポート番号の組み合わせを指す。

リモートプロシージャコール(remote procedure call, RPC)
※https://zenn.dev/hsaki/books/golang-grpc-starting/viewer/rpc より画像引用
別のコンピュータやプロセス上にある関数やプロシージャ(手続き)を、あたかもローカルにあるかのように呼び出す仕組み。ネットワーク越しの関数呼び出しを簡単にする仕組み。
ネットワーク上の異なるシステム間で関数や手続きを呼び出すための通信手法。
これにより、分散システムやネットワークを介したアプリケーション間で簡単に通信や処理の実行ができるようになる。
ローカルで関数を呼び出す感覚で、別のマシンやプロセス上の処理を実行できるため、分散システムやマイクロサービスアーキテクチャで広く利用されている。
「クライアント」:依頼を行うプログラム
「サーバ」:依頼を受けて仕事を実行するプログラム
RPCの仕組み
※https://apidog.com/jp/blog/introduce-grpc/ より画像引用
①クライアント(呼び出し元)が、ローカルにある関数を呼び出すように見せかけて、実際にはネットワーク経由でサーバー(呼び出し先)にリクエストを送信する。
②サーバーは、受け取ったリクエストを処理し、結果をクライアントに返す。
③クライアントは、サーバーからの応答を受け取り、それをローカルの関数の戻り値として扱う。
この一連の流れは、開発者から見ると「ローカルで関数を呼び出している」ように見えるため、ネットワーク通信の複雑さを意識せずにプログラムを書くことができる。
RPCのメリット
- 開発が簡単
ネットワーク通信の詳細を意識せず、ローカル関数を呼び出すようにプログラムを書ける。 - 分散システムの構築が容易
複数のマシンやサービス間で処理を分散させることができる。 - 言語やプラットフォームに依存しない
RPCプロトコル(例: gRPC, JSON-RPC)を使えば、異なるプログラミング言語やOS間でも通信が可能。
RPCのデメリット
- ネットワークの遅延
ローカル関数呼び出しと比べて、ネットワーク通信による遅延が発生する。 - エラーハンドリングが複雑
ネットワーク障害やサーバー側のエラーに対処する必要がある。 - セキュリティリスク
ネットワークを介するため、データの暗号化や認証が必要になる。
RPCの代表的なプロトコル
- gRPC
Googleが開発した高性能なRPCフレームワーク。HTTP/2とProtocol Buffersを使用。 - JSON-RPC
JSON形式でデータをやり取りするシンプルなRPCプロトコル。 - XML-RPC
XML形式でデータをやり取りする古くからあるRPCプロトコル。

リモートプロシージャコール(remote procedure call, RPC)
関数の実行とパラメータの管理
サーバがリクエストを受け取ると、それは一連の命令、つまり関数を実行する必要がある。
しかし、サーバがどの関数を実行するべきかを知るためには、何らかの方法でリクエストと関数を関連付ける必要があるため、<string, callable> というキーと値のペアを格納したハッシュマップを使って、一種の目次を作成する。
"string" はリクエストが指定する特定の関数を識別するキー(例えば関数の名前)、"callable" はその関数自体を指す。
リクエストがサーバに到着すると、サーバはテーブルを参照し、リクエストに指定されたキーに関連付けられた関数を探す。そしてその関数を呼び出し、リクエストから受け取ったパラメータを渡す。これにより、各リクエストはそれに対応する適切な関数で処理される。
また、パラメータの検証を行うために "param_types" を使用することも可能。これにより、関数を実行する前に、パラメータが適切な形式で、関数の要件を満たしているかどうかを確認できる。
サーバとクライアント間の通信にはソケットインターフェースが使用される。
これはネットワーク上の異なるコンピュータ間でデータを交換するための一般的な方法。
この通信をより容易に管理するために、ソケットのネットワーク接続を処理するラッパークラスや構造体を作成し、これをメインプログラムから分離することが推奨される。

ネットワーク
コンピュータネットワーク
異なるコンピュータシステム間の相互接続を指す概念であり、この接続は通常、データリンクにより実現される。
データリンク
直接連結された機器群が通信を行うための規約(プロトコル)やネットワークを指し示す。
その通信媒体はデータリンクの種類により異なる。
通信媒体は物理的な接続のことで、ツイストペアケーブル(LANケーブル)、同軸ケーブル、銅線、光ファイバー、さらには電波なども含まれる。
伝送速度:データリンク上でデータが転送される速度
1 秒あたりのビット数(Mbps)で表される。
レイテンシー(遅れ)は、データの最初のビットが受信機に到達するまでの時間を指し、秒単位(ms)で測定される。
データをネットワークを介して送信する方法
※https://www.slideserve.com/dorie/4547909 より画像引用
回線交換
回線交換においては、コンピュータは回線交換装置と接続され、これら装置間は多数の通信回線で接続される。通信が行われる際には、その通信が断絶するまで、特定の回線が専有的に使用される。この結果、他のユーザーはその通信が完結するまで該当の回線を使用してデータを転送することは出来ない。
パケット交換
※https://www.slideserve.com/dorie/4547909 より画像引用
パケット交換は、メッセージやファイル全体を一括で送信するのではなく、パケットと呼ばれる小規模な断片に分割し、これを送信する。各パケットには宛先アドレスと送信順序の情報が含まれており、ネットワークはこれにより送信先とパケットを正しい順序で組み立てる。
※https://www.medical-design.co.jp/archives/blog/1787 より画像引用
これらのパケットはパケット交換機と回線を通じて目的地まで送られる。
パケット交換機は、ルーターのような装置で、宛先アドレスに基づいて各パケットの最適な経路を決定し、パケットを宛先に転送する役割を担っている
これにより、複数のパケットが異なる経路を通り、より速く目的地に到達することができ、ネットワークの性能が向上する。
全てのパケットが宛先に到着すると、元のメッセージやファイルが再構成される。パケットが回線を通過している間でも、回線に空きがあれば、一つの回線を複数のユーザーで共有することが可能となる。
近年、インターネットやその他のコンピュータネットワークにおいては、パケット交換方式が主流となっている。
IP アドレス
※https://atmarkit.itmedia.co.jp/ait/articles/0212/06/news002_2.html より画像引用
ネットワークに接続されている各コンピュータまたはパケット交換機に割り当てられる一意の識別子。
IP アドレスは、IANA(internet assigned numbers authority)という機関によって管理されている。この機関は、全世界の地域インターネットレジストリ(RIR: regional internet registry)へ IP アドレスの配布を行なう。そして、RIR は各国の国別インターネットレジストリ(NIR: national internet registry)に対してさらに IP アドレスを配布する。
最終的に、ローカルインターネットレジストリ(LIR: local internet registry)へ IP アドレスが配布され、それがユーザーに提供される。
なお、日本における RIR は APNIC であり、NIR は JPNIC となります。そして、ISP は LIR に該当する。
ISP と契約を結んだユーザーがインターネットにアクセスするには、ユニークな IP アドレスが必須になる。IP アドレスの割り当て方式は ISP との契約形態により、動的割り当てと静的割り当ての二つが存在する。
※https://www.nttpc.co.jp/column/network/fixed_ip.html より画像引用
動的 IP アドレス
ISP からユーザーのデバイスへ動的に割り当てられるアドレスのこと。
デバイスがインターネットに接続する度に IP アドレスが変更される可能性があり、一般的に家庭でのインターネット接続契約ではこの方式が適用される。
静的 IP アドレス
ISP と契約したユーザーが常に同一の IP アドレスを利用する方式。
この方式は公開 Web サーバやウェブカメラ等、恒久的に一定の IP アドレスを必要とするデバイスに対して有用。
静的 IP アドレスは、主にビジネスや企業の環境で活用される。
インターネットサービスプロバイダ(ISP)
※https://www.doracoon.net/navi/solutions/solutions-4210/ より画像引用
インターネットでデータを送受信するために必要なインフラを提供する企業。
このインフラには、パケットを宛先の IP アドレスに送信するために使用されるネットワーク機器やアクセスネットワークが含まれる。
インターネットサービスプロバイダ(ISP)の役割
顧客に IP アドレスを配布し、その結果としてインターネットサービスを提供すること。
アクセスネットワーク
※https://drivenets.com/resources/education-center/what-is-a-core-network/ より画像引用
インターネットネットワークの一部を構成し、加入者宅と、コアインターネットの始点となるルーター(PE, Provider Edge)に接続する回線で構成されている。これらのアクセスネットワークは、各地域の ISP が提供する。
ユーザーがインターネットや通信サービスに接続するためのネットワーク部分を指す。
これは、家庭やオフィスからインターネットサービスプロバイダ(ISP)や通信事業者のネットワークに接続するまでの経路をカバーしている。
アクセスネットワークの種類
①有線アクセスネットワーク
・光ファイバー、ADSL、ケーブルテレビ回線など、物理的なケーブルを使用。
・高速で安定した通信が可能。
②無線アクセスネットワーク
・モバイルネットワーク(LTE、5G)、Wi-Fiなど、無線技術を使用。
・移動中でも接続可能で柔軟性が高い。
コアインターネット
バックボーンとも言われ、インターネットを形成する高速かつ大容量のネットワークを指す。
これはルーター、スイッチ、その他のネットワーク機器の集合体であり、異なる地域や国間のデータ転送を担当する。
アクセスネットワークへの接続が確立すると、エンドユーザーのデバイスは、インターネット上の他のデバイスとデータの送受信が可能になる。これらのデータは、コアインターネットを介して送信される。コアインターネットは、多数のルーターやその他のネットワーク機器で成り立ち、世界中のどの地点からでも、データを適切な宛先へと転送することが可能。
家庭でインターネットにアクセスする場合、ISP に接続する必要がある。
接続方法例
① FTTH(Fiber to the Home)
FTTH は光ファイバーを使ってインターネットに接続し、ONU と呼ばれる機器が必要。
ケーブルは、ケーブルテレビと同じケーブルを使用してインターネットに接続し、ケーブルモデムと呼ばれる装置が必要。
② DSL(Digital Subscriber Line)
電話回線を利用してインターネットに接続する方法。
FTTH に比べて転送速度は低下します。
③モバイルネットワーク
※https://k-tai.watch.impress.co.jp/docs/column/fujioka/1558037.html より画像引用
5G や 4G 等の無線通信を利用してインターネットに接続する方法。
これらのネットワークは、電波を介して基地局に接続し、その基地局がコアインターネットへ接続する。
パケット転送の仕組み
ローカルエリアネットワーク(LAN)
※https://qa.elecom.co.jp/faq_detail.html?id=4159&category=152 より画像引用
家庭やオフィスの各デバイスが相互に通信し、リソースを共有できるよう設計されたネットワーク環境。
家庭やオフィスなどの狭い範囲にあるパソコンなどの機器同士を接続したもの。家庭のパソコンを LAN に接続するには、スイッチやルーターに接続する。
家庭内やオフィス内で複数のデバイス間の通信が必要となる際、それは一般的に ISP を介さない。
LAN 環境には、ルーターやスイッチといったデバイスが配置され、これらは受信したパケットデータを適切な家庭やオフィス内のデバイスに向けて転送する。
※有線の場合も無線の場合も同様
デバイスから他のデバイスへパケットを送信する際には、まずそのパケットは LAN 内の最初のルーターに到達する。ルーターはパケットを受け取ると、その宛先の IP アドレスを確認し、次にパケットを転送すべき宛先を探す。この操作は、ルーターが特定の宛先 IP アドレスに到達するためにどのリンクを使用すべきかを参照するルーティングテーブルを使用して行われる。
多くのルーターでは、パケットを転送する前に、まず受信したパケット全体を一時的にメモリ上に保存する。このステップを経ることで、ルーターはパケットにエラーがないか、あるいは悪意を持ったパケットでないことを確認してから転送を行うことが可能となる。
さらに、ルーターはパケットの転送先を特定するために、そのパケットの IP ヘッダを解析する。この情報を元に、ルーターはルーティングテーブルを参照し、パケットを次にどの位置に転送すべきかを決定する。
LAN で使用される IP アドレスは、一般的には「プライベート IP アドレス」と呼ばれ、これらはグローバルには一意でないため、公開インターネット上での通信には使用できないが、ローカルネットワーク内での通信には活用される。
IANA(Internet Assigned Numbers Authority)は、LAN 内のプライベートネットワークで使用するために、特定の IP アドレスの範囲を指定している。
これらの範囲には、以下のものがあります。
・10.0.0.0 ~ 10.255.255.255
・172.16.0.0 ~ 172.31.255.255
・192.168.0.0 ~ 192.168.255.255
これらの IP アドレスの範囲は、ISP から固有の IP アドレスを取得する必要がなく、誰でも自宅や会社でプライベートネットワークを構築するために使用することができる。
ルーターにつながる全てのデバイスには、一意のローカル IP アドレスが配分される。
※サブネットマスク(Subnet Mask)
※https://active.nikkeibp.co.jp/atcl/act/19/00395/072100002/ より画像引用
IPアドレスのうち「ネットワーク部」と「ホスト部」を区別するための数値。
IPアドレスと組み合わせて使用され、ネットワークの範囲を定義する役割を果たす。
- IPアドレスの構造
IPアドレス(IPv4)は、32ビットの数値で表され、通常は「192.168.1.1」のようにドットで区切られた4つの数値(オクテット)で表現される。このIPアドレスは、以下の2つの部分に分かれます。
・ネットワーク部:ネットワーク自体を識別する部分。
・ホスト部:そのネットワーク内の個々のデバイス(ホスト)を識別する部分。
サブネットマスクは、この「ネットワーク部」と「ホスト部」の境界を指定する。
NAT(Network Address Translator)
※https://baremetal.jp/blog/2023/09/08/1298/ より画像引用
プライベートネットワーク内のデバイスがインターネットと通信する際に、IPアドレスを変換する技術。
インターネット上で使用できるパブリックIPアドレスは限られているが、NATを使うことで、1つのパブリックIPアドレスを複数のプライベートIPアドレスで共有できる。NATは、ルーターやファイアウォールなどのネットワーク機器で動作する。
・プライベートIPアドレス:家庭や企業内のローカルネットワークで使用されるIPアドレス
インターネット上ではルーティングされない。(例: 192.168.1.10)
・パブリックIPアドレス:インターネット上で一意に識別されるIPアドレス。インターネットと通信するために必要。(例: 203.0.113.1)
NAPT(Network Address Port Translator)
1つのパブリックIPアドレスを複数のプライベートIPアドレスで共有するための技術。
NAPTは、IPアドレスだけでなく、ポート番号も利用して通信を区別する。これにより、1つのパブリックIPアドレスで複数のデバイスからの通信を同時に処理できる。通信ごとに動的にポート番号を割り当てる。
※ポート番号:通信の「宛先アプリケーション」を指定するための番号
ISP の階層構造と通信料金体系
コアネットワークは、ISP の階層構造で構成されている。
このネットワークの下層には、特定の地域の顧客にインターネットサービスを提供するローカル ISP が存在する。これらのローカル ISP は全てのローカル ISP に接続することは不可能であるため、地域 ISP と呼ばれるより大規模な ISP に接続する。
地域 ISP は、次に更に規模の大きな ISP である Tier-1 ISP に接続する。これらは全ての地域 ISP を結びつけ、グローバルなインターネットサービスを提供する最大規模の ISP 。
ローカル ISP は、地域 ISP との間のインターネットトラフィック量に基づいて地域 ISP に料金を支払う。これはトランジット(transit)と称される。
Tier-1 ISP は、階層の最上層に位置し、これらの ISP は大規模なネットワークや高速回線など、多くのリソースを保有している。彼らはインターネットアクセスのために他の ISP にお金を払う必要はなく、その代わりに同層の他の ISP とピアリング(peering)と呼ばれる契約を結んでいる。
ピアリングとは、2 つの ISP が互いに課金することなく、インターネットトラフィックを交換する相互協定のこと。これにより、ISP は顧客により良いサービスを提供でき、コストを削減できるため、双方の ISP が交換による利益を得ることができる。

ミドルウェア(Middleware)
アプリケーションと基盤ソフトウェア(OSやデータベースなど)の間で動作するソフトウェアのこと。
プログラムコードで構成され、OS上で実行される。
※https://xtech.nikkei.com/it/article/COLUMN/20081220/321788/ より画像引用
※https://circleci.com/ja/blog/what-is-middleware/ より画像引用
※
https://medium-company.com/ミドルウェア/ より画像引用
特徴
仲介役としての機能
アプリケーションと基盤ソフトウェアの間でデータのやり取りを仲介する。
(例)データベースへの接続管理、メッセージング、セッション管理など。
共通機能の提供
アプリケーション開発者が頻繁に必要とする機能(例: 認証、ロギング、キャッシュなど)を提供する。
プラットフォームの抽象化
異なるOSやデータベース間の違いを吸収し、アプリケーションが特定の環境に依存しないようにする。
※ミドルウェアとWeb三層構造は関連性があるが、それぞれ異なる概念であることに注意
ミドルウェアは、Web三層構造の各層で利用されることがあるが、ミドルウェア自体が「3つの層をまとめた概念」というわけではない。むしろ、ミドルウェアは各層の間や内部で動作するソフトウェアとして機能する。
プレゼンテーション層
ミドルウェア:Webサーバー(例: Apache, Nginx)
Webサーバーは、クライアントからのリクエストを受け取り、静的コンテンツを配信したり、アプリケーション層にリクエストを転送したりする。
アプリケーション層
ミドルウェア:アプリケーションサーバー(例: Tomcat, Node.js)
アプリケーションサーバーは、ビジネスロジックを実行し、データ層とやり取りする。
データ層
ミドルウェア:データベース管理システム(例: MySQL, PostgreSQL)
データベース管理システムは、データの保存と取得を行なう。

ミドルウェアがサーバー間のデータのやり取りを仲介する仕組み
プロトコルの変換
異なるサーバー間で異なるプロトコルが使用されている場合、ミドルウェアがプロトコルを変換する。
(例)HTTPリクエストをデータベースのSQLクエリに変換する。
メッセージのルーティング
メッセージを適切なサーバーやアプリケーションに転送する。
(例)APIゲートウェイがクライアントからのリクエストを適切なマイクロサービスに転送する。
データのバッファリング
サーバー間のデータのやり取りを一時的に保存し、効率的に処理する。
(例)メッセージキューがメッセージを一時的に保存し、受信側が準備できたときに配信する。

プログラムの動作
プログラムの動作
通常のプログラム
Javaプログラム
コンパイルとインタープリタ
※https://qiita.com/KenyaSaitoh/items/22f32b9d7aea5844d779#112-javaの歴史 より画像引用