.\" Copyright (C) 2011 by Andi Kleen .\" and Copyright (c) 2011 by Michael Kerrisk .\" .\" %%%LICENSE_START(VERBATIM) .\" Permission is granted to make and distribute verbatim copies of this .\" manual provided the copyright notice and this permission notice are .\" preserved on all copies. .\" .\" Permission is granted to copy and distribute modified versions of this .\" manual under the conditions for verbatim copying, provided that the .\" entire resulting derived work is distributed under the terms of a .\" permission notice identical to this one. .\" .\" Since the Linux kernel and libraries are constantly changing, this .\" manual page may be incorrect or out-of-date. The author(s) assume no .\" responsibility for errors or omissions, or for damages resulting from .\" the use of the information contained herein. The author(s) may not .\" have taken the same level of care in the production of this manual, .\" which is licensed free of charge, as they might when working .\" professionally. .\" .\" Formatted or processed versions of this manual, if unaccompanied by .\" the source, must acknowledge the copyright and authors of this work. .\" %%%LICENSE_END .\" .\" Syscall added in following commit .\" commit a2e2725541fad72416326798c2d7fa4dafb7d337 .\" Author: Arnaldo Carvalho de Melo .\" Date: Mon Oct 12 23:40:10 2009 -0700 .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .\" .\" Japanese Version Copyright (c) 2013 Akihiro MOTOKI .\" all rights reserved. .\" Translated 2013-05-22, Akihiro MOTOKI .\" .TH RECVMMSG 2 2014\-06\-13 Linux "Linux Programmer's Manual" .SH 名前 recvmmsg \- 複数のメッセージをソケットから受信する .SH 書式 .nf \fB#define _GNU_SOURCE\fP /* feature_test_macros(7) 参照 */ \fB#include \fP \fBint recvmmsg(int \fP\fIsockfd\fP\fB, struct mmsghdr *\fP\fImsgvec\fP\fB, unsigned int \fP\fIvlen\fP\fB,\fP .br \fB unsigned int \fP\fIflags\fP\fB, struct timespec *\fP\fItimeout\fP\fB);\fP .fi .SH 説明 \fBrecvmmsg\fP() システムコールは \fBrecvmsg\fP(2) の拡張で、 このシステムコールを使うと一度の呼び出しでソケットから複数のメッセージを受信することができる (アプリケーションによっては性能上のメリットがある)。 他に \fBrecvmsg\fP(2) から拡張されている点としては、受信操作におけるタイムアウトのサポートがある。 \fIsockfd\fP 引き数は、データを受信するソケットのファイルディスクリプターである。 \fImsgvec\fP 引き数は \fImmsghdr\fP 構造体の配列である。 この配列の大きさは \fIvlen\fP で指定する。 \fImmsghdr\fP 構造体は \fI\fP で次のように定義されている。 .in +4n .nf struct mmsghdr { struct msghdr msg_hdr; /* メッセージヘッダー */ unsigned int msg_len; /* このヘッダーで受信されたバイト数 */ }; .fi .in .PP \fImsg_hdr\fP フィールドは、 \fBrecvmsg\fP(2) で説明されている \fImsghdr\fP 構造体である。 \fImsg_len\fP フィールドは、 このエントリーで返されるメッセージのバイト数で、 このヘッダーに対して \fBrecvmsg\fP(2) を呼び出した場合の返り値と同じ値が入る。 \fIflags\fP 引き数には複数のフラグを論理和 (OR) で指定できる。 フラグは、 \fBrecvmsg\fP(2) で説明されているものに加えて、以下が使用できる。 .TP \fBMSG_WAITFORONE\fP (Linux 2.6.34 以降) 最初のメッセージを受信後に \fBMSG_DONTWAIT\fP を有効にする。 .PP \fItimeout\fP 引き数は \fIstruct timespec\fP (\fBclock_gettime\fP(2) 参照) へのポインターで、 この構造体で受信操作のタイムアウト (秒とナノ秒) を指定する (\fIただし、バグを参照のこと\fP) (待ち時間はシステムクロックの粒度に切り上げられ、カーネルのスケジューリング遅延により少しだけ長くなる可能性がある)。 \fItimeout\fPが NULL の場合、 受信操作は無期限に停止 (block) する。 停止 (blocking) モードの \fBrecvmmsg\fP() の呼び出しは、 \fIvlen\fP 個のメッセージを受信するか、タイムアウトが満了するまで停止する。 非停止 (nonblocking) モードの呼び出しでは、 読み出し可能なメッセージ (最大で \fIvlen\fP 個) を読み出し、 すぐに返る。 \fBrecvmmsg\fP() が返った際には、 \fImsgvec\fP のうちデータが受信された要素には、受信したそれぞれのメッセージの情報が格納されている。 また、 \fImsg_len\fP には受信したメッセージの大きさが入り、 \fImsg_hdr\fP の各フィールドは \fBrecvmsg\fP(2) に書かれている通りに更新される。 呼び出しの返り値は、更新された \fImsgvec\fP の要素数である。 .SH 返り値 成功すると、 \fBrecvmmsg\fP() は \fImsgvec\fP に受信されたメッセージ数を返す。 エラーの場合、 \-1 を返し、 \fIerrno\fP にエラーを示す値を設定する。 .SH エラー エラーは \fBrecvmsg\fP(2) と同じである。 これに加えて、以下のエラーが起こる場合がある。 .TP \fBEINVAL\fP \fItimeout\fP が無効である。 .SH バージョン \fBrecvmmsg\fP() システムコールは Linux 2.6.33 で追加された。 glibc でのサポートはバージョン 2.12 以降で利用可能である。 .SH 準拠 \fBrecvmmsg\fP() は Linux 固有である。 .SH 例 .PP 以下のプログラムは、 \fBrecvmmsg\fP() を使って複数のメッセージをソケットから受信し、それらを複数のバッファーに格納する。 呼び出しは、すべてのバッファーにメッセージが格納されるか、 指定したタイムアウト時間が経過すると返る。 以下のコマンドは、 ランダムな数字が入った UDP データグラムを定期的に生成する。 .in +4n .nf $\fB while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234; \fP \fBsleep 0.25; done\fP .fi .in 生成されたデータグラムをサンプルアプリケーションが読み出し、以下のような出力が得られる。 .in +4n .nf $\fB ./a.out\fP 5 messages received 1 11782 2 11345 3 304 4 13514 5 28421 .fi .in .SS プログラムのソース \& .nf #define _GNU_SOURCE #include #include #include #include #include int main(void) { #define VLEN 10 #define BUFSIZE 200 #define TIMEOUT 1 int sockfd, retval, i; struct sockaddr_in sa; struct mmsghdr msgs[VLEN]; struct iovec iovecs[VLEN]; char bufs[VLEN][BUFSIZE+1]; struct timespec timeout; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == \-1) { perror("socket()"); exit(EXIT_FAILURE); } sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sa.sin_port = htons(1234); if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == \-1) { perror("bind()"); exit(EXIT_FAILURE); } memset(msgs, 0, sizeof(msgs)); for (i = 0; i < VLEN; i++) { iovecs[i].iov_base = bufs[i]; iovecs[i].iov_len = BUFSIZE; msgs[i].msg_hdr.msg_iov = &iovecs[i]; msgs[i].msg_hdr.msg_iovlen = 1; } timeout.tv_sec = TIMEOUT; timeout.tv_nsec = 0; retval = recvmmsg(sockfd, msgs, VLEN, 0, &timeout); if (retval == \-1) { perror("recvmmsg()"); exit(EXIT_FAILURE); } printf("%d messages received\en", retval); for (i = 0; i < retval; i++) { bufs[i][msgs[i].msg_len] = 0; printf("%d %s", i+1, bufs[i]); } exit(EXIT_SUCCESS); } .fi .SH バグ .\" FIXME . https://bugzilla.kernel.org/show_bug.cgi?id=75371 .\" http://thread.gmane.org/gmane.linux.man/5677 \fItimeout\fP 引き数は意図した通りには動作しない。 タイムアウトは各データグラムの受信後にのみチェックされる。 そのため、 タイムアウトが満了する前に \fIvlen\-1\fP 個のデータグラムを受信し、 その後全くデータグラムを受信しなかった場合、 呼び出しはずっと停止し続けてしまう。 .SH 関連項目 \fBclock_gettime\fP(2), \fBrecvmsg\fP(2), \fBsendmmsg\fP(2), \fBsendmsg\fP(2), \fBsocket\fP(2), \fBsocket\fP(7) .SH この文書について この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man\-pages/ に書かれている。