如何解决如何在C中同步管道中的读写?
这里是完整的 C 初学者。 我正在尝试从子进程中写入一些字符串并读取父进程中的字符串。但看起来我没有正确实现读写。所以我的父母只是读取它得到的第一个字符串。下面是我的代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <ctype.h>
/* Function declaration */
bool isNumeric(char* str);
int main(int argc,char* argv[]) {
// Check if input is recieved
if (argc == 1) {
printf("Input not received!\n");
exit(1);
}
// Check if the input is an int
if (isNumeric(argv[1]) == 0) {
printf("Input is not an Integer!\n");
exit(1);
}
// Initialize pipe
int fd[2];
pid_t childpid;
pipe(fd);
childpid = fork();
if (childpid == -1) {
printf("fork failed");
exit(1);
}
else if (childpid > 0) {
char string[100];
close(fd[1]);
printf("PARENT START\n");
while (read(fd[0],string,sizeof(string)) > 0) {
printf("%s\n",string);
}
printf("PARENT END\n");
close(fd[0]);
}
else {
close(fd[0]);
char string[100];
string[0] = '\0';
printf("CHILD START\n");
for (int i = 0; i < 5; i++) {
sprintf(string,"%d",i);
write(fd[1],strlen(string)+1);
}
printf("CHILD END\n");
close(fd[1]);
exit(0);
}
}
输出只是
PARENT START
CHILD START
CHILD END
0
PARENT END
我的预期输出是
PARENT START
CHILD START
CHILD END
0
1
2
3
4
PARENT END
我花了几个小时试图同步这个过程,但我不知道如何解决这个问题。
解决方法
您忽略了 read
的返回值,因此对 printf
的调用在第一个零字节处停止。您发送由零字节分隔的消息。在接收到的数据中找到零字节并从管道中提取消息的代码在哪里?
您有发送消息的代码。它用终止零字节分隔消息。接收消息、在传入数据流中搜索零字节并将其之前的数据作为消息传递的代码在哪里?
这里有一些丑陋、低效的代码来接收消息。它检查传入的字节流是否有终止的零字节。它在文件末尾返回 0
,错误时返回负数,成功时返回 1
。:
int recvMessage (int fd,char* buf,int len)
{
while (len > 0)
{
int r = read(fd,buf,1);
if (r <= 0) // pipe closed or error
return r;
if (*buf == 0) // we received a terminating zero byte
return 1;
buf++;
len--;
}
return -2; // message larger than buffer
}
,
你需要学习的五件事:
-
sizeof(string)
不会返回字符串的长度,更不用说您还没有读过的!在这种情况下,它总是返回 100。 -
write
不能保证写入作为其第三个参数提供的字节数。您需要重复调用write
,直到您要写入的整个缓冲区都已写入。 -
read
不能保证读取作为其第三个参数提供的字节数。您需要反复调用read
,直到读取了所需的字节数。 -
在这种情况下,您不想读取特定数量的字节。你想读到你读过的一个字符是 NUL 为止。
-
除非您为
1
的第三个参数传递read
,否则您最终可能会阅读太多。这不是问题;你只需要在下次阅读时考虑到这一点。
作家
替换
write(fd[1],string,strlen(string)+1);
与
char *p = string;
size_t n = strlen(string) + 1;
while (n > 0) {
ssize_t rv = write(fd[1],p,n);
if (rv == -1) {
perror("write");
exit(1);
}
n -= rv;
p += rv;
}
阅读器
替换
char string[100];
while (read(fd[0],sizeof(string)) > 0) {
...
}
与
#define BLOCK_SIZE 100
char *string = NULL;
size_t size = 0;
size_t len = 0;
while (1) {
// Increase the buffer size if necessary.
if (size < len + BLOCK_SIZE) {
char *tmp = realloc(string,len + BLOCK_SIZE);
if (!tmp) {
perror("realloc");
exit(1);
}
string = tmp;
}
// Read from the pipe.
ssize_t rv = read(fd[0],string+len,BLOCK_SIZE);
if (rv == -1) {
perror("read");
exit(1);
}
// Handle EOF
if (rv == 0)
break;
len += rv;
// Check if we've received a message (or even more than one).
while (1) {
for (size_t i=0; i<len; ++i) {
if (!string[i]) {
// Handle a message.
...
len -= i+1;
memmove(string,string+i+1,len);
break;
}
}
}
}
// Handle a partial message.
if (len) {
fprintf(stderr,"Premature EOF");
exit(1);
}
free(string);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。