System V IPC

System V IPC

  • System V メッセージキュー

  • System V セマフォ

  • System V 共有メモリ

  • System V IPC用の関数

    メッセージキューセマフォ共有メモリ
    ヘッダ
    作成、オープン、削除msggetsemgetshmget
    制御用関数msgctlsemctlshmctl
    IPC操作用関数msgsnd, msgrcvsemopshmat, shmdt



    key_tとftok関数

    System V IPCは名前にkey_t(ヘッダ)値を用いる。
    ftok関数は、既存のパス名と整数の正規別氏を、key_t値(IPCキー)に変換する。

    #include <sys/ipc.h>
    
    key_t ftok(const char *pathname, int id);
    
    戻り値:成功ならIPCキー、エラーなら-1

    この関数は、pathnameとidの下位8ビットを組み合わせて整数のIPCキーを生成する。System V IPCを用いる特定のアプリケーションでは、そのアプリケーションにとってなんらかの意味があるpathnameを、サーバとクライアントの間で合意している必要がある。
    一旦クライアントとサーバー間で、pathnameとidに関する合意が取れれば、両者は独立にftok関数を呼び出して、これらを同一のIPCキューに変換することが出来る。

    //ftok関数のサンプル
    #include <stdio.h>
    #include <sys/ipc.h>
    
    int
    main()
    {
      key_t key;
      key  = ftok("/tmp", 1);
      printf("IPC Key = %d\n", key);
    
      return 0;
    }
    



    UNIX ネットワークプログラミング Vol.2 p.29の結果
    Fedora5では、以下のようになった。
    
    //ファイルシステムに関する情報と結果のIPCキーの印字
    #include <stdio.h>
    #include <sys/ipc.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    int
    main()
    {
      struct stat st;
      char *pathname = "/tmp";
      stat(pathname, &st);
    
      printf("st_dev: %lx, st_ino: %lx, key: %x\n",
        (u_long)st.st_dev,
        (u_long)st.st_ino,
        ftok(pathname, 0x57));
    
      return 0;
    }
    
    ///////////////////////////////
    //結果
    st_dev: fd00, st_ino: 570001, key: 57000001



    ipc_perm構造体

    カーネルは、各IPCオブジェクトに関して、ファイルに関する情報と類似した情報の構造体を維持する

    struct ipc_perm {
      uid_t uid; /* 所有者のユーザID */
      gid_t gid; /* 所有者のグループID */
      uid_t cuid; /* 作成者のユーザID */
      gid_t cgid; /* 作成者のグループID */
      mode_t mode; /* 読み書き許可ビット */
      ulong_t seq; /* スロット使用シーケンス番号 */
      key_t key; /* IPCキー */
    };

    この構造体を含め、他のSystem V IPC関数関連の主な定数は、ヘッダで定義されている。


    IPCチャネルの作成とオープン

    IPCオブジェクトの作成あるいはオープンを行うmsgget(), semget(), shmget() は、すべてkey_t型のkey値を引数に持ち、整数の識別子を返す。アプリケーションは、msgget(), semget(), shmget() の最初の引数であるkey値に、次のいずれかを用いることが出来る。

  • ftokにpathnameとidを与えて呼び出す

  • ユニークなIPCオブジェクトを新しく生成することを保証する定数であるIPC_PRIVATEをkeyに指定する


  • keyにIPC_PRIVATEを指定すると、一意なIPCオブジェクトが作成されることが保証される。

  • oflagのIPC_CREATビットを設定すると、すでに存在しない場合にはkeyで指定されたエントリが新たに作成される。既存のエントリが見つかった場合には、そのエントリが返される。

  • oflagのIPC_CREATビットとIPC_EXCLビットを同時に指定すると、エントリが既に存在しない場合に限って、keyで指定されたエントリが新たに作成される。既存エントリが見つかった場合には、エラーとしてIPCオブジェクトが既に存在することを表すEEXISTが返される
  • IPCオブジェクトに関するIPC_CREATとIPC_EXCLの組み合わせは、open()におけるO_CREATとO_EXCLの組み合わせに類似している。



    msgctl() : メッセージ制御操作

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);

    msgctl()はメッセージキュー識別子msqidで指定されたメッセージキューに対してcmdで指定された制御操作を行う。

    msqid_dsデータ構造体は、で以下のように定義されている。

    struct msqid_ds {
      struct ipc_perm msg_perm; /* 所有権と許可 */
      time_t msg_stime; /* 最後のmsgsnd(2)の時刻 */
      time_t msg_rtime; /* 最後のmsgrcv(2)の時刻 */
      time_t msg_ctime; /* 最後に変更が行われた時刻 */
      unsigned long __msg_cbytes; /* キューにある現在のバイト数 */
      msgqnum_t msg_qnum; /* キューにある現在入っているメッセージの数 */
      msglen_t msg_qbytes; /* キューに許可されている最大バイト数 */
      pid_t msg_lspid; /* 最後のmsgsnd(2)のPID */
      pid_t msg_lrpid; /* 最後のmsgrcv(2)のPID */
    };

    cmdの有効な値

  • IPC_STAT

  • IPC_SET

  • IPC_RMID

  • IPC_RMID

  • IPC_INFO(Linux固有)

  • MSG_INFO(Linux固有)

  • MSG_STAT(Linux固有)

  • msgget(), msgctl()サンプル

    //カーネルが割り当てたメッセージキュー識別子を印字する
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int
    main()
    {
      int i, msqid;
      msqid = msgget(IPC_PRIVATE, IPC_CREAT);
      printf("msqid = %d\n", msqid);
      msgctl(msqid, IPC_RMID, NULL);
     
      return 0;
    }
    
    /////////////////////////
    //結果
    msqid = 360448





    まとめ

  • msgget(), semget(), shmget()の最初の引数はSystem V IPCキーである。

  • System V IPC キーは、ftok()関数を用いてパス名から生成される。

  • System V IPCキーには、特別な値であるIPC_PRIVATEを用いることが出来る。

  • msgget(), semget(), shmget()は、IPCオブジェクトを識別するために用いるSystem V IPC識別子として整数を返す。

  • System V IPC識別子はシステム全体に共通する識別子。ある時間のあとで再利用される。




  • 参考文献:
    UNIXネットワークプログラミング Vol.2 スティーブンズ

    Linux manページ: http://www.linux.or.jp/JM/html/LDP_man-pages/man2/msgctl.2.html