最後に tl;dr があります。
私のコメントで、私はあなたに mmap()
を提案しました /dev/null
デバイス。しかし、私のマシンではデバイスがマッピングできないようです (err 19
:No such device
)。 /dev/zero
のようです ただし、マッピング可能です。別の質問/回答は、それが MAP_ANONYMOUS
と同等であることを示唆しています fd
になります 引数とそれに関連付けられた open()
そもそも不要。例をご覧ください:
#include <iostream>
#include <cstring>
#include <cerrno>
#include <cstdlib>
extern "C" {
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
}
template <class Type>
struct iovec ignored(void *p)
{
struct iovec iov_ = {};
iov_.iov_base = p;
iov_.iov_len = sizeof(Type);
return iov_;
}
int main()
{
auto * p = mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if ( MAP_FAILED == p ) {
auto err = errno;
std::cerr << "mmap(MAP_PRIVATE | MAP_ANONYMOUS): " << err << ": " << strerror(err) << std::endl;
return EXIT_FAILURE;
}
int s_[2] = {-1, -1};
int result = socketpair(AF_UNIX, SOCK_STREAM, 0, s_);
if ( result < 0 ) {
auto err = errno;
std::cerr << "socketpair(): " << err << ": " << strerror(err) << std::endl;
return EXIT_FAILURE;
}
int w_[3] = {1,2,3};
ssize_t nwritten = 0;
auto makeiov = [](int & v){
struct iovec iov_ = {};
iov_.iov_base = &v;
iov_.iov_len = sizeof(v);
return iov_;
};
struct iovec wv[3] = {
makeiov(w_[0]),
makeiov(w_[1]),
makeiov(w_[2])
};
nwritten = writev(s_[0], wv, 3);
if ( nwritten < 0 ) {
auto err = errno;
std::cerr << "writev(): " << err << ": " << strerror(err) << std::endl;
return EXIT_FAILURE;
}
int r_ = {0};
ssize_t nread = 0;
struct iovec rv[3] = {
ignored<int>(p),
makeiov(r_),
ignored<int>(p),
};
nread = readv(s_[1], rv, 3);
if ( nread < 0 ) {
auto err = errno;
std::cerr << "readv(): " << err << ": " << strerror(err) << std::endl;
return EXIT_FAILURE;
}
std::cout <<
w_[0] << '\t' <<
w_[1] << '\t' <<
w_[2] << '\n' <<
r_ << '\t' <<
*(int*)p << std::endl;
return EXIT_SUCCESS;
}
上記の例では、プライベートを作成していることがわかります (書き込みは、fork()
以降の子には表示されません) ) 4KiB の匿名 (ファイルに依存しない) メモリ マッピング (ほとんどのシステムで 1 つのページ サイズ)。次に、2 つの int の書き込み先を提供するために 2 回使用されます。後の int は前の int を上書きします。
正確ではない あなたの質問を解決してください:バイトを無視する方法。 readv()
を使用しているため 、その姉妹関数 preadv()
を調べました 一見すると、あなたがやりたいことをしているように見えます:バイトをスキップします。ただし、ソケット ファイル記述子ではサポートされていないようです。次のコードは preadv(): 29: Illegal seek
を返します .
rv = makeiov(r_[1]);
nread = preadv(s_[1], &rv, 1, sizeof(int));
if ( nread < 0 ) {
auto err = errno;
std::cerr << "preadv(): " << err << ": " << strerror(err) << std::endl;
return EXIT_FAILURE;
}
だから preadv()
にも見える seek()
を使用 もちろん、ソケットでは許可されていません。確立されたストリームで受信したバイトを無視/ドロップするように OS に指示する方法があるかどうか (まだ?) はわかりません。 @geza が正しいためだと思います。最終的な (無視された) 宛先に書き込むコストは、私が遭遇したほとんどの状況で非常に些細なことです。また、無視されたバイトのコストがない場合 より良いオプション、実装、またはプロトコルの使用を真剣に検討する必要があります。
tl;dr:
4KiB の匿名プライベート メモリ マッピングの作成は、実質的に連続割り当てコンテナーと見分けがつきません (非常にハイエンドなパフォーマンス以外のワークロードにとって重要ではない微妙な違いがあります)。 また、標準コンテナを使用すると、メモリ リーク、ワイルド ポインタなどの割り当てバグが発生しにくくなります。だから私はKISSと言って、それをするだけです いずれかを支持する代わりに 私が上に書いたコードの。例:std::array<char, 4096> ignored;
または std::vector<char> ignored{4096};
iovec.iov_base = ignored.data();
を設定するだけです .iov_len
を設定します 無視する必要がある任意のサイズ (コンテナーの長さ内)。