C++ でシステム コールを作成する
このチュートリアルでは、C++ で書かれたプログラムから write システムを呼び出す方法について説明します。 まず、システム コール、特に write システム コールとそのプロトタイプをすばやく更新します。
後で、C++ プログラムからの write システム コールの呼び出しについて説明します。
C++ でのシステム コール
すべてのオペレーティング システムは、システム コールを通じて一連のサービスを提供します。 これは、コンピューター プログラムがオペレーティング システムからサービスを要求するメカニズムです。
システム コールは、次のサービスを提供します。
- プロセスの作成と管理
- 主記憶管理
- ファイルおよびファイル システムの管理
- デバイスの入出力
- 保護
- ネットワーキング
プログラムが必要とする最も頻繁なサービスは入出力です。 次に、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つのパラメーターの詳細は次のとおりです。
- ファイル記述子
fdは、ファイルを開く呼び出しから取得されます。 これは整数値です。 値0、1、2は、それぞれ標準入力、標準出力、標準エラーに与えることもできます。 - データが一次メモリに格納されているメモリ内のバッファ
bufへのポインタ。 - バッファー
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 配列から書き込む文字数を指定します。
count は write() API 呼び出しから返される整数値です。 失敗した場合、値は -1 になります。 したがって、カウントを確認し、それに応じてエラー メッセージを出力します。
書き込み操作が成功した場合、count の値は正になり、if 条件はファイルに正常に書き込まれた合計バイト数を示します。

最初の出力値 3 は、ファイルが正常に開かれたことを示しています。 2 行目の 50 は、50 バイトすべてが正常に書き込まれたことを示しています。
次に、open ステートメントを変更しました。
fd = open("abc.txt", O_RDONLY | O_CREAT | O_TRUNC, 0644);
O_WRONLY を O_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 です。 したがって、エラー メッセージが出力されます。