C - 奇怪的fork()+ execl()行为

时间:2018-05-24 17:52:37

标签: c unix fork exec dup2

我将尝试尽可能具体地解决我的问题。我的目标是实现两个套接字(客户端/服务器);客户端必须向服务器发送awk命令+一些输入行。服务器必须使用给定的输入执行awk命令,并将每行awk的stdout和awk的每一行stderr发送回客户端,并与字符串“ERRLINEi”(i =行号)连接。

我问过如何做到这一点,因为我完全迷失了,我得到了很好的建议,使用fork,execl,pipe和dup2。所以我试着把它写下来:

execl("/usr/bin/awk", "awk", command, (char *)0)

但这不起作用。请注意,此函数在while循环中调用,循环直到从客户端接收新输入行。我真的不明白为什么所以我在函数调用之前(在调用run_awk()的main函数中)放了一个printf指令,结果是run_awk()在同一个进程中被多次调用同一个输入。

注意:我的* out和* err参数应该用于存储awk的结果。因为我只是想看看我的程序在做什么,所以我没有使用它们。

更新 我理解了代码中的一些错误。我把分叉部分带回主要功能,但我仍然有问题。实际上,我需要做的是:从父到子发送一个命令(有感觉的awk语法)(我实现了这个)然后让孩子从stdin一个接一个地读取输入行(随机文本),允许execl像这样跑:

if((t_fd = accept(l_fd, (struct sockaddr *)NULL, NULL)) < 0) sockerror(2, 0); //accept connection from client
    recv(t_fd, &com_len, sizeof(int), 0); //receive command length
    command = malloc(com_len+1);
    rbytes = recv(t_fd, command, com_len, 0); //receive command
    command[rbytes] = '\0';
    printf("Received command: %s\n", command);
    if((pipe(in_pipe)+pipe(out_pipe)+pipe(err_pipe)) < 0) syscallerror("pipe"); //init pipes
    bool check = true;
    while(recv(t_fd, &inp_len, sizeof(int), 0) > 0){ //receive single input line length - loop while there are lines to read
        memset(input, 0, inp_len+1);
        recv(t_fd, input, inp_len, 0);  //receive input line
        if((p = fork()) < 0) syscallerror("fork");
        if(p > 0){
            close(in_pipe[0]);  // Close reading end of first pipe
            if(check){ //this makes the server write the command in the pipe just once
                write(in_pipe[1], command, strlen(command));
                check = false;
            }
            write(in_pipe[1], input, strlen(input)); //write the input line

            //close(in_pipe[1]); //I can't close it because other lines will be sent in the loop
            close(out_pipe[1]);
            close(err_pipe[1]);
            int n = read(out_pipe[0], out, 300); //read should block until child has produced output (you can assume it will always produce it)
            int k = read(err_pipe[0], err, 300);
            if(n > 0) printf("parent %d: received output %s\n", getpid(), out);
            if(k > 0) printf("parent %d: received error %s\n", getpid(), err);
            close(out_pipe[0]);
            close(err_pipe[0]);
            memset(out, 0, 301);
            memset(err, 0, 301);
        }
        else{
            close(in_pipe[1]);  // Close writing end of first pipe
            char com[300]; // Read command using first pipe
            read(in_pipe[0], com, 300);
            // Close all reading ends
            close(out_pipe[0]);
            close(err_pipe[0]);
            dup2(in_pipe[0], 0); //set correct file descriptors
            dup2(out_pipe[1], 1);
            dup2(err_pipe[1], 2);
            close(in_pipe[0]);
            close(err_pipe[1]);
            close(out_pipe[1]);
            if(execl("/usr/bin/awk", "awk", com, (char *)0) < 0) syscallerror("execl");
            exit(0);
        }
    }
    close(in_pipe[1]);
    kill(p, SIGKILL);

我的新代码是:

    <ContentPage.Content>
        <ScrollView>
        <StackLayout 
            Padding="{Binding MainStackSidePadding}" 
            Spacing="15">
            <RelativeLayout 
            Padding="{Binding MainStackSidePadding}" 
            BackgroundColor="Red">
                <Image x:Name="logo" Source="testbar.png" HorizontalOptions="Center" HeightRequest="{Binding LogoSmallHeight}" 
                       RelativeLayout.XConstraint =
                            "{ConstraintExpression Type=RelativeToParent,
                                Property=Width,
                                Factor=0.5,
                                Constant=0}"
                        RelativeLayout.YConstraint =
                            "{ConstraintExpression Type=RelativeToParent,
                                Property=Height,
                                Factor=0,
                                Constant=0}"/>
                <Image x:Name="backButton" Source="back.png" HeightRequest="30"
                        RelativeLayout.XConstraint =
                            "{ConstraintExpression Type=RelativeToParent,
                                Property=Width,
                                Factor=0.025,
                                Constant=0}"
              RelativeLayout.YConstraint =
                            "{ConstraintExpression Type=RelativeToView,
                                ElementName = logo,
                                Property=Height,
                                Factor=0,
                                Constant=50}">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer
                    Command="{Binding GoBackCommand}"/>
                    </Image.GestureRecognizers>
                </Image>
            </RelativeLayout>
            <!--Some other elements and labels etc. -->
        </StackLayout>
    </ScrollView>
</ContentPage.Content>

如果您看到任何未初始化的变量,那是因为它们是在此循环之外声明的。我该如何解决这个问题?

0 个答案:

没有答案