Posix / Linux:
int pipe(int pipefd[2]);
pipefd[0]
относится к концу чтения канала.
pipefd[1]
относится к концу записи канала.
Linux Speci c:
int pipe2(int pipefd[2], int flags);
Когда дело доходит до CreateProcess
, версия Posix / Linux выполняется в несколько шагов.
- Вызов
fork()
для создания нового процесса, в котором все еще выполняется одна и та же программа, поэтому теперь два процесса продолжат выполнение одной и той же программы из той же точки, где был вызван fork()
. Определение, является ли это родительским процессом или дочерним процессом, выполняется путем проверки возвращаемого значения (идентификатора процесса) из fork()
. dup
файловых дескрипторов, возвращаемых pipe
с использованием int dup2(int oldfd, int newfd);
для замены stdin
и stdout
для нового процесса. Выполнение программы в новом процессе с использованием одной из функций exec*
.
// create pipes here
if(pid_t pid = fork(); pid == -1) {
// fork failed
} else if(pid == 0) { // child process goes here (with a new process id)
// dup2(...)
// exec*()
} else { // parent process goes here
// do parenting stuff
}
Пример:
#include <unistd.h>
#include <sys/types.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
struct Pipe {
Pipe() {
if(pipe(io)) throw std::runtime_error("pipe failure");
}
~Pipe() {
close_rd();
close_wr();
}
void close_rd() { closer(io[0]); }
void close_wr() { closer(io[1]); }
int rd() { return io[0]; }
int wr() { return io[1]; }
private:
void closer(int& fd) {
if(fd != -1) {
close(fd);
fd = -1;
}
}
int io[2];
};
int main() {
Pipe parent_write, parent_read;
if(pid_t pid = fork(); pid == -1) {
// fork failed
return 1;
} else if(pid == 0) { // child process goes here (with a new process id)
// close file descriptors we don't need:
parent_write.close_wr();
parent_read.close_rd();
// duplicate into the place where stdin/stdout was
dup2(parent_write.rd(), fileno(stdin));
dup2(parent_read.wr(), fileno(stdout));
// execute a program
execl("/bin/ls", "/bin/ls", nullptr);
// exec* functions never returns if successful, so if we get here, it failed:
std::exit(1);
} else { // parent process goes here
std::cout << "child process " << pid << " started\n";
}
// close file descriptors we don't need:
parent_write.close_rd();
parent_read.close_wr();
// read data from child process using the file descriptor in parent_read.rd()
char buf[1024];
ssize_t rv;
while((rv = read(parent_read.rd(), buf, 1024))) {
write(fileno(stdout), buf, static_cast<size_t>(rv));
}
// use write(parent_write.wr(), ...) to write to the child.
}