使用管道读写
Read and write using pipes
我有一个包含 2 个 child 进程的程序,它必须执行以下操作:
- 使用parent从文件中读取数据'data.txt'并写入管道
- 使用child从管道中读取数据并过滤小写字母
- 使用另一个 child 将过滤后的字母写入新文件,每个字母占一个新行
我试过了,效果不错……有点。问题是,它将过滤后的字母写入所需的文件,但程序不会停止。我做错了什么?
#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 FILTERING\n");
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 PIPE\n");
exit(-100);
}
if (pipe(child1Child2FileDescriptors) < 0)
{
printf("ERROR CREATING PIPE\n");
exit(-101);
}
pid_t child1PID = fork();
if (child1PID < 0)
{
printf("ERROR CREATING CHILD\n");
exit(-200);
}
if (!child1PID)
{
child1Process();
}
pid_t child2PID = fork();
if (child2PID < 0)
{
printf("ERROR CREATING CHILD\n");
exit(-201);
}
if (!child2PID)
{
child2Process();
}
parentProcess();
int status1, status2;
waitpid(child1PID, &status1, 0);
waitpid(child2PID, &status2, 0);
printf("CHILD 1 TERMINATED WITH EXIT STATUS: %d\n", WEXITSTATUS(status1));
printf("CHILD 2 TERMINATED WITH EXIT STATUS: %d\n", WEXITSTATUS(status2));
return 0;
}
你的 while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8)))
循环永远不会结束。
parent 需要告诉 child 没有更多的数据来了,它不会再读了。
你可以通过发送一个特殊的字节来做到这一点。
示例:
在parent:
char endByte = 0x1;
write(parentChildpipeFileDescriptors[1], &endByte, 1);
//then close
在 child 的 while 循环中:
if(buffer[i] == 0x1){
printf("CHILD 1 FINISHED FILTERING\n");
fflush(stdout);
close(parentChildpipeFileDescriptors[0]);
close(child1Child2FileDescriptors[1]);
exit(count);
};
child1process 中的读取循环将永远不会终止,因为 child2 仍然打开该管道的写入端。你需要执行:
close(parentChildpipeFileDescriptors[1]);
在进入读取循环之前。一般规则是,如果进程不打算使用文件描述符,则应立即将其关闭。
我有一个包含 2 个 child 进程的程序,它必须执行以下操作:
- 使用parent从文件中读取数据'data.txt'并写入管道
- 使用child从管道中读取数据并过滤小写字母
- 使用另一个 child 将过滤后的字母写入新文件,每个字母占一个新行
我试过了,效果不错……有点。问题是,它将过滤后的字母写入所需的文件,但程序不会停止。我做错了什么?
#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 FILTERING\n");
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 PIPE\n");
exit(-100);
}
if (pipe(child1Child2FileDescriptors) < 0)
{
printf("ERROR CREATING PIPE\n");
exit(-101);
}
pid_t child1PID = fork();
if (child1PID < 0)
{
printf("ERROR CREATING CHILD\n");
exit(-200);
}
if (!child1PID)
{
child1Process();
}
pid_t child2PID = fork();
if (child2PID < 0)
{
printf("ERROR CREATING CHILD\n");
exit(-201);
}
if (!child2PID)
{
child2Process();
}
parentProcess();
int status1, status2;
waitpid(child1PID, &status1, 0);
waitpid(child2PID, &status2, 0);
printf("CHILD 1 TERMINATED WITH EXIT STATUS: %d\n", WEXITSTATUS(status1));
printf("CHILD 2 TERMINATED WITH EXIT STATUS: %d\n", WEXITSTATUS(status2));
return 0;
}
你的 while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8)))
循环永远不会结束。
parent 需要告诉 child 没有更多的数据来了,它不会再读了。 你可以通过发送一个特殊的字节来做到这一点。
示例:
在parent:
char endByte = 0x1;
write(parentChildpipeFileDescriptors[1], &endByte, 1);
//then close
在 child 的 while 循环中:
if(buffer[i] == 0x1){
printf("CHILD 1 FINISHED FILTERING\n");
fflush(stdout);
close(parentChildpipeFileDescriptors[0]);
close(child1Child2FileDescriptors[1]);
exit(count);
};
child1process 中的读取循环将永远不会终止,因为 child2 仍然打开该管道的写入端。你需要执行:
close(parentChildpipeFileDescriptors[1]);
在进入读取循环之前。一般规则是,如果进程不打算使用文件描述符,则应立即将其关闭。