簡體   English   中英

在 C shell 中實現管道

[英]implementing pipes in C shell

我是編程初學者,我正在實現 C shell 中的管道。

我發現一些使用 STDIN 的命令 shell output 開始無法正常工作。 例如光標移動。

直接使用 STDIN cat | echo hello的這種命令就是這種情況。 cat | echo hellotr | ls tr | ls

我檢查了它是否與未關閉的 fd 無關...我在 dup2 后立即關閉 pipe 的寫入端。 我在 pipe 的寫入端的 pipe 期間關閉了子進程中 pipe 的讀取端。

這是代碼,抱歉有點亂,它使用一個 int term->redir->pipe_fd 數組來處理多個 pipe 情況:

// For each pipe, it creates the pipe in a new instance of the int array term->redir->pipe_fd.  

int     make_pipe(t_term *term)  
{  
    int pipe_stack;  

    term->redir->pipe_stack++;  
    if (!((pipe_stack = term->redir->pipe_stack) < MAX_FD)  
            || pipe(term->redir->pipe_fd[pipe_stack]) == -1)  
    { 
        err_dup();  
        return (close_pipe(term));  
    }  
    return (0);  
}  

// left_pipe dup2 the write end of (pipe[1]) to the STDOUT, and closes the pipe's write end.  

int     left_pipe(t_term *term)  
{  
    int new_fd;  
    int pipe_stack;  

    new_fd = -1;  
    pipe_stack = term->redir->pipe_stack;  
    term->redir->pipe_write = 1;  
    if ((new_fd = dup2(term->redir->pipe_fd[pipe_stack][WRITE_END],
                    STDOUT_FILENO)) == -1)  
        ft_printf("[fd=2]21sh: %d: LEFT Bad file descriptor\n[/fd]",
                term->redir->pipe_fd[pipe_stack][WRITE_END]);  
    close(term->redir->pipe_fd[pipe_stack][WRITE_END]);  
    term->redir->pipe_fd[pipe_stack][WRITE_END] = -1;  
    return ((new_fd == -1) ? 1 : 0);  
}

// then, sh_exec is called, see below. The read end of the pipe is closes in the child processus. 
// right pipe dup2 the STDIN whith the readend of the pipe (pipe[0]) and closes it.

int     right_pipe(t_term *term)  
{  
    int new_fd;  
    int pipe_stack;  

    new_fd = -1;  
    pipe_stack = term->redir->pipe_stack;  
    term->redir->pipe_write = 0;  
    if (pipe_stack > FD_INIT)  
    {  
        term->redir->pipe_read = 1;  
        if ((new_fd = dup2(term->redir->pipe_fd[pipe_stack][READ_END],
                        STDIN_FILENO)) == -1)  
            ft_printf("[fd=2]21sh: %d: RIGHT Bad file descriptor\n[/fd]",
                    term->redir->pipe_fd[pipe_stack][READ_END]);  
        close(term->redir->pipe_fd[pipe_stack][READ_END]);  
        term->redir->pipe_fd[pipe_stack][READ_END] = -1;  
        term->redir->pipe_stack--;  
    }  
    return ((new_fd == -1) ? 1 : 0);  
}

在調用了左邊的 pipe 之后,它在下面調用了 exec function 並關閉了 pipe (pipe[0]) 的未使用的 read_end。 在調用了正確的 pipe 之后,它再次調用 exec function 來執行命令的正確部分:

void        wait_pipe(char *cmd, int *status)  
{  
    if (waitpid(-1, status, WNOHANG) == -1)  
        print_exec_error(cmd);  
}  

int         sh_exec(char *path, char **cmd, t_term *term)  
{  
    pid_t   father;  
    int     status;  

    status = 0;  
    father = fork();  
    if (father > 0 && term->redir->pipe_stack >= 0)  
        wait_pipe(*cmd, &status);  
    else if (father > 0)  
    {  
        if (waitpid(father, &status, 0) == -1)  
            print_exec_error(*cmd);  
    }  
    if (!father)  
    {  
        if (term->redir->pipe_write)  
            close(term->redir->pipe_fd[term->redir->pipe_stack][READ_END]);  
        if (execve(path, cmd, term->env) == -1)  
        {  
            ft_printf("[fd=2]Filetype unknown\n[/fd]");  
            exit(0);  
        }  
        err_not_found(*cmd);  
    }  
    return (status);  
}  

此外,我不明白使用以下命令cat | echo cat | echo 它返回一行的提示然后停止,不太可能是單獨的cat命令繼續並等待直到它收到停止信號。

如果有人有線索?

此外,我不明白使用以下命令cat | echo cat | echo 它返回一行的提示然后停止,不太可能是單獨的 cat 命令繼續並等待直到它收到停止信號。

我將嘗試解釋這里發生的事情:

$ cat | echo

foobar
$

第一個空行是echo命令僅打印\nstdout (因為它沒有任何參數),然后我得到提示,這是cat等待輸入,我鍵入foobar並按 enter( \n )。 我懷疑cat每行打印它的 output 行所以它試圖將foobar\n寫入其stdout ,但它的stdout是“管道”( | )到echostdinecho已經退出關閉它的stdin (因為他有沒什么可做的),所以cat試圖寫入一個封閉的 pipe 並獲得SIGPIPE SIGPIPE的默認行為是結束進程。

運行strace證實了這一切:

$ strace cat | echo
...
read(0, foobar
"foobar\n", 131072)             = 7
write(1, "foobar\n", 7)                 = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=6069, si_uid=1000} ---
+++ killed by SIGPIPE +++
$

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM