Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模拟unix壳管_C++_Unix_Redirect_Pipe_Stdout - Fatal编程技术网

C++ 模拟unix壳管

C++ 模拟unix壳管,c++,unix,redirect,pipe,stdout,C++,Unix,Redirect,Pipe,Stdout,教育任务:想模仿管道符号(命令、方法)“|”的工作。程序从STDIN获取unix shell中类似的命令: command1 | command2 | command3 | .... 并且应该执行它,为每个命令将STDIN | STDOUT重定向到管道。最终输出重定向到result.out文件。应仅使用execlp和fork 第1个变体:适用于1-2个命令,但冻结3个或更多。我做错了什么:似乎我关闭了所有管道描述符 现在在第二个变体中,执行行被简化了,现在又出现了另一个问题:输出混乱。如何在命

教育任务:想模仿管道符号(命令、方法)“|”的工作。程序从STDIN获取unix shell中类似的命令:

command1 | command2 | command3 | ....
并且应该执行它,为每个命令将STDIN | STDOUT重定向到管道。最终输出重定向到result.out文件。应仅使用execlp和fork

第1个变体:适用于1-2个命令,但冻结3个或更多。我做错了什么:似乎我关闭了所有管道描述符

现在在第二个变体中,执行行被简化了,现在又出现了另一个问题:输出混乱。如何在命令之间正确传递管道

第三个变体:最接近正确,添加了更多调试信息。问题:如何正确连接中间儿童


