Linuxシステム応用プログラミング——エラー処理(errno)


1.errno変数ファイルには、記号errnoと、文字Eで始まる様々な定数が定義されている.たとえば、errnoが定数EACCESに等しい場合、権限の問題が発生したことを示します(たとえば、要求されたファイルを開くのに十分な権限がありません).
UNIX関数でエラーが発生すると、常に負の値が返され、整数変数errnoが追加情報を含む定数に設定されます.たとえばopen関数が正常に実行されると、エラーが発生すると-1を返す非負のファイル記述子が返されます.Openエラーでは、約15種類のerrno値(ファイルが存在しない、権限の問題など)があります.
errnoには2つのルールがあるはずです.
ルール1:エラーがなければ、errnoの値はインスタンスによって消去されません.したがって、errnoの値は、関数の戻り値がエラーを示す場合にのみ検証されます.
ルール2:いずれの関数もerrnoの値を0に設定、で定義された定数はすべて0ではありません.
 
エラーフラグerrnoは整数値であり、これはユーザプロンプトによくありません.C規格では、エラー情報の印刷を支援する2つの関数が定義されています.
1)、strerror()
#include <string.h>
#include <errno.h>

char *strerror(int errnum);

戻り値:メッセージ文字列へのポインタ
この関数は、通常errno値であるerrnumをエラー情報文字列にマッピングし、この文字列のポインタを返します.
2)、perror()perror関数はerrnoの現在の値に基づいて、標準エラーにエラー情報を生成し、返します.
#include <stdio.h>

void perror(const char *msg);

まずmsgが指す文字列を出力し、次にコロン、スペース、次にerrno値に対応するエラー情報を出力し、最後に改行します.
例:
次のコードでは、この2つのエラー関数の使用方法を示します.
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
    fprintf(stderr, "EACCES: %s
", strerror(EACCES)); errno = ENOENT; perror(argv[0]); exit(0); }

実行結果は次のとおりです.
fs@ubuntu:~/qiang/error$ ./error 
EACCES: Permission denied
./error: No such file or directory
fs@ubuntu:~/qiang/error$ 

  2. すべてのエラーメッセージを印刷
C標準ライブラリ定義sys_nerrはエラー情報の合計数を記録するために使用され、以下のプログラムはループによってすべての情報を印刷する.
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    int idx = 0;
    for (idx = 0; idx < sys_nerr; idx++) {
        printf("Error #%3d: %s
", idx, strerror(idx)); } exit(0); }

実行結果は次のとおりです.
fs@ubuntu:~/qiang/error$ ./print_err 
Error #  0: Success
Error #  1: Operation not permitted
Error #  2: No such file or directory
Error #  3: No such process
Error #  4: Interrupted system call

....

Error #132: Operation not possible due to RF-kill
Error #133: Unknown error 133
Error #134: Unknown error 134
fs@ubuntu:~/qiang/error$ 

3.マルチスレッド拡張スレッドをサポートする環境では、複数のスレッドがプロセスアドレス空間を共有し、各スレッドには、1つのスレッドが別のスレッドに干渉しないように、独自のローカルerrnoがある.
関数strerror()はスレッドが安全ではありません.この関数はerrnumに対応する文字列を静的バッファに保存し、バッファのポインタを返すためです.別のスレッドがstrerror()を呼び出すと、静的バッファの内容が再設定されます.
 
4.エラー回復はで定義された様々なエラーは、致命的と非致命的の2つに分類される.致命的なエラーの場合、リカバリ動作は実行できません.最大1つのエラー情報をユーザー画面に印刷するか、エラー情報をログファイルに書き込んで終了します.非致命的な誤りに対しては,より適切に処理できる場合がある.