使用execlp的输出和管道来解决问题

时间:2014-06-29 16:43:10

标签: c exec pipe stdout

我正在编写一个程序,其界面如下: myprog file1 file2 c

这个程序用execlp打开文件2创建两个子节点和P2,在这个文件上创建一个grep -c用于创建c并将结果提供给他的兄弟P1(我必须关闭STDOUT的FD并加入管道p2p1它们之间)。 P1从p2p1接收该值并将该值发送到P0。此外,这也与file1相同,并将结果提供给P0,它将打印它们。

问题是:父亲P0读了一些东西,但这是错误的。

我该怎么办?这是代码,感谢您的关注。

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

#define MAX_STRING_LENGTH 128


/**************************/
/* DICHIARAZIONE FUNZIONI */
/**************************/
void wait_child();
void processo_p2(char *inputfile, char *c);
void processo_p1(char *inputfile, char *c);

/*********************/
/* VARIABILI GLOBALI */
/*********************/
int p1p0[2], p2p1[2];


int main(int argc, char* argv[])
{
    int pid[2], i, value, count=0;
    char *c, buf[10];

    if (argc !=4) 
    {
        fprintf(stderr, "Numero di argomenti errato\n");
        fprintf(stderr, "Usage: %s file1 file2 C\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    c=argv[3];

    /* Init */

    pipe(p1p0);
    pipe(p2p1);

    for (i=0; i<2; i++) 
    {
        pid[i] = fork();
        if (pid[i] < 0)
        {
            fprintf(stderr, "P0: Errore nella fork");
            exit(EXIT_FAILURE);
        }
        else if (pid[i] == 0) 
        {
            if (i==0) /*P1*/
            {
                close(p1p0[0]);
                close(p2p1[1]);
                sleep(1);
                    processo_p1(argv[1], c);
                    close(p2p1[0]);
        close(p1p0[1]);
            exit(EXIT_SUCCESS);
        }
        else if (i==1)
        {
            close(p2p1[0]);
            close(p1p0[0]);
            close(p1p0[1]);
            processo_p2(argv[2],c);
            close(p2p1[1]);
            exit(EXIT_SUCCESS);
        }
    }
    else
    {
        printf("P0: created child P%d with PID %d\n", i+1, pid[i]);
        close(p2p1[0]);
        close(p2p1[1]);
        close(p1p0[1]);
    }
} 
i=0;
int nread;
while ( (nread = read(p2p1[0], &buf[i], sizeof(char)) ) > 0 ) {
    i++;
buf[i] = '\0';
printf("%s\n",buf);

for(i=0;i<2;i++)
{
    wait_child();
}

return 0;
}

void processo_p2(char *inputfile, char *c)
{
int fd, nread, i=0, found=0;
char temp, row[100];

close(1);
dup(p2p1[1]);
execlp("grep", "grep", "-c", c, inputfile, (char *)0);
perror("P2: errorr in exec");
close(1);
}

void processo_p1(char *inputfile, char *c)
{
int fd, nrw, sk, nread, p2=0, i=0;
int value=1;
char temp, row[100], buf[10];

//RECEIVING DATA FROM P2 AND SENDING TO P0

while ( (nread = read(p2p1[0], &buf[i], sizeof(char)) ) > 0 ) {
    i++;
}
buf[i] = '\0';
printf("from p2: %s\n",buf); //NOTHING STAMPED
write(p1p0[1],&buf,strlen(buf)+1);

close(1);
dup(p1p0[1]);
execlp("grep", "grep", "-c", c, inputfile, (char *)0);
perror("P1: errore in exec");
close(p1p0[1]);
}


void wait_child() {
int pid_terminated,status;

pid_terminated=wait(&status);
if (pid_terminated < 0)
{
    fprintf(stderr, "%d\n", getpid());
    perror("P0: errore in wait");
    exit(EXIT_FAILURE);
}
if(WIFEXITED(status))
{
    printf("P0: terminazione volontaria del figlio %d con stato %d\n",
            pid_terminated, WEXITSTATUS(status));
    if (WEXITSTATUS(status) == EXIT_FAILURE)
    {
        fprintf(stderr, "P0: errore nella terminazione del figlio pid_terminated\n");
        exit(EXIT_FAILURE);
    }
}
else if(WIFSIGNALED(status))
{
    fprintf(stderr, "P0: terminazione involontaria del figlio %d a causa del segnale %d\n",
            pid_terminated,WTERMSIG(status));
    exit(EXIT_FAILURE);
}
}

1 个答案:

答案 0 :(得分:0)

Trivia(但它会停止代码编译):最初显示的代码在错误的位置有一个紧密的括号 - 这些函数显然都嵌入在main()中。最后一个大括号应该大大向上移动。

在启动子进程的循环中,您有父进程执行:

    printf("P0: created child P%d with PID %d\n", i+1, pid[i]);
    close(p2p1[0]);
    close(p2p1[1]);
    close(p1p0[1]);

在父进程中,紧接在循环之后,您有:

int nread;
while ( (nread = read(p2p1[0], &buf[i], sizeof(char)) ) > 0 ) {
    i++;
buf[i] = '\0';
printf("%s\n",buf);

for(i=0;i<2;i++)
{
    wait_child();
}

return 0;
}

&#39;很遗憾您关闭了您尝试阅读的文件描述符。父母应该从p1p0[0]开始阅读,你确实已经开放了。

修正:

  • 将三个闭合的一组移出循环。
  • 从正确的文件描述符中读取。
  • 为显示的while循环插入缺少的大括号,或移除其左大括号。

评论中的问题与评论一样,具有难以理解的代码。但问题是你的循环太大了。

这就是我的main()函数的固定版本的尾部:

 …rest of loop to launch children…
        else
        {
            printf("P0: created child P%d with PID %d\n", i + 1, pid[i]);
        }
    }

    close(p2p1[0]);
    close(p2p1[1]);
    close(p1p0[1]);

    i = 0;
    int nread;
    while ((nread = read(p1p0[0], &buf[i], sizeof(char)) ) > 0)
        i++;
    buf[i] = '\0';
    printf("%s\n", buf);

    for (i = 0; i < 2; i++)
    {
        wait_child();
    }

    return 0;
}

鉴于我已将源代码保存在文件pip.c中并从中创建了程序pip,因此生成了一个示例运行:

$ ./pip pip.c pip.c c
P0: created child P1 with PID 75458
P0: created child P2 with PID 75459
from p2: 49

49

P0: terminazione volontaria del figlio 75459 con stato 0
P0: terminazione volontaria del figlio 75458 con stato 0
$

我对所有换行都不满意,但至少会给出两次相同的答案,因为它显然应该是。