0

我的作业有问题,我要上课。我必须创建一个读/写程序,它将一个文本文件读入其中并将内容写入一个新的文本文件。问题是,我必须使用父/子进程和管道。我必须将内容与一个孩子一起传递到管道中,并使用另一个孩子从管道中读取数据并将其写入新文件。

我有三个文件parent.cread.cwrite.c. 该程序在大多数情况下运行良好!它甚至可以完美地将数据从一个文件传输到另一个文件。我遇到的问题是 write.c 过程永远不会完成。我认为这可能与从管道读取有关(不会返回 0 或 EOF)。这是我的源代码:

父.c

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

#define BUFF_SIZE 255

int main(int ac, char* av[]) 
{   
    if(ac <3)
    {
        printf("Please enter all required arguments!\n");   
        exit(0);    
    }
    
    int pfd[2];
    int pipeCreated;
    
    char readFile[50];
    char writePipe[20];
    
    pid_t child_pid_read;
    pid_t child_pid_write;
    
    pipeCreated = pipe(pfd);
    
    if(pipeCreated == -1)
    {
        printf("An error occurred when trying to create a pipe\n");
        exit(0);
    }
    
    strcpy(readFile, av[1]);
    sprintf(writePipe,"%d", pfd[1]);
    
    child_pid_read = fork();
    
    char writeFile[50];
    char readPipe[20];
    
    //Handling the read()
    switch(child_pid_read) 
    {
        //Error in case forfk() failed
        case -1:
            perror("fork failed");
            return 1;
            
            //Handle child processes
        case 0:
             if(close(pfd[0]) == -1)
             {
                 printf("An error occurred while closing the pipe\n");
                 exit(0);
             }
             if(execle("./read.out", "./read.out", readFile, writePipe, (char*)0, NULL) == -1)
             {
                 printf("Child: Error creating read.\n");
                 exit(0);
             }
        
        default:
            wait(&child_pid_read);
            
            strcpy(writeFile, av[2]);
            sprintf(readPipe,"%d", pfd[0]);
             
            child_pid_write = fork();
            break;
    }
    
    //Handling the write
    switch(child_pid_write) 
    {
        //Error in case fork() failed
        case -1:
            perror("fork failed");
            return 1;
            
        //Handle child processes
        case 0:
            if(close(pfd[1]) == -1)
            {
                printf("An error occurred while closing the pipe\n");
                exit(0);
            }
            
            if(execle("./write.out", "./write.out", writeFile, readPipe, (char*)0, NULL) == -1)
            {
                printf("Child: Error creating read.\n");
                exit(-1);
            }
            break;
        
        default:
            wait(&child_pid_write);
            break;
    }
    printf("Write completed!");
    return 0;
}

阅读.c:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#define BUFF_SIZE 16

int main(int ac, char* av[]) 
{   
    char buffer[BUFF_SIZE];
    int fd;
    int pid;
    
    if(ac > 1)
    {
        fd = open(av[1], O_RDONLY);
        if(fd == -1)
        {
            printf("error: Could Not Open File\n");
            exit(0);
        }
        
        pid = atoi(av[2]);
        
    }
    
    int num_read = 1;
    
    while(1)
    {
        num_read = read(fd, buffer, BUFF_SIZE);
        
        if(num_read == -1)
        {
            printf("Error reading file\n");
            exit(0);
        }
        
        if(num_read == 0)
        {
            break;
        }
                
        if(write(pid, buffer, num_read) != num_read)
        {
            printf("Error writing to pipe\n");
            break;
        }
    }
    close(fd);
    return 1;
}

写.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#define BUFF_SIZE 1

int main(int ac, char* av[]) 
{
    char buffer[BUFF_SIZE];

        int fd = open(av[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
        
        int pid = atoi(av[2]);
        
        int num_read = 1;
    
    while(1)
    {
            num_read = read(pid, buffer, BUFF_SIZE);
            
            printf("num_read: %d\n", num_read);
            
            if(num_read == -1)
            {
                printf("Error reading pipe\n");
                break;
            }
            
            if(write(fd, buffer, num_read) != num_read)
            {
                printf("Error writing to file\n");
                break;
            }
            
            if(num_read == EOF)
            {
                break;
            }
    }
        
        close(fd);
        return 1;
}

请查看我的代码并提出更正建议。我正在通过终端 ( ./parent.out, oldFile.txt, newFile.txt) 传递文本文件的名称。

4

2 回答 2

1

两个问题:

  1. 在等待()读取过程返回之前,您不会分叉写入过程。如果读取进程尝试写入的数据超出管道缓冲区的容量,它将阻塞并且永远不会退出。您需要允许两个进程同时运行以避免这种死锁。它适用于一个小文件,但如果文件大于 4KB,它将挂起。
  2. 分叉写入进程后,父进程必须关闭pfd[0]。在所有打开写端的进程关闭它之前,管道的读取器不会得到 EOF。它应该是:

    default:
        if(close(pfd[0]) == -1)
         {
             printf("An error occurred while closing the pipe\n");
             exit(0);
         }
        wait(&child_pid_write);
        break;
    
于 2012-09-13T06:37:05.610 回答
0

您的孩子想要读取数据,为什么要关闭 fd[0],从管道返回,表明 fd[0] 用于读取,fd[1] 用于写入。由于我无法添加评论,我必须发表评论这里....

于 2012-09-13T05:51:31.323 回答