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

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

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

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

プロセスの情報を取得および設定するためのシステムコール (C 言語)

モーダルを閉じる

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

モーダルを閉じる

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

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

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

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

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

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

作成日作成日
2018/06/13
最終更新最終更新
2021/01/06
記事区分記事区分
一般公開

目次

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

    Spring Bootでの実用的な機能をわかりやすく解説中

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

    プロセスの情報を取得および設定するためのシステムコールに関する、C 言語のサンプルコードです。

    各種 ID

    プロセスID の取得 (getpid/getppid)

    コマンドラインから直接実行したプログラムの親プロセスはシェルになるため getppid() で取得されるプロセスID は $$ と同じ値になります。getpid() で取得できるプロセスID はプロセス毎に異なるため一時ファイル等の識別子としても利用できます。

    main.c

    #include <unistd.h>
    #include <stdio.h>
    
    int main() {
        pid_t pid, ppid;
        pid = getpid();
        ppid = getppid();
        printf("pid = %d, ppid = %d\n", pid, ppid);
        return 0;
    }
    

    実行例

    $ gcc -Wall -O2 main.c && ./a.out
    pid = 6899, ppid = 524
    $ echo $$
    524
    

    実ユーザ/グループID と実効ユーザ/グループID の取得 (getuid/geteuid, getgid/getegid)

    main.c

    #include <unistd.h>
    #include <stdio.h>
    
    int main() {
        uid_t uid, euid;
        gid_t gid, egid;
        uid = getuid();
        euid = geteuid();
        gid = getgid();
        egid = getegid();
        printf("uid = %u, euid = %u, gid = %u, egid = %u\n", uid, euid, gid, egid);
        return 0;
    }
    

    所有ユーザおよびグループを root (id = 0) に変更し、更にセットユーザ/グループID という印を付与します。

    gcc -Wall -O2 main.c
    sudo chown root:root a.out
    sudo chmod ug+s a.out
    ls -l a.out
    -rwsr-sr-x 1 root root 8848 Jul 29 13:05 a.out
    

    実行したユーザとファイル所有ユーザの id がそれぞれ出力されることが確認できます。実効ユーザの root 権限で動作します。

    $ ./a.out
    uid = 1000, euid = 0, gid = 1000, egid = 0
    
    $ id `whoami`
    uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev)
    

    システムリソースの上限 (getrlimit/setrlimit)

    システムリソースにはソフトリミットとハードリミットがあります。

    ulimit -S -a
    ulimit -H -a
    

    これらのリミットを確認および変更するシステムコールが getrlimit/setrlimit です。以下は RLIMIT_NOFILE リソースの例です。

    main.c

    #include <sys/resource.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdint.h>
    
    int main() {
        // リソースリミット情報を保持する構造体
        struct rlimit rlim;
    
        // ファイルディスクリプタ数の上限についてソフトリミットとハードリミットを確認
        if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
            perror("getrlimit failed");
            return 1;
        }
        if(rlim.rlim_cur == RLIM_INFINITY) { // unlimited
        }
        else {
            printf("rlim_cur = %ju\n", (uintmax_t)rlim.rlim_cur);
        }
        if(rlim.rlim_max == RLIM_INFINITY) { // unlimited
        }
        else {
            printf("rlim_max = %ju\n", (uintmax_t)rlim.rlim_max);
        }
    
        // ファイルディスクリプタ数の上限についてソフトリミットとハードリミットを 0 に設定
        rlim.rlim_cur = 0;
        rlim.rlim_max = 0;
        if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
            perror("setrlimit failed");
            return 1;
        }
    
        // 開けないことを確認
        int fd;
        if((fd = open("./main.c", O_RDONLY)) < 0) {
            perror("yyy");
            return 1;
        }
        if(close(fd) < 0) {
            perror("xxx");
            return 1;
        }
    
        return 0;
    }
    

    実行例

    $ gcc -Wall -O2 main.c && ./a.out
    rlim_cur = 1024
    rlim_max = 1048576
    yyy: Too many open files
    

    優先度 (getpriority/setpriority)

    nice および renice コマンドの内部で利用されているシステムコールです。

    main.c

    #include <sys/resource.h> // getpriority, setpriority
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    void print_pri() {
        int pri;
        errno = 0;
        // 自分のプロセス0 優先度を取得
        pri = getpriority(PRIO_PROCESS, 0);
        if(errno != 0) {
            perror("getpriority failed");
            exit(1);
        }
        printf("%d\n", pri);
    }
    
    int main() {
        print_pri();
        // 自分のプロセス0 優先度を 19 に変更
        if(setpriority(PRIO_PROCESS, 0, 19)) {
            perror("setpriority failed");
            return 1;
        }
        print_pri();
        return 0;
    }
    

    実行例

    $ gcc -Wall -O2 main.c && ./a.out
    0
    19
    

    ファイルシステム

    カレントディレクトリの変更 (chdir/fchdir)

    カレントディレクトリは各プロセスが個別に持つ情報です。

    main.c

    #include <unistd.h>
    #include <fcntl.h> // open()
    #include <stdio.h> // perror()
    #include <stdlib.h> // system()
    
    int main() {
    
        // 現在位置の記憶
        int fd;
        if((fd = open(".", O_RDONLY)) < 0) {
            perror("open failed");
            return 1;
        }
        system("pwd");
    
        // カレントディレクトリの変更
        if(chdir("/tmp") < 0) {
            perror("chdir failed");
            return 1;
        }
        system("pwd");
    
        // 先程記憶したディレクトリに戻る
        if(fchdir(fd) < 0) {
            perror("fchdir failed");
            return 1;
        }
        system("pwd");
        return 0;
    }
    

    実行例

    $ gcc -Wall -O2 main.c && ./a.out
    /vagrant
    /tmp
    /vagrant
    

    ルートディレクトリの変更 (chroot)

    ルートディレクトリは各プロセスが個別に持つ情報です。chroot コマンドの内部でも chroot システムコールが利用されています。

    main.c

    #include <unistd.h> // chroot(), chdir()
    #include <stdio.h> // perror()
    
    int main() {
        if(chroot("/tmp") < 0) {
            perror("chroot failed");
            return 1;
        }
        if(chdir("/") < 0) {
            perror("chdir failed");
            return 1;
        }
        printf("sleeping...");
        sleep(60);
        return 0;
    }
    

    プロセスルートを /proc 以下の情報で調べると readlink の結果が /tmp になっていることが分かります。

    $ gcc -Wall -O2 main.c
    $ sudo ./a.out &
    [1] 28181
    $ ps auxw | grep a.out
    root     28181  0.0  0.7  49256  3704 pts/0    S    16:24   0:00 sudo ./a.out
    root     28182  0.0  0.1   4172   644 pts/0    S    16:24   0:00 ./a.out
    vagrant  28184  0.0  0.1  12784   948 pts/0    S+   16:24   0:00 grep a.out
    $ sudo readlink /proc/28182/root
    /tmp
    
    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    Spring Bootでの実用的な機能をわかりやすく解説中

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

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

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

    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