LoginSignup
0
0

`write`/`read`と`send`/`recv`の違い命名と責務による誤解を解く

Last updated at Posted at 2024-05-07

ソケットプログラミング:write/readsend/recvの責務と関係

ソケットプログラミングにおいて、write/readsend/recvの違いに戸惑う人は多いでしょう。この記事では、Unixの「Everything is a file」の思想による抽象化の背景を踏まえ、これらの関数の責務と関係を説明し、なぜ両方の関数で通信が可能なのかを解説します。

Everything is a fileの思想とソケット

Unixシステムでは、「Everything is a file」という設計思想があります。この思想に基づき、ネットワークソケットもファイルディスクリプタとして抽象化されます。つまり、ソケットに対してファイル操作関数(write/read)を使用することができるのです。

この抽象化により、プログラマはファイルI/Oと同じインターフェースでネットワークI/Oを扱うことができ、コードの統一性と可読性が向上します。

ユーザー空間とカーネル空間の責務

ソケット通信では、ユーザー空間とカーネル空間が異なる責務を担っています。

ユーザー空間の責務:

  • ソケットの作成とファイルディスクリプタの管理
  • write/readsend/recv関数を使ってソケットにデータを書き込み、読み取る

カーネル空間の責務:

  • ソケットバッファの管理
  • プロトコルスタックの処理
  • ネットワークデバイスドライバの制御
  • 実際のデータ転送

write/read関数の責務

write関数は、ファイルディスクリプタに対してデータを書き込みます。ソケットの場合、write関数を呼び出すと、データはカーネル空間のソケットバッファにコピーされます。

read関数は、ファイルディスクリプタからデータを読み取ります。ソケットの場合、read関数を呼び出すと、カーネル空間のソケットバッファからデータがユーザー空間にコピーされます。

send/recv関数の責務

send関数とrecv関数は、ソケット通信に特化した関数です。これらの関数は、write/read関数と同様に、データをソケットバッファにコピーしたり、ソケットバッファからデータを読み取ったりします。

ただし、send/recv関数は追加のフラグ引数を受け取ることができ、送受信動作をより細かく制御できます。

データ転送の責務はカーネルにある

重要なのは、実際のデータ転送はカーネルが担っているということです。ユーザー空間のwrite/readsend/recv関数は、データをソケットバッファにコピーしたり、ソケットバッファからデータを読み取ったりするだけです。

データがソケットバッファに書き込まれると、カーネルが以下の処理を行います:

  1. プロトコルスタックでのデータ処理
  2. ルーティングとARP
  3. ネットワークデバイスドライバへのデータ受け渡し
  4. ネットワークインターフェイスカード(NIC)からの送信

まとめ

Unixの「Everything is a file」の思想により、ネットワークソケットはファイルディスクリプタとして抽象化されています。これにより、write/read関数を使ってソケット通信を行うことができます。

ソケット通信では、ユーザー空間の責務はソケットへのデータの書き込みと読み取りであり、実際のデータ転送はカーネル空間の責務です。write/readsend/recv関数は、データをソケットバッファにコピーしたり、ソケットバッファからデータを読み取ったりするだけで、直接的なデータ転送は行いません。

したがって、write/read関数でもソケット通信が可能なのは、カーネルがソケットバッファに書き込まれたデータを元に通信を行うからです。send/recv関数は、送受信動作をより細かく制御できる点でwrite/read関数と異なります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0