我的 under-linux c 程序有什么问题: "ls -al | tr a-z A-Z > file.txt"?

4

我对 Linux 和相关技术非常陌生,无法让脚本正常运行。我猜测程序在执行 tr 函数时被挂起了。

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

int main()
{

int pdesc[2];
pipe(pdesc);

int a = fork();

if (a == 0) // child
    {

    dup2(pdesc[1],1); // chaning std_out to pipes_out
    execlp("ls", "ls", "-l", "-a", NULL);

    }
else       //parent
    {
    wait();
    int file1 = open("file.txt", O_WRONLY|O_CREAT|O_TRUNC,0777);
    dup2(pdesc[0], 0); // chaning std_in to pipes_in
    dup2(file1, 1); // chaning std_out to file's stream
    execlp("tr", "tr", "a-z", "A-Z", NULL);
    }



return 0;
}

1
是这样的吗:"参数列表必须以NULL指针终止,并且由于这些是可变参数函数,因此此指针必须转换为(char *) NULL。"? - Daniel Fischer
你的输出文件不应该是可执行的,它是一个数据文件,而不是程序。我建议它不应该是公共可写的,很可能也不是组可写的,但这是我的安全问题(并且umask可能会解决这个问题)。 - Jonathan Leffler
1个回答

6
经典错误,所以这是一个好问题。
你需要在父进程和子进程中关闭未使用的管道文件描述符。
从管道读取的进程(本身)具有打开的管道写入端口,因此管道永远不会完全关闭,因此永远不会传递EOF。
此外,wait(2)导致死锁,程序没有包括,并且对wait(2)的调用缺少必需的参数。因为shell将等待父进程完成但不等待子进程,所以实际上在这里放置一个wait(2)调用会很好。但是,在当前的两个进程设计中,您没有地方放置它,因为在父进程的execlp(2)之后,您无法控制。修复的一种方法是让父进程再次fork(),并让原始PID除了在循环中等待(2)所有子进程完成之外什么也不做。
以下是一个工作版本,还要注意更改输出文件模式。
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
int pdesc[2];

    pipe(pdesc);

    int a = fork();

    if (a == 0) { // child
        dup2(pdesc[1],1); // chaining std_out to pipes_out
        close(pdesc[1]);
        close(pdesc[0]);
        execlp("ls", "ls", "-l", "-a", NULL);
    } else {      //parent
        int file1 = open("file.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
        dup2(pdesc[0], 0); // chaning std_in to pipes_in
        dup2(file1, 1); // chaning std_out to file's stream
        close(pdesc[0]);
        close(pdesc[1]);
        close(file1);
        execlp("tr", "tr", "a-z", "A-Z", NULL);
    }
    return 0;
}

它在没有wait()的情况下工作,但我不确定为什么。wait()不是(没有参数的)等待子进程死亡吗? - Patryk
问题在于wait需要在关闭操作之后但在execlp之前才能勉强工作。但是在那个位置,如果ls产生足够的输出以使自己被挂起,它可能会导致死锁。(内核不会缓冲任意数量的正在传输的管道内容。)请查看man 2 wait以了解如何正确调用。 - DigitalRoss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接