将 UNIX 管道映射到 C++ std::cout
Mapping UNIX Pipe to C++ std::cout
我正在研究 C++ 中通信进程的选项。从将 Unix 管道绑定到 std::cout 的想法开始,但我可以让它工作。当直接使用 write(STDOUT_FILENO) 写入时,我得到了预期的结果。使用 std::cout 写入时,我得到更小且随机的输出。
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
int main() {
int pfd[2];
if(pipe(pfd) == -1){
std::cout << "Cannot create pipe" << std::endl;
return 0;
}
int pid = fork();
if(pid == -1){
std::cout << "Error on fork: " << errno << std::endl;
} else if(pid == 0) { // Child process
if(dup2(pfd[PIPE_WRITE],STDOUT_FILENO) < 0) {
std::cout << "Cannot redirect STDOUT: " << errno << std::endl;
return 0;
}
close(pfd[PIPE_WRITE]);
for(int i = 0; i < 8; i++){
int data = i;
write(STDOUT_FILENO,&data,sizeof(int)); // Works
//std::cout << data; // Don't work
}
} else { // Parent process
close(pfd[PIPE_WRITE]);
for(int i = 0; i < 8; i++){
int data;
ssize_t status;
if((status = read(pfd[PIPE_READ],&data,sizeof(int))) != sizeof(int)) {
std::cout << "Error (" << errno << ") on read: " << status << std::endl;
return -1;
}
std::cout << data << std::endl;
}
}
return 0;
}
让我们仔细看看你的写作:
write(STDOUT_FILENO,&data,sizeof(int)); // Works
//std::cout << data; // Don't work
第一个"working"版本以原始二进制形式将data
的内容写入标准输出。第二个 "non-working" 版本将 data
的值作为文本 写入标准输出。
如果 data
的值为 5
那么 write
调用将写入整数值 5
而 std::cout << data
将写入整数值 53
(使用ASCII encoding)。
当您在父级中以原始和二进制 int
形式读取数据时,这当然会产生影响。
如果你想将原始二进制数据写入 std::cout
你必须使用 std::ostream::write
:
std::cout.write(reinterpret_cast<char*>(&data), sizeof data);
以上行等同于您的 write
系统调用。
同样重要的是,以原始格式写入 int
将写入 sizeof(int)
个字节,通常为四个字节。将一位整数作为文本写入将写入一个字节。
您的循环将写入八个数字,这意味着如果使用 write
,它将写入 32 个字节 (4 * 8)。如果你使用 <<
输出到 std::cout
那么你将写入 8 个字节。当您阅读时,您将读取这 8 个字节并放入两个单个 int
值中,然后 read
调用将 return 0
因为管道已关闭。
这两个 int
的值取决于您的硬件架构,如果是 little-endian or big-endian。
我正在研究 C++ 中通信进程的选项。从将 Unix 管道绑定到 std::cout 的想法开始,但我可以让它工作。当直接使用 write(STDOUT_FILENO) 写入时,我得到了预期的结果。使用 std::cout 写入时,我得到更小且随机的输出。
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
int main() {
int pfd[2];
if(pipe(pfd) == -1){
std::cout << "Cannot create pipe" << std::endl;
return 0;
}
int pid = fork();
if(pid == -1){
std::cout << "Error on fork: " << errno << std::endl;
} else if(pid == 0) { // Child process
if(dup2(pfd[PIPE_WRITE],STDOUT_FILENO) < 0) {
std::cout << "Cannot redirect STDOUT: " << errno << std::endl;
return 0;
}
close(pfd[PIPE_WRITE]);
for(int i = 0; i < 8; i++){
int data = i;
write(STDOUT_FILENO,&data,sizeof(int)); // Works
//std::cout << data; // Don't work
}
} else { // Parent process
close(pfd[PIPE_WRITE]);
for(int i = 0; i < 8; i++){
int data;
ssize_t status;
if((status = read(pfd[PIPE_READ],&data,sizeof(int))) != sizeof(int)) {
std::cout << "Error (" << errno << ") on read: " << status << std::endl;
return -1;
}
std::cout << data << std::endl;
}
}
return 0;
}
让我们仔细看看你的写作:
write(STDOUT_FILENO,&data,sizeof(int)); // Works
//std::cout << data; // Don't work
第一个"working"版本以原始二进制形式将data
的内容写入标准输出。第二个 "non-working" 版本将 data
的值作为文本 写入标准输出。
如果 data
的值为 5
那么 write
调用将写入整数值 5
而 std::cout << data
将写入整数值 53
(使用ASCII encoding)。
当您在父级中以原始和二进制 int
形式读取数据时,这当然会产生影响。
如果你想将原始二进制数据写入 std::cout
你必须使用 std::ostream::write
:
std::cout.write(reinterpret_cast<char*>(&data), sizeof data);
以上行等同于您的 write
系统调用。
同样重要的是,以原始格式写入 int
将写入 sizeof(int)
个字节,通常为四个字节。将一位整数作为文本写入将写入一个字节。
您的循环将写入八个数字,这意味着如果使用 write
,它将写入 32 个字节 (4 * 8)。如果你使用 <<
输出到 std::cout
那么你将写入 8 个字节。当您阅读时,您将读取这 8 个字节并放入两个单个 int
值中,然后 read
调用将 return 0
因为管道已关闭。
这两个 int
的值取决于您的硬件架构,如果是 little-endian or big-endian。