第四种变体,固定逻辑,几乎正确:适用于1、3或更多命令,适用于2(以前工作正常)-奇怪:)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
无效拆分(常量字符串和str、向量和标记、,
常量字符串和分隔符=”)
{
//跳过开头的分隔符。
字符串::size\u type lastPos=str.find\u first\u not\u of(分隔符,0);
//查找第一个“非分隔符”。
字符串::size\u type pos=str.find\u first\u of(分隔符,lastPos);
while(string::npos!=pos | | string::npos!=lastPos)
{
//找到一个标记,将其添加到向量。
回推(str.substr(lastPos,pos-lastPos));
//跳过分隔符。请注意“not_of”
lastPos=str.find_first_not_of(分隔符,pos);
//查找下一个“非分隔符”
pos=str.find_first_of(分隔符,lastPos);
}
}
内联字符串修剪(字符串和字符串)
{
常量字符串空白(“\t\f\v\n\r”);
字符串::size_type pos=str.find_first_not_of(空白);
if(pos!=字符串::npos)
str.erase(0,pos);//前缀空格
pos=str.find_last_not_of(空格);
if(pos!=字符串::npos)
str.erase(pos+1);//删除空格
返回str;
}
void parse_命令(字符串和命令、字符串和名称、字符串和argc)
{
命令=修剪(命令);
字符串::size\u type pos=command.find\u first\u of(“”);
if(pos!=字符串::npos){
name=command.substr(0,位置);
argc=command.substr(pos+1,command.length()-pos-1);
}否则{
名称=命令;
argc=“”;
}
}
void exec_命令(uint n、向量和命令)
{
字符串名称,args;
parse_命令(命令[n]、名称、参数);
如果(args.length()>0)
execlp(name.c_str(),name.c_str(),args.c_str(),NULL);
其他的
execlp(name.c_str(),name.c_str(),NULL);
}
//谁-----(标准时间)-->pfd[1]--pfd[0]--(标准时间)-->wc-l
无效执行行(向量和命令,uint i,int*parent\u pfd=0)
{
int-pfd[2];
管道(pfd);
如果(i>0&&!fork()){
//孩子
printf(“子,i:%d\n”,i);
如果(i>1){
执行_线(命令、i-1、pfd);
关闭(pfd[1]);
关闭(pfd[0]);
}否则{
printf(“更深的子%d:%s,父\u pfd[0]=%d,父\u pfd[1]=%d,”
“pfd[0]=%d,pfd[1]=%d\n”,
getpid(),trim(命令[i-1]).c_str(),
父项pfd[0]、父项pfd[1]、pfd[0]、pfd[1];
关闭(标准文件号);
//if(母公司pfd)
//dup2(父管道pfd[1],标准管道文件号);//将标准管道复制到父管道输出
//否则
dup2(pfd[1],标准输出文件号);//将标准输出复制到管道输出
关闭(pfd[1]);
关闭(pfd[0]);
exec_命令(i-1,命令);
}
}否则{
if(母公司pfd){
printf(“中间子级,i:%d\n”,i);
printf(“中间子级%d:%s,父级\u pfd[0]=%d,父级\u pfd[1]=%d,”
“pfd[0]=%d,pfd[1]=%d\n”,
getpid(),trim(commands[i]).c_str(),parent_pfd[0],parent_pfd[1],
pfd[0],pfd[1]);
关闭(标准文件号);
dup2(pfd[0],STDIN_FILENO);//将STDIN复制到管道中
关闭(标准文件号);
dup2(父管道pfd[1],标准管道文件号);//将标准管道复制到父管道输出
关闭(pfd[1]);
关闭(pfd[0]);
exec_命令(i,命令);
}否则{
printf(“最终,i:%d\n”,i);
printf(“最终%d:%s,pfd=%p,父\u pfd=%p,pfd[0]=%d,pfd[1]=文件\n”,
getpid(),trim(命令[i]).c_str(),pfd,parent_pfd,pfd[0]);
int fd=打开(“结果输出”,O|RDWR | O|CREAT | O|TRUNC,S|IRUSR | S|IWUSR);
dup2(fd,STDOUT_FILENO);//将STDOUT复制到文件
dup2(pfd[0],STDIN_FILENO);//将STDIN复制到管道中
关闭(pfd[0]);//关闭重定向的as
关闭(pfd[1]);//此处不需要关闭写入
关闭(fd);
exec_命令(i,命令);
}
}
}
int main()
{
字符缓冲区[1024];
ssize_t size=read(标准文件号,缓冲区,1024);
如果(大小>0){
缓冲区[大小]='\0';
字符串命令=缓冲区;
矢量命令;
拆分(命令,命令,“|”);
执行命令行(commands,commands.size()-1);
}
返回0;
}

用于将管道连接到标准输入和输出的逻辑看起来有故障

int pfd[2];
pipe(pfd);
首先创建一个管道,大概是为了将一个进程的标准输出连接到另一个进程的标准输入。那很好

现在,让我们看一下代码的一部分,它将执行其中一个进程:

close(STDIN_FILENO);
close(STDOUT_FILENO);
dup2(pfd[0], STDIN_FILENO);     // Copy STDIN to pipe in
dup2(pfd[1], STDOUT_FILENO);    // Copy STDOUT to pipe out
close(pfd[0]);  // Close as was redirected
close(pfd[1]);  // Close as was redirected
exec_command(i, commands);
现在,我甚至不需要解释这个。您可以在这里阅读自己的注释,然后尝试解释为什么要将同一管道的两端连接到同一流程的标准输入和输出?这毫无意义。管道应将一个进程的标准输入连接到另一个进程的标准输出。在这种情况下,执行流程并附加其标准是没有意义的
close(STDIN_FILENO);
close(STDOUT_FILENO);
dup2(pfd[0], STDIN_FILENO);     // Copy STDIN to pipe in
dup2(pfd[1], STDOUT_FILENO);    // Copy STDOUT to pipe out
close(pfd[0]);  // Close as was redirected
close(pfd[1]);  // Close as was redirected
exec_command(i, commands);
int pfd_cur[2];
int in = -1;
int out = -1;
while (number_of_commands) { // process all commands from first to last
    number_of_commands--; // and set cur_command_number
    if(cur_command_number == 0) {
        if(number_of_commands > 0) {
            pipe(pfd_cur);
            out = pfd_cur[1];
            in = pfd_cur[0];
            // We process first command
            // collect command (STDIN_FILENO, out);
        } else {
            // We process first command and we have only one command
            // collect command (STDIN_FILENO, STDOUT_FILENO);
        }
    } else {
        if(number_of_commands == 0)
        {
            // We process last command
            // collect command(in, STDOUT_FILENO);
        } else {
            pipe(pfd_cur);
            out = pfd_cur[1];
            // We process intermediate command
            // collect command (in, out);
            in = pfd_cur[0];
        }
    }
}
struct node {
    // pipe num
    int in_fd;
    int out_fd;
    const char *command;
    char **argv;
    int agrc;
    struct node *next;
    struct node *prev;
};
void execute(struct node* command)
{
    if(!fork())
    {
        if(command->out_fd != 1)
        {
            close(STDOUT_FILENO);
            dup2(command->out_fd, STDOUT_FILENO);

        }
        if(command->in_fd != 0)
        {
            close(STDIN_FILENO);
            dup2(command->in_fd, STDIN_FILENO);
        }

        execvp(command->command, command->argv);

        close(command->out_fd);
        close(command->in_fd);
    }
}
void execute_line(vector<string> &commands, size_t i, int *parent_pfd = 0)
{
    int pfd[2];
    pipe(pfd);
    if(i > 0 && !fork()) {
        // Child
        if(i >= 1) {
            execute_line(commands, i-1, pfd);
            close(pfd[1]);
            close(pfd[0]);
        } else {
            printf("Deeper child %d: %s, parent_pfd[0]=%d, parent_pfd[1]=%d, "
                   "pfd[0]=%d, pfd[1]=%d\n",
                   getpid(), trim(commands[i-1]).c_str(),
                   parent_pfd[0], parent_pfd[1], pfd[0], pfd[1]);

            close(STDOUT_FILENO);
            dup2(pfd[1], STDOUT_FILENO);        // Copy STDOUT to pipe out

            close(pfd[1]);
            close(pfd[0]);

            exec_command(i - 1, commands);
        }
    } else {
        if(parent_pfd) {
            printf("Middle child %d: %s, parent_pfd[0]=%d, parent_pfd[1]=%d, "
                   "pfd[0]=%d, pfd[1]=%d\n",
                   getpid(), trim(commands[i]).c_str(), parent_pfd[0], parent_pfd[1],
                   pfd[0], pfd[1]);

            close(STDIN_FILENO);
            dup2(pfd[0], STDIN_FILENO);         // Copy STDIN to pipe in

            close(STDOUT_FILENO);
            dup2(parent_pfd[1], STDOUT_FILENO); // Copy STDOUT to parent pipe out

            close(pfd[1]);
            close(pfd[0]);

            exec_command(i, commands);
        } else {
            printf("Final %d: %s, pfd=%p, parent_pfd=%p, pfd[0]=%d, pfd[1]=file\n",
                   getpid(), trim(commands[i]).c_str(), pfd, parent_pfd, pfd[0]);
            int fd = open("result.out", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
            dup2(fd, STDOUT_FILENO);            // Copy stdout to file
            dup2(pfd[0], STDIN_FILENO);         // Copy STDIN to pipe in
            close(pfd[0]);  // Close as was redirected
            close(pfd[1]);  // Close WRITE as not necessary here
            close(fd);

            exec_command(i, commands);
        }
    }
}