Set pipe buffer size

2019-02-04 16:30发布

I have a C++ multithreaded application which uses posix pipes in order to perform inter thread communications efficiently (so I don't have to get crazy with deadlocks).

I've set the write operation non-blocking, so the writer will get an error if there is not enough space in the buffer to write.

if((pipe(pipe_des)) == -1)
    throw PipeException();

int flags = fcntl(pipe_des[1], F_GETFL, 0); // set write operation non-blocking
assert(flags != -1);
fcntl(pipe_des[1], F_SETFL, flags | O_NONBLOCK);

Now I'd wish to set the pipe buffer size to a custom value (one word in the specific case).

I've googled for it but I was not able to find anything useful. Is there a way (possibly posix compliant) to do it?

Thanks

Lorenzo

PS: I'm under linux (if it may be useful)

标签: c buffer pipe
3条回答
疯言疯语
2楼-- · 2019-02-04 17:08

I googled "linux pipe buffer size" and got this as the top link. Basically, the limit is 64Kb and is hard coded.

Edit The link is dead and it was probably wrong anyway. The Linux pipe(7) man page says this:

A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on whether the O_NONBLOCK flag is set (see below). Different implementations have different limits for the pipe capacity. Applications should not rely on a particular capacity: an application should be designed so that a reading process consumes data as soon as it is available, so that a writing process does not remain blocked.

In Linux versions before 2.6.11, the capacity of a pipe was the same as the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11, the pipe capacity is 16 pages (i.e., 65,536 bytes in a system with a page size of 4096 bytes). Since Linux 2.6.35, the default pipe capacity is 16 pages, but the capacity can be queried and set using the fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ operations. See fcntl(2) for more information.

Anyway, the following still applies IMO:

I'm not sure why you are trying to set the limit lower, it seems like a strange idea to me. If you want the writer to wait until the reader has processed what it has written, you should use a pipe in the other direction for the reader to send back an ack.

查看更多
够拽才男人
3楼-- · 2019-02-04 17:14

You could use a shared-memory area( System V - like ) of two words, one for sending data and the other for receiving data, and implement your pipes with them. other solutions, as you may found previously, are about recompiling the kernel as you would like to have it, but it is not the case, I suppose.

Ciao!

查看更多
姐就是有狂的资本
4楼-- · 2019-02-04 17:16

Since you mentioned you are on Linux and may not mind non-portability, you may be interested in the file descriptor manipulator F_SETPIPE_SZ, available since Linux 2.6.35.

int pipe_sz = fcntl(pipe_des[1], F_SETPIPE_SZ, sizeof(size_t));

You'll find that pipe_sz == getpagesize() after that call, since the buffer cannot be made smaller than the system page size. See fcntl(2).

查看更多
登录 后发表回答