【发布时间】:2021-02-21 14:05:23
【问题描述】:
对于 UNIX OS 课程中的练习,我应该开发一个程序,其中两个同级进程通过管道进行通信。一个进程(生产者)应该从标准输出读取字符串并将它们发送到另一个进程(消费者),然后必须将字符串转换为大写并再次将其打印到标准输出。字符串“end”终止了兄弟进程和父进程。
该程序运行良好,但是当尝试从用户那里读取整个短语而不是单个字符串时它会崩溃。
这是我的主要部分:
int main(void) {
int child_status, fd[2];
if (pipe(fd)) {
fprintf(stderr, "Error: Could not create pipe.\n");
return EXIT_FAILURE;
}
if (!fork()) {
// child1
producer(fd);
exit(0);
} else if (!fork()) {
// child2
consumer(fd);
exit(0);
} else {
// father
pid_t pid;
...
生产者进程:
void producer(int *fd) {
char buff[BUFFSIZE];
char *line;
close(fd[0]);
while (1) {
fflush(stdout);
fprintf(stdout, "Insert string:\t");
scanf("%[^\n]s%*c", buff);
fflush(stdout);
line = strdup(buff);
printToPipe(fd[1], line);
if (!strcmp(line, "end")) // Special string terminates process
return;
sleep(1);
}
return;
}
以及消费者进程:
void consumer(int *fd) {
char *buff;
close(fd[1]);
while (1) {
if ( (buff = readFromPipe(fd[0])) == NULL ) {
close(fd[0]);
return;
}
fprintf(stdout, "%s\n", strToUpper(buff));
fflush(stdout);
}
return;
}
printToPipe() 和 readfromPipe() 直接实现 read() 和 write() 系统调用。
意外行为:
一旦输入第一个短语并转换为大写,程序就会无限循环打印出提示和第一个大写短语(即:Insert string: TEST TEST)。特别是:
- 尽管我考虑了 \n 字符 (
scanf("%[^\n]s%*c", buff);),但后续的 scanfs 将被忽略。如果我检查 scanf 返回值,则第一次之后的所有迭代都为 0, - 似乎消费者通过其输出“自我维持”自身:它不等待通过管道的新输入并继续打印转换后的短语。
【问题讨论】:
-
"%[^\n]s%*c"-->"%[^\n]%*c"。[...]本身就是一个字段指令,而不是s指令的修饰符。您格式中的s尝试匹配文字 's' 字符。 -
它不能解决您的问题,那么我们可能需要查看minimal reproducible example。请注意,在这种情况下,准备一个将部分涉及将问题缩小到初始输入或通过管道传输数据
-
关于:
scanf("%[^\n]s%*c", buff);输入格式说明符:%[\n]将在输入流中保留 '\n'。所以下一个字符永远不会是s建议:scanf("%[^\n]%*c", buff); -
printToPipe和readFromPipe的定义在哪里???
标签: c loops process pipe scanf