我有一个任务是写3个与管道连接在一起的过程。第一个应该从用户读取输入,第二个应该从第1个读取并且使字母大写,3个应该从第2个读取并打印结果。问题是scanf只读取第一个按下的字符,然后程序结束。我做错了什么?我试图发送硬编码的字符串,它工作得很好。
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#define ODCZYT 0
#define ZAPIS 1
int main(){
char readbuffer[80];
char tempbuffer[80];
char printbuffer[80];
int i=0;
int potok[2];
int potok2[2];
pid_t pid_A, pid_B, pid_C;
pipe( potok );
pipe( potok2);
puts( "fork" );
if(!(pid_A = fork()) )
{
puts("Podaj string:");
close(potok[ODCZYT]);
close(potok2[ODCZYT]);
close(potok2[ZAPIS]);
scanf( "%s", readbuffer )
write(potok[ZAPIS],readbuffer, sizeof(readbuffer));
close(potok[ZAPIS]);
}
if(!(pid_B = fork()) )
{
close( potok[ZAPIS] );
close(potok2[ODCZYT]);
read( potok[ODCZYT], tempbuffer, sizeof(tempbuffer));
close(potok[ODCZYT]);
while(tempbuffer[i]){
tempbuffer[i]=toupper(tempbuffer[i]);
i++;
}
write(potok2[ZAPIS],tempbuffer, sizeof(tempbuffer));
close(potok2[ZAPIS]);
}
if( !(pid_C = fork()) ) {
close(potok[ODCZYT]);
close(potok[ZAPIS]);
close(potok2[ZAPIS]);
read( potok2[ODCZYT], printbuffer, sizeof(printbuffer));
puts(printbuffer);
close(potok2[ODCZYT]);
}
return 0;
}
答案 0 :(得分:1)
问题代码可能会做出更多预期。它不是创建3个进程,而是创建7个进程,不包括main()
进程,实际上是8个进程。
线程[main()]确实创建了线程[A],[B]和[C]。
线程[A]在第一个if
块内完成工作,然后继续创建线程[B1]和[C1]。
线程[B]在第二个if
块内完成工作,然后继续创建线程[C2]。
线程[B1]在第二个if
块内完成工作,然后继续创建线程[C3]。
要查看,总线程包括[main()],[A],[B],[C],[B1],[C1],[C2]&amp; [C3]。
这不是问题描述所表明的。
要修复代码,请在每个'if'块的底部放置一个return(0)
语句,这将导致每个线程只执行其中'if'块中的任务。
一个小小的修正......改变:
scanf( "%s", readbuffer )
为:
scanf( "%s", readbuffer ); //<-- Add semicolon
使用内容
创建test.txt
文件
uppercase
然后运行程序:
> ./test < test.txt
打印'UPPERCASE'的结果
为什么scanf()仅在从键盘输入时读取一个字符,但在从文件读取时有效?
问题是线程同步问题。线程[main()]终止,shell程序(即:Bash等)试图重新获得控制权;但是线程[A]的scanf()需要一个事件(例如传入的字符)才能意识到它是时候终止(和终止)了。一旦按下一个键,线程[A]就会吞噬它,但是线程[A]会立即终止,而不会从键盘处理该字符。 scanf()
永远不会真正返回!一旦线程[A]终止,shell程序(即:Bash等)就会重新获得对键盘的控制权。
如何解决这个问题?
让线程[main()]等待线程[C]终止。更改程序结束,添加waitpid()
电话:
waitpid(pid_C, NULL, 0);
return(0);
(当然,为了引用waitpid()
,您必须添加相应的.h文件。)
可在以下位置找到固定代码:http://www.mahonri.info/SO/23743011_pipes-and-fork-scanf-is-reading-only-one-character.c }
答案 1 :(得分:0)
read()和write()不保证返回您要求的所有字节。检查read()和write()调用的返回值,以查看实际读取和写入的字符数。您可能需要循环才能获得所有这些内容。此外,我没有运行您的代码段,但您没有对父进程执行任何操作。您需要在每个条件结束时退出父级,以防止它运行下一个部分,这可能会产生不良后果。