我一直有一些关于管道连接的问题,我在寻找一些关于这个问题的澄清-下面是我使用的c程序的一个示例。
我有两个演示程序,它们将stdin从文件中取出,并将stdout / stderr放入一系列管道中。然后将这些管道送入两个比较程序,其中一个程序获取两个演示程序的stdout,另一个程序获取两个演示程序的stderr。
就目前情况而言,我不确定在适当地将每个子节点连接起来之后,应该关闭其中的哪些管道。任何指导将不胜感激。
jobStruct job_handler(char* jobLine, char* testProgram, char* filename, int jobNumber, int isQuiet, int counter) {
jobStruct jobStatus;
jobStatus.exitStatus = 0;
int pipeOne[2];
int pipeTwo[2];
int pipeThree[2];
int pipeFour[2];
pipe (pipeOne);
pipe (pipeTwo);
pipe (pipeThree);
pipe (pipeFour);
pid_t pidList[4];
for (int i = 0; i < PROGRAM_SIZE; i ++) {
pid_t status = fork();
if (!status) {
if (i == 0) {
int inputFile = open (filename, O_RDONLY);
args[0] = "test-program-one";
for (int i = 0; i < argCount; i ++) {
args[i + 1] = jobArgs[i];
}
args[argCount + 1] = NULL;
// Pipes
dup2(inputFile, STDIN_FILENO);
dup2(pipeOne[WRITE_END], STDOUT_FILENO);
dup2(pipeTwo[WRITE_END], STDERR_FILENO);
// Close pipes here.
// Exec
execvp(args[0], args);
// Job failed to load.
job_failed(jobNumber);
} else if (i == 1) {
int inputFile = open (filename, O_RDONLY);
args[0] = "test-program-two";
for (int i = 0; i < argCount; i ++) {
args[i + 1] = jobArgs[i];
}
args[argCount + 1] = NULL;
// Pipes
dup2(inputFile, STDIN_FILENO);
dup2(pipeThree[WRITE_END], STDOUT_FILENO);
dup2(pipeFour[WRITE_END], STDERR_FILENO);
// Close pipes here.
// Exec
execvp(args[0], args);
// Job failed to load.
job_failed(jobNumber);
} else if (i == 2) {
dup2(pipeOne[READ_END], 3);
dup2(pipeThree[READ_END], 4);
// Close pipes here.
// Exec
char* cmpArgs[3];
char jobArg[14];
snprintf(jobArg, 14, "Job %i stdout", jobNumber);
cmpArgs[0] = "comparison-program";
cmpArgs[1] = jobArg;
cmpArgs[2] = NULL;
execvp("comparison-program", cmpArgs);
// Job failed to load.
job_failed(jobNumber);
} else {
dup2(pipeTwo[READ_END], 3);
dup2(pipeFour[READ_END], 4);
// Redirect to dev/null if isQuiet == 1
int devNull = open("/dev/null", 0);
if (isQuiet) {
dup2(devNull, STDOUT_FILENO);
dup2(devNull, STDERR_FILENO);
} else {
close (devNull);
}
// Close pipes here.
char* cmpArgs[3];
char jobArg[14];
snprintf(jobArg, 14, "Job %i stderr", jobNumber);
cmpArgs[0] = "comparison-program";
cmpArgs[1] = jobArg;
cmpArgs[2] = NULL;
execvp("comparison-program", cmpArgs);
// Job failed to load.
job_failed(jobNumber);
}
} else {
pidList[i] = status;
}
}
...
// Further processing
}
我尝试关闭每个子进程的所有非dup 2管道末端,但这不起作用,反而导致程序超时。任何帮助/指导将不胜感激!
1条答案
按热度按时间toe950271#
这个问题可能是由于管道过早关闭,当调用
pipe(pipeOne);
、pipe(pipeTwo);
、pipe(pipeThree)
和pipe(pipeFour);
碰巧创建了文件描述符3和4,这些文件描述符被child 2和child 3重新分配。子级2和子级3需要避免过早关闭文件描述符3和4。对于儿童2,更改:
类似于:
对于孩子3,更改:
类似于:
在
dup2
调用之后,子级0和1应关闭pipeOne
、pipeTwo
、pipeThree
和pipeFour
的两端。假设STDOUT_FILENO
和STDERR_FILENO
在调用pipe()
之前已经打开,则不需要进行特殊检查以避免过早关闭管道,而上面的fd 3和4需要进行这种检查。通过将
pipeOne
、pipeTwo
、pipeThree
和pipeFour
替换为8个文件描述符的一维数组或4×2个文件描述符的二维数组,代码可以变得不那么冗长。