考虑uv_try_write
的文档(同样适用于uv_write
和uv_write2
)。
声明是:
int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs)
uv_buf_t
是一个至少包含以下字段的数据结构:
char* uv_buf_t.base
size_t uv_buf_t.len
我很确定我在这里遗漏了一些东西。
一个人应该提交多个uv_buf_t
结构而不是更大结构的原因是什么?
换句话说,如果我有100 char
要写出来,我为什么要提交10 uv_buf_t
包含每10 char
而不是uv_buf_t
包含100 char
?
这样的选择是有意义的真实世界示例会有所帮助,因为我在阅读文档时无法弄清楚它。
答案 0 :(得分:2)
无论何时执行格式化I / O,您所做的只是串联一串小字符串。
当你写下像
这样的东西时,想想发生在幕后的事情fprintf(stdout, "Hello, %s!\n", getenv("USER"));
这可以实现(忽略对getenv
的多重评估):
struct iovec bufs[3] = {{"Hello, ", 7}, {getenv("USER"), strlen(getenv("USER"))}, {"!\n", 2}};
writev(STDOUT_FILENO, bufs, 3);
(在实践中,FILE
操作稍微复杂一些 - 可能是不必要的 - 但大多数情况 这么简单。)
允许直接指定多个缓冲区意味着您不必浪费处理时间(或源代码复杂性),在写入之前分配单个缓冲区来保存它们。
另外,您是否曾在make -j
下运行编译器,导致其输出异常混乱?这通常是因为它们不这样做 - 而是它们发出几个单独的write
并且它们与并行进程的写入混合在一起,而不是在单个系统调用期间发出每一行。 / p>
答案 1 :(得分:1)
大多数应用程序可能使用单个应用程序,但由于writev
是我们在try变体中公开它的事情。想象一个应用程序,它充当代理,并在多个数据包中获取数据,然后需要中继。一次性检测属于同一数据包的所有缓冲区将系统调用限制为1,而不必为所有缓冲区分配空间,然后复制内容只是为了调用write
。
您可以在此处详细了解该方法:https://en.wikipedia.org/wiki/Vectored_I/O