C++ でシステム コールを作成する

Abdul Mateen 2024年2月15日
  1. C++ でのシステム コール
  2. C++ の write システム コール
C++ でシステム コールを作成する

このチュートリアルでは、C++ で書かれたプログラムから write システムを呼び出す方法について説明します。 まず、システム コール、特に write システム コールとそのプロトタイプをすばやく更新します。

後で、C++ プログラムからの write システム コールの呼び出しについて説明します。

C++ でのシステム コール

すべてのオペレーティング システムは、システム コールを通じて一連のサービスを提供します。 これは、コンピューター プログラムがオペレーティング システムからサービスを要求するメカニズムです。

システム コールは、次のサービスを提供します。

  1. プロセスの作成と管理
  2. 主記憶管理
  3. ファイルおよびファイル システムの管理
  4. デバイスの入出力
  5. 保護
  6. ネットワーキング

プログラムが必要とする最も頻繁なサービスは入出力です。 次に、write システム コールについて説明します。

プログラムは、write システム コールを介して、基盤となるオペレーティング システムにデバイスへの書き込みを要求します。

write 呼び出しに進む前に、ファイル記述子について理解することが重要です。

ファイル記述子

Unix および Unix ベースのオペレーティング システムでは、ファイル記述子は、ファイルまたはソケットやパイプなどの他の IO リソースを一意に識別する番号です。

通常、ファイル記述子は負でない整数値です。 プログラムは、ファイル記述子を介して IO 用のファイルにアクセスします。

ライブラリ関数は IO を処理し、ファイル記述子をパラメーターとして受け取ります。

最初のステップは、IO 用のファイルにアクセスするために、名前 (ファイルがプログラムのフォルダーにない場合は絶対パス/相対パス) でファイルを開くことです。

open 関数がファイルを開くことに成功した場合 (つまり、同じ名前のファイルが存在し、ユーザーが必要な権限を持っている場合)、ファイル記述子を返します。

int fd = open("abc.txt", O_RDONLY | O_CREAT);

open 関数には 2つのパラメーターがあります。 最初のパラメーターはファイル名で、2 番目のパラメーターは読み取りモード (読み取り専用モード、書き込み専用モードなど) です。

ファイルに対する後続の IO 操作は、ファイル記述子を介して実行されます。

C++ の write システム コール

write システム コールは、オペレーティング システム カーネルが提供する最も基本的なルーチンの 1つです。 プライマリ メモリ (バッファ) からファイル (一部のハードウェア デバイスに格納されている) にデータを書き込みます。

write() システム コールは、buf が指すメモリ バッファから、ファイル ディスクリプタが参照するファイルに最大 count バイトを書き込みます。

これは、バイトしか理解できない低レベルの関数です。 クラスのように、write 呼び出しを使用してレコードを書き込むことはできません。

したがって、複雑な I/O を実行するには、高レベルの入出力関数 (printf() など) が不可欠です。

最初に、データをファイルに書き込むために使用される write システム コールの構文を見てみましょう。

ssize_t write(int fd, const void *buf, size_t count);

write 関数の 3つのパラメーターの詳細は次のとおりです。

  1. ファイル記述子 fd は、ファイルを開く呼び出しから取得されます。 これは整数値です。 値 012 は、それぞれ標準入力、標準出力、標準エラーに与えることもできます。
  2. データが一次メモリに格納されているメモリ内のバッファ buf へのポインタ。
  3. バッファー buf から fd が指すファイルに書き込まれる count で指定されたバイト数。

ssize_t および size_t は、それぞれ、stddef.h で定義されている符号付きおよび符号なしの整数データ型です。

戻り値

write 関数は符号付きの値を返します。 成功すると、ファイルに正常に書き込まれたバイト数を返します。これは、指定された count よりも少ない場合があります。

合計書き込みバイト数が count よりも少ない理由として考えられるのは、出力デバイスのメモリがいっぱいであるか、ソースの書き込みバッファーに書き込む chars の数が count で指定された数よりも少ない可能性があります。

エラーの場合、write システム コールは -1 を返し、発生したエラーを示すために errno が設定されます。

ここに、write システム コールを使用してファイルに書き込む完全なプログラムがあります。

#include <errno.h>
#include <fcntl.h>

#include <iostream>

extern int errno;

using namespace std;

int main() {
  int fd, count;
  fd = open("abc.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
  cout << "File descriptor = " << fd << '\n';
  if (fd == -1) {
    // print which type of error have in a code
    printf("Error Number % d\n", errno);
    // print program detail "Success or failure"
    perror("Program");
  }
  char buff[] = "This is a test program to check write system call.";
  count = write(fd, buff, 50);
  if (count == -1)
    cout << "Error writing in file";
  else
    cout << "Number of bytes written to the file: " << count << '\n';
  close(fd);
  return 0;
}

最初のヘッダー ファイル fcntl.h には、write システム コールがあります。 2 番目のヘッダー ファイルにはエラー関数があります。

open 関数呼び出しでは、新しいファイル名 abc.txt を書き込みモードで作成します。 ファイルは以前に存在する可能性がありますが、O_TRUNC を使用すると、以前の内容が削除され、新しい空のファイルが作成されます。

コード 0644 は、ファイルのパーミッションを示します。 次に、if 条件は、ファイルが正常に開かれたかどうかをチェックします。

失敗した場合、エラーメッセージが表示されます。

次に、サンプル テキストを含む文字配列 (バッファーとして使用) を作成しました。 最後に、ファイルに書き込みます。

3 番目のパラメーターは 50 で、buff 配列から書き込む文字数を指定します。

countwrite() API 呼び出しから返される整数値です。 失敗した場合、値は -1 になります。 したがって、カウントを確認し、それに応じてエラー メッセージを出力します。

書き込み操作が成功した場合、count の値は正になり、if 条件はファイルに正常に書き込まれた合計バイト数を示します。

書き込みシステムコール

最初の出力値 3 は、ファイルが正常に開かれたことを示しています。 2 行目の 50 は、50 バイトすべてが正常に書き込まれたことを示しています。

次に、open ステートメントを変更しました。

fd = open("abc.txt", O_RDONLY | O_CREAT | O_TRUNC, 0644);

O_WRONLYO_RDONLY に置き換えたことに注意してください。その結果、出力は次のようになります。

File descriptor = -1
Error Number  13
Program: Permission denied
Error writing in file

コンテンツを切り捨てて既存のファイルを読み取りモードで開くことはできないため、open 操作は失敗しました。

失敗の結果、ファイル記述子が -1 になっていることがわかります。 また、書き込み操作が失敗します。

write システム コールの前にファイルを閉じると、結果として write システム コールによる操作が失敗します。 この場合、出力は次のようになります。

File descriptor = 3
Error writing in file

ここでは、ファイル記述子は -1 ではありませんが、ファイルは閉じられています。 したがって、write システム コールは失敗します。

write システムコールによって返される値は -1 です。 したがって、エラー メッセージが出力されます。