我试图创建一个程序,其中父项从文件中读取一些操作,使用管道将它们传递给子项,并且子项使用bc进行所有操作。稍后,孩子必须将其传递回父母,并且必须将其写在文件上。
然而,当我执行它时,我没有得到任何结果,也不知道问题出在哪里。孩子似乎正确地接受了手术,但是有了&EXTS' EXT'字符。
当父母没有从文件中读取时,我的代码工作正常,问题是当我尝试从文件中读取时。
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EOL '\n'
int main(int argc, char *argv[]){
int tube1[2];
int tube2[2];
int fID;
pipe(tube1);
pipe(tube2);
if(argc != 2){
perror("./yourProgram.c [origin]");
exit(EXIT_FAILURE);
}
if (fork() == 0){
//Child Process
close(tube1[1]); // writing end of the pipe
dup2(tube1[0], 0); // stdin ----> pipe reading end
close(tube2[0]); // reading end of the pipe
dup2(tube2[1], 1); // stdout ---> pipe writing end
//Execute and write the output in the tube2
execlp("bc", "bc", "-q", NULL);
}else {
//Parent Process
close(tube1[0]); // reading end of the pipe
//dup2(tube1[1], 1); // stdout ---> pipe writing end
close(tube2[1]); // reading end of the pipe
//dup2(tube1[1], 1); // stdout ---> pipe writing end
//Files
//Destiny
char *destiny = "final.txt";
int destinyFile = open(destiny, O_WRONLY | O_CREAT | O_TRUNC, 0644);
//Origin
char *origin = argv[1];
int originFile = open(origin, O_RDONLY);
//Variables
char block;
char result;
char buffer[4096];
int i = 0;
int numbytes;
while(numbytes = read(originFile, &block, sizeof(block)) > 0){
if(block == EOL){
//Write on the tube, so the child can read it
if(write(tube1[1], buffer, strlen(buffer)) == -1){
perror("error en write en pipe");
exit(EXIT_FAILURE);
}
//Read the child's answer
while(numbytes = read(tube2[0], &result, 1) > 0){
if(result != EOL){
//Concatenate strings as: 'X + Y = Result \n'
char str[80];
strcat(str, buffer);
strcat(str, " = ");
strcat(str, &result);
strcat(str, "\n");
//Write the result in the Final File
if(write(destinyFile, str, strlen(str)) == -1){
perror("error en write en stdout");
exit(EXIT_FAILURE);
}
}else
continue;
}
//Reset Buffer
buffer[0] = '\0';
i = 0;
}else{
buffer[i] = block;
i = i + 1;
}
}
}
}
我读到的文件是:
2+3
4*5
8/2
quit
答案 0 :(得分:1)
此代码修复了注释中提到的关键问题(但不是一次读取一个字节的性能问题)。如果计算产生的结果足够大,bc
将其输出分成多行(例如,计算因子100)。代码不会尝试处理这个问题。此外,某些操作不会产生任何输出。例如,c=2345
不产生任何输出。该程序也没有处理这个问题。
您没有在孩子中关闭足够的文件描述符。
经验法则:如果你
dup2()
管道的一端到标准输入或标准输出,关闭两端
管道尽快。
这意味着在使用任何之前
exec*()
特别是一系列的职能。
经验法则还包括使用
dup()
要么
fcntl()
与F_DUPFD
。
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define EOL '\n'
int main(int argc, char *argv[])
{
int tube1[2]; // Parent -> child
int tube2[2]; // Child -> parent
if (argc != 2)
{
perror("./yourProgram.c origin");
exit(EXIT_FAILURE);
}
pipe(tube1);
pipe(tube2);
if (fork() == 0)
{
// Child Process
dup2(tube1[0], 0); // stdin ----> pipe reading end
close(tube1[0]); // reading end of the pipe to child
close(tube1[1]); // writing end of the pipe to child
dup2(tube2[1], 1); // stdout ---> pipe writing end
close(tube2[0]); // reading end of the pipe to parent
close(tube2[1]); // writing end of the pipe to parent
// Execute and write the output in the tube2
execlp("bc", "bc", "-q", NULL);
perror("bc");
exit(EXIT_FAILURE);
}
else
{
// Parent Process
close(tube1[0]); // reading end of the pipe to child
close(tube2[1]); // writing end of the pipe to parent
// Files
// Destiny
char *destiny = "final.txt";
int destinyFile = open(destiny, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (destinyFile < 0)
{
perror(destiny);
exit(EXIT_FAILURE);
}
// Origin
char *origin = argv[1];
int originFile = open(origin, O_RDONLY);
if (originFile < 0)
{
perror(origin);
exit(EXIT_FAILURE);
}
// Variables
char block;
char result;
char buffer[256];
int i = 0;
int numbytes;
while ((numbytes = read(originFile, &block, sizeof(block))) > 0)
{
buffer[i++] = block;
//printf("Block: [%.*s]\n", i, buffer);
if (block == EOL)
{
// Write on the tube, so the child can read it
if (write(tube1[1], buffer, i) == -1)
{
perror("error en write en pipe");
exit(EXIT_FAILURE);
}
buffer[i-1] = '\0';
// Read the child's answer
int j = 0;
char reply[256];
while ((numbytes = read(tube2[0], &result, sizeof(result))) > 0)
{
reply[j++] = result;
//printf("Reply: [%.*s]\n", j, reply);
if (result == EOL)
{
// Concatenate strings as: 'X + Y = Result \n'
char str[256];
str[0] = '\0';
strcat(str, buffer);
strcat(str, " = ");
strcat(str, reply);
// Write the result in the Final File
if (write(destinyFile, str, strlen(str)) == -1)
{
perror("error en write en stdout");
exit(EXIT_FAILURE);
}
printf("Response: [%.*s]\n", j-1, reply);
break;
}
}
// Reset Buffer
i = 0;
}
}
close(tube1[1]);
close(tube2[0]);
}
return 0;
}
给出样本输入文件:
2+3
4*5
8/2
quit
屏幕上的输出是:
Response: [5]
Response: [20]
Response: [4]
,final.txt
中的输出为:
2+3 = 5
4*5 = 20
8/2 = 4