写我自己的壳...停留在管?(Writing my own shell… stuck on pipe

2019-07-19 01:29发布

在过去的几天里,我一直在试图写我自己的壳实现,但我似乎已经得到了被困在得到管道正常工作。 我能够解析线和叉断管之间的命令(例如:LS |排序)分别,但似乎无法将它们从一个到另一个去管输入。

我想,我只是不知道如何使用DUP2()和管道正常。

现在我已经列入我的代码,仍然失败... :(如此坚持?

void forkAndExecute( char* arrayOfWords[] , vector<pid_t> *vectorOfPIDs , bool hasNextCmd , bool hasPrevCmd) {

int fd[ 2 ];
pid_t pid;

if( hasNextCmd ){
    pipe(fd);
}

pid = fork();

//error if PID < 0
if( pid < 0 ) {
    cerr << ">>> fork failed >>>" << endl;
    exit(-1);
}
//child process if PID == 0
else if( pid == 0 ) {
    if ( hasPrevCmd ){
        dup2(fd[0] , 0);
        close(fd[0]);
        close(fd[1]);

    }
    if ( hasNextCmd ){
        dup2(fd[1],1);
        close(fd[0]);
        close(fd[1]);
    }
    execvp( arrayOfWords[0] , arrayOfWords );
    cout << ">>> command not found >>>" << endl;
    //if logic reaches here, exec failed
    exit(0);
} 
//parent process
else{
    close(fd[0]);
    close(fd[1]);
    //if( ! isLastCmd ){

    //}
    vectorOfPIDs->push_back(pid);
}

}

Answer 1:

第一个建议:符号常量比幻数较好。

const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
int fd[2];
pipe(fd);
// Now you can refer to fd[PIPE_READ] and fd[PIPE_WRITE].

第二个建议:退一步,想想你要完成什么。

要产卵两个进程,连接到第二个进程的标准输入第一个进程的标准输出。 对?

所以,在C,这意味着你需要采取调用pipe ,通过fd[PIPE_WRITE]第一个孩子的过程,这将dup2它为1,并通过fd[PIPE_READ]的第二个孩子的过程,这将dup2它0。

简单地看forkAndExecute'的原型表明,它不能做到这一点:

void forkAndExecute( char* arrayOfWords[] , vector *vectorOfPIDs , 
    bool hasNextCmd , bool hasPrevCmd);

它只能处理一个命令,并从望着那参数列表,除非它诉诸恶全局变量,有没有办法为它接收来自其PrevCmd文件描述符或从NextCmd收到的文件描述符。

想想如何管理您需要的文件描述符,并重新设计forkAndExecute才能够使用这些。



Answer 2:

一般过程会增加错误处理此基础工艺(伪):

pipe(fds)
if (fork() is child) {
  dup2(fds[1], 1)
  close(fds[0])
  close(fds[1])
  exec("ls")
}
if (fork() is child) {
  dup2(fds[0], 0)
  close(fds[0])
  close(fds[1])
  exec("sort")
}
close(fds[0])
close(fds[1])
wait()

首先创建管道。 然后用叉子叉子进程,使他们继承它。 重新映射文​​件描述符为0(标准输入)和1(标准输出),这样的过程读写的适当位置。 关闭你不想要孩子的过程看或块,当工作完成后,对剩余的文件描述符。 EXEC实际子进程。 等他们到结束,你就大功告成了!



Answer 3:

好的。这是为我工作。 希望这可以帮助你:

/************************
function: void pipeCommand(char** cmd1, char** cmd2)
comment: This pipes the output of cmd1 into cmd2.
**************************/
void pipeCommand(char** cmd1, char** cmd2) {
  int fds[2]; // file descriptors
  pipe(fds);
  // child process #1
  if (fork() == 0) {
    // Reassign stdin to fds[0] end of pipe.
    dup2(fds[0], STDIN_FILENO);
    close(fds[1]);
    close(fds[0]);
    // Execute the second command.
    // child process #2
    if (fork() == 0) {
        // Reassign stdout to fds[1] end of pipe.
        dup2(fds[1], STDOUT_FILENO);
        close(fds[0]);
        close(fds[1]);
        // Execute the first command.
        execvp(cmd1[0], cmd1);
    }
    wait(NULL);
    execvp(cmd2[0], cmd2);
    }
    close(fds[1]);
    close(fds[0]);
    wait(NULL);
}


Answer 4:

这里有一个关于UNIX管道的教程,具体如何建设piplines在壳状结构:

http://www.cse.ohio-state.edu/~mamrak/CIS762/pipes_lab_notes.html

没有多少完全编写的代码,但它描述的概念相当不错。

你也可以下载源代码,几乎所有的壳,比如bash的 , tcsh的 , zsh的 ,等等。



Answer 5:

要读出的Bash的源代码 ,看看他们是如何做到的。



Answer 6:

当我需要一些年前做类似的壳,我用这本书实用的Unix编程 。

这是许多IPC主题的例子非常有用。 我仍然有我的办公桌上的副本,我从时间参考时间。 对于$ 2 - 使用$ 9这是你所得到的一个很好的价值。

对于它的价值,只是觉得我会提到它。



Answer 7:

这里是从系统编程类我把最后一个学期在管道的音符。



Answer 8:

您在每个程序的输入连接到它自己的输出。 你可能想每个程序的输出到下一个的输入端连接代替。

而不是去为一个管道处理的一般情况下,你应该有一个开始两个基础 ,并从那里展开。 如果您继续通过延长工作代码,而不是直接对结构复杂的拍摄,你会更好地理解的文件描述符插入到对方的方式。



Answer 9:

好了,我不知道答案,但我工作的同样的问题大气压。 我将分享我有什么。 它适用于两个命令,但运行完之后,I / O被打破。 在陌生的路上我一直没能还没有搞清楚。 叫水管工!

void pipeCommand(char** cmd1, char** cmd2) {
  int fds[2]; // file descriptors
  pipe(fds);
  int oldIn, oldOut;
  // child process #1
  if (fork() == 0) {
    // Reassign stdin to fds[0] end of pipe.
    oldIn = dup(STDIN_FILENO);
    dup2(fds[0], STDIN_FILENO);
    close(fds[1]);
    close(fds[0]);
    // Execute the second command.
    execvp(cmd2[0], cmd2);
  // child process #2
  } else if ((fork()) == 0) {
    oldOut = dup(STDOUT_FILENO);
    // Reassign stdout to fds[1] end of pipe.
    dup2(fds[1], STDOUT_FILENO);
    close(fds[0]);
    close(fds[1]);
    // Execute the first command.
    execvp(cmd1[0], cmd1);
  // parent process
  } else
    wait(NULL);
    dup2(oldIn, STDIN_FILENO);
    dup2(oldOut, STDOUT_FILENO);
    close(oldOut);
    close(oldIn);
}

我有一种感觉它有什么我还是等待后我没有做这样做()



文章来源: Writing my own shell… stuck on pipes?