モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)
目次目次を開く/閉じる

Linux システムコールを C 言語から利用するための基本的な知識

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2018/05/27
最終更新最終更新
2020/10/01
記事区分記事区分
一般公開

目次

    アカウント プロフィール画像 (サイドバー)

    プログラミング教育者。ScratchやPythonを教えています。

    0
    ステッカーを贈るとは?

    C 言語から Linux OS の各システムコールを利用する場合を想定して、関連情報をまとめます。

    システムコールについて

    プログラムを実行するとき、CPU のレジスタの一つであるプログラムカウンタは、実行するプログラムが展開されたメモリ上のアドレスを指します。CPU が実行するプログラムには、OS のカーネルと、カーネルが管理するユーザプログラムがあります。CPU のプログラムカウンタは、これら複数のプログラムのメモリアドレスを次々と切り換えながら指すことで、見かけ上、複数のプログラムを同時に実行します。これをプリエンプティブ・マルチタスク (preemptive multitask) とよびます。プロセスとして動作するユーザプログラム間の切り換えはコンテキストスイッチという仕組みを利用します。

    カーネルとユーザプログラムは異なる CPU モードで動作します。それぞれ、特権モード (スーパーバイザモード、カーネルモード) とユーザモードで動作しており、例えばユーザモードではハードウェアを操作する CPU 命令を出すことができません。ユーザプログラムからハードウェアを操作したい場合は、カーネルが提供するシステムコールというインタフェースを用いて間接的に操作します。このインタフェースを介することにより、ハードウェアを操作する CPU 命令を、不具合を含む可能性のあるユーザプログラムからでも「安全に」出すことができます。ハードウェアを操作するような CPU 命令を出すためには、ユーザプログラムの動作権限を一時的に特権モードに切り換える必要があり、このときもコンテキストスイッチの仕組みを利用します。

    libc とシステムコールの関係

    カーネルが提供するシステムコールは、アセンブラで記述して呼び出すこともできますが、例えば C 言語の場合、より簡単に利用できるライブラリ関数が各システムコールに対応するように libc 内で提供されています。libc を利用すると、OS の違いによって存在したりしなかったりするシステムコールの差異を吸収することもできます。

    マニュアルの参照方法

    CentOS の場合は man-pages をインストールしておきます。

    sudo yum install man
    sudo yum install man-pages
    

    man コマンド実行時にはセクション番号を指定できます。例えば chmod はコマンドとシステムコールでそれぞれ別物であるため、システムコールのマニュアルを読みたい場合は man 2 chmod とします。

    • 1: ユーザコマンド (ls など)
    • 2: システムコール (fork など)
      1. システムコールを除く C ライブラリ関数 (printf など)

    上述のとおり、OS によってはシステムコールが存在せず、互換性のためにシステムコールを間接的に利用するライブラリ関数として実装されていることにも注意します。その場合はセクション番号 3 を指定する必要があります。

    man 2 fork
    man 2 chmod
    

    エラー処理について

    システムコールの返り値で条件分岐して perror() でエラー内容を出力します。

    main.c

    #include <sys/stat.h> // open()
    #include <fcntl.h> // open()
    #include <stdio.h> // perror()
    #include <errno.h> // errno
    #include <string.h> // strerror()
    #include <locale.h> // setlocale()
    
    int main() {
        int fd_r;
    
        // 英語以外のエラー表示をしたい場合は `LC_ALL` を空にして $LANG 環境変数を見るようにします。
        setlocale(LC_ALL, "");
    
        // 基本的には、システムコールを内部的に利用する C ライブラリ関数の返り値を利用して
        // エラーが発生したかどうかを判別できます。0 以上であれば成功、失敗の場合は -1 です。
    
        // ただし、システムコールによっては戻り値なしでリターンするものや
        // `exit()` のようにそもそもリターンしないものがあります。
    
        if ((fd_r = open("/path/to/nofile", O_RDONLY)) < 0) {
    
            // `任意のメッセージ: strerror(errno)` という形式で出力できます。
            perror("/path/to/nofile");
    
            // システムコールの実行でエラーが発生した場合は、外部変数 `errno` にエラー番号が格納されます。
            // エラーが発生していない場合は以前の値が格納されたままになります。
            // 戻り値なしでリターンするシステムコールを利用する場合は、
            // errno に 0 を代入してから実行してエラー判定する必要があります。
            printf("errno %d: %s\n", errno, strerror(errno));
    
            return 1;
        }
    
        // fd_r を利用した処理
        // ...
        return 0;
    }
    

    実行例

    gcc -Wall -O2 main.c
    unset LC_ALL
    unset LC_MESSAGES
    unset LC_CTYPE
    
    $ LANG=ja_JP.UTF-8 ./a.out
    /path/to/nofile: そのようなファイルやディレクトリはありません
    errno 2: そのようなファイルやディレクトリはありません
    
    $ LANG=C ./a.out
    /path/to/nofile: No such file or directory
    errno 2: No such file or directory
    
    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    プログラミング教育者。ScratchやPythonを教えています。

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    さらに詳しく →
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      関連記事

      • cmake で ccache を有効化するための設定
        YOCTO Linux で開発している場合など、ビルド速度が開発効率にそのまま影響する際は ccache (compiler cache) で C/C++ ビルドを高速化することを考えます。cmakeと併用する場合の設定およびコマンド例を記載します。 インストール sudo apt install ccache 以下のバイナリファイルに加えて $ w
        AWS NinjaAWS Ninja11/22/2022に更新
        いいねアイコン画像0
      • Python から C ライブラリを利用 (ctypes)
        FFI (Foreign Function Interface) の一つである ctypes を利用すると、C 言語のライブラリを Python から利用できます。サンプルコードを記載します。 適宜参照するための公式ドキュメント libm の sqrt を利用する例 main.py ``
        coderinacoderina9/2/2021に更新
        いいねアイコン画像0
      • 低レイヤーネットワークプログラミングに関する雑多な知識
        TCP/IP モデルのうちトランスポート層ではなく、インターネット層およびネットワークインターフェイス層のパケット (正確には PDU) を扱う低レイヤープログラミングの雑多なテクニックをまとめます。『ルーター自作でわかるパケットの流れ』などを参考にしています。バックアップ目的で書籍のサンプルコードをホスティングしました。 検証環境
      • ファイルディスクリプタ関連のシステムコールのサンプルコード (C 言語)
        ファイル記述子 (File Descriptor) に関連するシステムコールを利用した C 言語のサンプルコードを記載します。 ファイルの読み書き open/close main.c #include <unistd.h> #include <fcntl.h> #include <stdio.h> int main() { int fd_r, fd_w;...
        フロックフロック10/7/2021に更新
        いいねアイコン画像0
      • C言語の資産を利用 (C++をもう一度)
        サンプルコード メルセンヌ・ツイスタなど、C言語で記述されたライブラリをC++から利用するためには extern "C" を利用します。その際、組み込みマクロ __cplusplus を利用するとC言語からもC++からも利用できるヘッダファイルを作成できます。 sub.h #ifndef SUB_H_ #define SUB_H_ #ifdef __cplu