2017/05/25

[linux]メッセージキューのmsgszは8192を超えてはいかん

※2017/05/25 22:25 修正あり

Linuxのメッセージキューは、まずはサンプルを動かすことにした。
いつものように、LinuxといいつつWindows10のBash on Ubuntu on Windows(以下 BoW)だ。

が・・・コンパイルは通るものの、msgget()でエラーになる。

Function not implemented


嫌な予感は的中した。
System V IPC is missing · Issue #1016 · Microsoft/BashOnWindows

Creators Updateでセマフォと共有メモリは対応したけど、メッセージキューはbacklogと書いてあるから、まだ残ってるという意味なのかな。


まあ、何でもかんでも期待しちゃいかんだろう。


VMに入っているUbuntu環境に持っていくと、進んだ。

が、msgsnd()でInvalid argumentが出てしまう。
Man page of MSGOP
msgsnd()がEINVALを返すのは、以下のどれか。

  1. msqid が不適切な値
  2. mtype が正の値でない
  3. msgsz が不適切な値 (0 以下か、システムで決まる値 MSGMAX よりも大きい値)

msqidはチェックしているし、mtypeも正の値を代入している。
ということは、3番のmsgszだ。

サンプルでは、こういう構造体になっていた。

struct {
    long mtype
    char mtext[BUFSIZ];
};

このBUFSIZは、8192だった。
だから、sizeofすると、たぶん8196・・・違った、8200だった。
8byteアラインなのね。


ではMSGMAXは?
これはマクロ値にはなっていないようだったが、Man pageの下の方に書いてあった。

MSGMAX

メッセージのテキストの最大サイズ: 8192 バイト (Linux では、この制限値は /proc/sys/kernel/msgmax 経由で読み出したり変更したりできる)。

うーん、ここだけ読むとメッセージのテキストの最大サイズだから使ってもよさそうなのだけど、msgszのが超えたらいかんと書いてある方が強いのだろう。


というわけで、うちの環境ではmtextが8184までOKで、8185からInvalid argumentになった。

sizeofはマクロに入れられないので、

struct {
  long mtype;
  char mtext[SZ_BUF];
};

#if 8 + SZ_BUF > 8182
#error !!!
#endif

みたいにして判定させるのが良いかも。


※追記

あれからいくつか見てみたが、msgsnd()に指定するサイズとして、sizeof(構造体)ではなく、sizeof(構造体) - sizeof(long)、としているサイトが見られた。
ま、まさか・・・。

もう一度説明を見直すと、msgsnd()のサイズとして指定するのは、struct msgbufではなく、mtextに相当するサイズ(msgsz)と書いてあるではないか!

私はmsgsnd()で構造体のサイズを指定していたのだが、それではダメだ。
そして、アラインメントもあるので、sizeof(long)を引くのも正しくなさそうな感じがする。
ここは、mtextに相当するサイズをマクロで指定するのがよいのかもしれん。


ふっ、まだまだ私も青いのぅ。。。
タイトルは間違っていないものの、動作検証をしていないから、後日やろう。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。