c-使用管道进行读写



我有一个带有两个子进程的程序,它必须执行以下操作:

  • 使用父级从文件"data.txt"读取数据并写入管道
  • 使用子项从管道中读取数据并过滤小写字母
  • 使用另一个子项将筛选后的字母写在新文件中,每一个都在新行上

我试过了,它成功了。。。有点问题是,它将过滤后的字母写入所需的文件,但程序不会停止。我做错了什么?

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>

int parentChildpipeFileDescriptors[2], child1Child2FileDescriptors[2];

void parentProcess()
{
close(child1Child2FileDescriptors[0]);
close(child1Child2FileDescriptors[1]);
close(parentChildpipeFileDescriptors[0]);

int fileDescriptor = open("data.txt", O_RDONLY);
char buffer[8];
int store;
while ((store = read(fileDescriptor, buffer, 8)))
{
write(parentChildpipeFileDescriptors[1], buffer, store);
}
close(fileDescriptor);

close(parentChildpipeFileDescriptors[1]);
}

void child1Process()
{
close(parentChildpipeFileDescriptors[1]);
close(child1Child2FileDescriptors[0]);

char buffer[8];
int store, count = 0;
while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8)))
{
for (int i = 0; i < store; i++)
{
if (buffer[i] >= 'a' && buffer[i] <= 'z')
{
count++;
write(child1Child2FileDescriptors[1], &buffer[i], sizeof(buffer[i]));
}
}
}
printf("CHILD 1 FINISHED FILTERINGn");

close(parentChildpipeFileDescriptors[0]);
close(child1Child2FileDescriptors[1]);

exit(count);
}

void child2Process()
{
close(parentChildpipeFileDescriptors[0]);
close(child1Child2FileDescriptors[1]);

mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
char *fileName = "stat.txt";
int newFileDescriptor = creat(fileName, mode);
char buffer;
int store;
while ((store = read(child1Child2FileDescriptors[0], &buffer, 1)))
{
write(newFileDescriptor, &buffer, sizeof(buffer));
write(newFileDescriptor, "n", 1);
}
close(newFileDescriptor);

printf("CHILD 2 FINISHED WRITING'n");

close(child1Child2FileDescriptors[0]);
close(parentChildpipeFileDescriptors[1]);

exit(444);
}

int main(int argc, char const *argv[])
{
if (pipe(parentChildpipeFileDescriptors) < 0)
{
printf("ERROR CREATING PIPEn");
exit(-100);
}

if (pipe(child1Child2FileDescriptors) < 0)
{
printf("ERROR CREATING PIPEn");
exit(-101);
}

pid_t child1PID = fork();
if (child1PID < 0)
{
printf("ERROR CREATING CHILDn");
exit(-200);
}
if (!child1PID)
{
child1Process();
}

pid_t child2PID = fork();
if (child2PID < 0)
{
printf("ERROR CREATING CHILDn");
exit(-201);
}
if (!child2PID)
{
child2Process();
}

parentProcess();
int status1, status2;
waitpid(child1PID, &status1, 0);
waitpid(child2PID, &status2, 0);
printf("CHILD 1 TERMINATED WITH EXIT STATUS: %dn", WEXITSTATUS(status1));
printf("CHILD 2 TERMINATED WITH EXIT STATUS: %dn", WEXITSTATUS(status2));

return 0;
}

child1process中的读取循环永远不会终止,因为child2仍然打开了该管道的写入端。您需要执行:

close(parentChildpipeFileDescriptors[1]);

在进入读取循环之前。一般规则是,如果进程不打算使用文件描述符,它应该立即关闭它。

您的while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8)))循环永远不会结束。

父母需要对孩子说,没有更多的数据了,它不会再进行一次读取。您可以通过发送一个特殊字节来完成此操作。

示例:

在父级中:

char endByte = 0x1;
write(parentChildpipeFileDescriptors[1], &endByte, 1);
//then close

在子项的while循环中:

if(buffer[i] ==  0x1){
printf("CHILD 1 FINISHED FILTERINGn");
fflush(stdout);
close(parentChildpipeFileDescriptors[0]);
close(child1Child2FileDescriptors[1]);
exit(count);
};

最新更新