简体   繁体   中英

Pipe to and from child process is not working

I am trying to learn pipes and I am trying out this program:

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

#define MAXLINE 100
void main(){

int pipe1[2],pipe2[2];
pid_t childpid;
 if(pipe(pipe1)<0){
            perror("Unable to create the pipe for pipe1");
            exit(-1);
    }
    if(pipe(pipe2)<0){
            perror("Unable to create the pipe for pipe1");
            exit(-1);
    }
    childpid=fork();
    printf("The child PID is:%d\n",childpid);
    if(childpid==0){
            printf("In the child process");
            close(pipe1[1]);
            close(pipe2[0]);
            server(pipe1[0],pipe2[1]);
            exit(0);
    }

    close(pipe1[0]);
    close(pipe2[1]);

    client(pipe2[0],pipe1[1]);
    waitpid(childpid,NULL,0);
    exit(0);
}

void client(int readfd,int writefd){

    int n,len;
    char buff[MAXLINE];
    printf("Please enter the name of the file to be read:");
    fgets(buff,MAXLINE,stdin);
    len=strlen(buff);
    if(buff[len-1]=='\n')
            len--;

    write(writefd,buff,len);
    printf("File name written into the pipe\n");
    printf("The num of bytes written are:\n",read(readfd,buff,MAXLINE));
    while((n-read(readfd,buff,MAXLINE))>0){
            printf("Trying to read the content\n");
            write(STDOUT_FILENO,buff,n);
    }
}

void server(int readfd,int writefd){

    int fd,n;
    char buff[MAXLINE + 1];
    write(writefd,"Yello in the server process",strlen("Yello in the server process"));

    if((n=read(readfd,buff,MAXLINE))==0)
            perror("End of file while reading");
    buff[n]='\0';
    if((fd=fopen(buff,O_RDONLY))<0){
            snprintf(buff+n,sizeof(buff)-n,"Can't open, %s",strerror(errno));
            n=strlen(buff);
            write(writefd,buff,n);
    }
    while( (n=read(fd,buff,MAXLINE))>0){
            write(writefd,buff,n);
            close(fd);
    }
}

The problem is I enter the file name and the program just exits. I tried to gdb the child process by setting set "follow-fork-mode child", and still nothing happens. Any ideas as to where I could be going wrong?

Ok, some more additional debugging info is: I set the follow-fork-mode to child.and it is causing a segmentation fault at the opening of the file.

Program received signal SIGSEGV, Segmentation fault. [Switching to process 28025] 0x00197f08 in _IO_file_fopen () from /lib/libc.so.6

This code in client() looks suspicious:

while((n-read(readfd,buff,MAXLINE))>0){

Surely, that should be:

while ((n = read(readfd, buff, MAXLINE)) > 0)
{

The change from - to = is the important one, of course; the rest are cosmetic (and one is even controversial).


You should also pay attention to compiler warnings. Given:

int fd,n;
...
if((fd=fopen(buff,O_RDONLY))<0){

There's no way this should be compiling without major warnings; fopen() returns a FILE * , not a file descriptor ( int ).


You also seem to have some odd communications. The server sends a message to the client before reading the file name from the client. The client, OTOH, does not necessarily read that message separately; it gets a glob of information and reports how many bytes it got. That may have included some of the file as well as the introductory message.


You shouldn't close a file in the loop that is reading from it:

while( (n=read(fd,buff,MAXLINE))>0){
        write(writefd,buff,n);
        close(fd);
}

The close should be outside the loop.


This code more or less works; it is messier than I'd like, but it does more or less work.

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

#define MAXLINE 100

static void server(int readfd, int writefd);
static void client(int readfd, int writefd);

int main(void)
{
    int pipe1[2], pipe2[2];
    pid_t childpid;
    if (pipe(pipe1)<0)
    {
        perror("Unable to create the pipe for pipe1");
        exit(-1);
    }
    if (pipe(pipe2)<0)
    {
        perror("Unable to create the pipe for pipe2");
        exit(-1);
    }
    childpid = fork();
    printf("The child PID is:%d\n", childpid);
    if (childpid == 0)
    {
        printf("In the child process\n");
        close(pipe1[1]);
        close(pipe2[0]);
        server(pipe1[0], pipe2[1]);
        exit(0);
    }

    close(pipe1[0]);
    close(pipe2[1]);

    client(pipe2[0], pipe1[1]);
    waitpid(childpid, NULL, 0);
    return 0;
}

static void client(int readfd, int writefd)
{
    int n, len;
    char buff[MAXLINE];
    printf("Please enter the name of the file to be read:");
    fgets(buff, MAXLINE, stdin);
    len = strlen(buff);
    if (buff[len-1]=='\n')
            len--;

    write(writefd, buff, len);
    printf("File name (%.*s) written into the pipe\n", len, buff);
    printf("The num of bytes written are: %d\n", (int)read(readfd, buff, MAXLINE));
    while ((n = read(readfd, buff, MAXLINE)) > 0)
    {
            printf("Trying to read the content\n");
            write(STDOUT_FILENO, buff, n);
    }
}

static void server(int readfd, int writefd)
{
    int fd, n;
    char buff[MAXLINE + 1];

    fprintf(stderr, "Server: %d\n", (int)getpid());
    write(writefd, "Yello in the server process", strlen("Yello in the server process"));

    if ((n = read(readfd, buff, MAXLINE))==0)
        perror("End of file while reading");
    buff[n] = '\0';
    if ((fd = open(buff, O_RDONLY)) < 0)
    {
            snprintf(buff+n, sizeof(buff)-n, "Can't open, %s", strerror(errno));
            n = strlen(buff);
            write(writefd, buff, n);
    }
    else
    {
        while ((n = read(fd, buff, MAXLINE)) > 0)
        {
            if (write(writefd, buff, n) != n)
            {
                fprintf(stderr, "Write failed in server\n");
                break;
            }
        }
        close(fd);
    }
}

Note that the code does not try using a file descriptor that it fails to open. It does not crash; the n-read(...) problem is one major part of the trouble, comments notwithstanding. The misuse of fopen() for open() was another major part of the trouble.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM