C++ microshell,输入命令并使用 fork()、dup()、pipe() 将其传送到进程。只是我没有得到我想要的结果

2023-12-07

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>


using namespace std;

//first comannd to execute
void first(int pipeA[], char * command[]){

  //redirect STDOUT to pipe[1] and close the pipe[0] we are not using
  dup2(pipeA[1], 1);
  close(pipeA[0]);

  execvp(command[0], command);
  printf(" first error ");
  exit(127);
}

void second(int pipeA[], char * command2[]){

  //redirect STDIN to pipe[0] and close the pipe[1] that we are not using
  dup2(pipeA[0], 0);
  close(pipeA[1]);

  //This doesnt seem to be doing anything at times
  execvp(command2[0], command2);
  perror(" second error ");
  exit(127);

}


int main(void)
{
  char buf[1024];
  char * command[1024];// this one is the first input usually 'cat file.txt'

  //Use only one or the other, sort never works and 'grep U' works sometimes
  char * command2[] = {(char *)"sort", (char *) NULL};// this is wants to sort the above 'command[1024]' and its use in the second function
  //char * command2[] = {(char *)"grep",(char *)"U",(char *) NULL};// this is wants to grep the above 'command[1024]' and its use in the second function

  //variables for forks and waits
  pid_t pid;
  pid_t pid2;
  int  status;
  int  status2;

  //see if || exists not in use currently
  bool pipeExists = false;

  //create pipe
  int pipeA[2];
  pipe(pipeA);

  //first line and ask for input,
  cout<< "command: ";

  while (fgets(buf,1024,stdin) != NULL)
 {
    buf[strlen(buf) -1] = 0; 

    //Save input into buf and tokenized? it
    //NOT YET CATCHING ||, im only debugging and usually use use 'cat file.txt'
    int number =0;
    char * ptr;
    ptr = strtok(buf, " ");
    while(ptr != NULL){
        command[number] = ptr;
        ptr = strtok(NULL, " ");
        number++;
    }

    //***************************************************************
    //1. do the pipes go here or after the children?
    //They seem to be working here but im not really sure where they should be
    close(pipeA[0]);
    close(pipeA[1]);

   //create first child
   if ((pid = fork()) <0)
    printf("fork error");
   else if (pid == 0) 
    { /* child */

        //create second child INSIDE ORIGINAL CHILD
        //2. Is this correct? or is there not supposed to be grandchildren?
        if ((pid2 = fork()) <0)
        printf("fork 2 error");
        else if (pid == 0) 
        { /* child */
         second(pipeA, command2);
         printf("couldn't execute: %s");
         exit(127);
        }


        //first command from buf
         first(pipeA, command);
         printf("couldn't execute: %s");
         exit(127);


        //3. Do I wait for this child aswell? 
        if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
          printf("waitpid error");
    }


   /* parent */ 
   if ( (pid = waitpid(pid, &status, 0)) < 0)
    printf("waitpid error");  
   printf("Command :");
   //***************************************************************

   //***************************************************************
   //SECOND WAY OF DOING IT
   // THIS WAY IT TRIGGERS WAITPID ERRORS.
   /*
    close(pipeA[0]);
    close(pipeA[1]);

   //create first child
   if ((pid = fork()) <0)
    printf("fork error");
   else if (pid == 0) 
    { 
     first(pipeA, command);
     printf("couldn't execute: %s");
     exit(127);
    }
    //create second child INSIDE ORIGINAL CHILD
    if ((pid2 = fork()) <0)
    printf("fork 2 error");
    else if (pid == 0) 
    { 
     second(pipeA, command2);
     printf("couldn't execute: %s");
     exit(127);
    }

    //3. Do I wait for this child aswell? 
    if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
      printf("waitpid error");


     if ( (pid = waitpid(pid, &status, 0)) < 0)
      printf("waitpid error");  
     printf("Command :");
   */
   //***************************************************************
 }

   exit(0);
} 

代码几乎显示了这里的内容及其问题。

我需要创建一个微外壳,它接受命令(“cat file.txt”)并使用 execvp() 执行它,并将其通过管道传输到另一个进程,然后“排序”或“grep U”或任何其他。

只是我的进程有时无法正确运行或不会显示任何内容。我已经关闭了所有地方的管道,但没有发生任何事情。


OP 的解决方案。

这是适用于 microshell 的代码。

我最终在原始父进程中创建了两个进程。

在 while 循环内移动一些变量并重置它们以再次工作。还要在每次代码运行时创建管道并关闭管道。

为两个进程而不只是一个进程创建了一个 waitpid() 。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;


//This function will execute the users first command.
//It takes in a pipe the command array and a boolean to check for piping
//If a pipe exists then the boolean is true and will dup() the STDOUT into the write part of the pipe
//We close unecessary parts of the pipe and execvp() the command in the command array
//there it some error checkink in case the command doesn't execute
void first_command(int pipeA[], char * command[], bool pipeExists){

  if(pipeExists){
    dup2(pipeA[1], 1);
    close(pipeA[0]);
  }

  execvp(command[0], command);
  printf("can not execute first command. \n");
  exit(127);
}

//This function is only called in the main is a piping exists
//It takes in a pipe and a command array
//It dup() the STDIN from the read end of the pipe and closes the unsued end
//It will execute the command accorind to what was provided in the the pipe
void second_command(int pipeA[], char * command2[]){

  dup2(pipeA[0], 0);
  close(pipeA[1]);

  execvp(command2[0], command2);
  printf("can not execute second command. \n");
  exit(127);

}


int main(void)
{
  //this variable will take in the line of input submitted by the user
  char buf[1024];

  //PIDs for the two child processes
  pid_t pid;
  pid_t pid2;

  //these will be use to check the status of each child in the parent process
  int  status;
  int  status2;

  //initializes the pipe
  int pipeA[2];

  //out put the first line to ask user for input
  cout<< "480shel> ";

  //stay inside the loop and keep asking the user for input until the user quits the program
  while (fgets(buf,1024,stdin) != NULL){

    //initialize a boolean to check if user wants to pipe something, set to false by default until we check with user
    bool pipeExists = false;

    //initialize this arrays to NULL so anything that store in them gets cleared out.
    //these arrays will hold the commands that the user wants to carry out.

    char * command[1024] = {NULL, NULL, NULL};
    char * command2[1024] = {NULL, NULL, NULL};

    //Important to delete mark the last byte as 0 in our input
    buf[strlen(buf) -1] = 0;

    //initialize this number to zero to start save the tokens at this index 
    int index = 0;

    //a char * to hold the token saved by strtok
    char * ptr;
    ptr = strtok(buf, " ");

    //Loop through 'buf' and save tokens accordingly
    while(ptr != NULL){

      //If ptr is equal to q or quit then user want to exit program
      if(strcmp( ptr, "q" ) == 0){
        exit(0);
      }
      if(strcmp( ptr, "quit" ) == 0){
        exit(0);
      }

      //if ptr is equal to || user wants to pipe something and we change pipeExists to true
      if(strcmp( ptr, "||" ) == 0){
        pipeExists = true;
        index= 0;
        ptr = strtok(NULL, " ");
      }

      //enter here while user doesnt want to user pipes
      if(!pipeExists){
        command[index] = ptr;
        ptr = strtok(NULL, " ");
        index++;
      }

      //enter here if user want to use pipes
      if(pipeExists){
        command2[index] = ptr;
        ptr = strtok(NULL, " ");
        index++;
      }
    }

    //if pipes exists then initialize it
    if(pipeExists){
      pipe(pipeA);
    }

    //create first child
    if ((pid = fork()) == 0) {
      //pass in the pipe, commands and pipe to function to execute
      first_command(pipeA, command, pipeExists);
    }
    else if(pid < 0){
      //error with child
      cerr<<"error forking first child"<<endl;
    }

    // if pipe exists create a second process to execute the second part of the command
    if(pipeExists){

      //create second child 
      if ((pid2 = fork()) == 0) {
        second_command(pipeA, command2);
      }
      else if(pid2 < 0){
        //error with second child
        cerr<<"error forking second child"<<endl;
      }
    }

    //if the pipe was created then we close its ends
    if(pipeExists){
      close(pipeA[0]);
      close(pipeA[1]);
    }

    //wait for the first child that ALWAYS executes
    if ( (pid = waitpid(pid, &status, 0)) < 0)
      cerr<<"error waiting for first child"<<endl;

    //wait for the second child bu only if user wanted to created to use piping
    if(pipeExists){
      if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
        cerr<<"error waiting for second child"<<endl;
    }


    cerr<<"480shell> ";

  }//endwhile
  exit(0);
} 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ microshell,输入命令并使用 fork()、dup()、pipe() 将其传送到进程。只是我没有得到我想要的结果 的相关文章

  • 使用 strcpy 从整数生成指针,无需进行强制转换

    我不明白我做错了什么 我正在学习 C 很抱歉 如果这显然是错误的 但我正在尝试使用uthash http uthash sourceforge net 制作股票及其价格的哈希图 但是当我将股票添加到哈希映射时 我收到上述错误 我所做的就是从
  • 使用 C# 和反射打印完整的对象图

    我有一个复杂的对象 class A int Field1 int field2 property ClassB ClassB property classC classC etc etc 我想使用反射打印完整的对象图 有什么好的代码吗 一种
  • 如何正确实现带有 close 方法的处置模式(CA1063)

    框架设计指南 第二版 第 327 页 说 考虑提供方法Close 除了Dispose 如果接近 是该领域的标准术语 这样做时 重要的是使 Close 实现与Dispose并考虑实施IDisposable Dispose方法明确 因此 按照提
  • 如何获取 PropertyGrid 的单元格值 (c#)?

    如何在 C 中获取属性网格项和项的值 例如 Name Ali LastName Ahmadi Name 和 LastName 是 propertygrid 的 2 个属性 PropertyGrid只是对象的组件模型表示的视图 我会说 查看组
  • Apple IOS 上的 C# 应用程序 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有基于 C Net 的应用程序 有什么方法可以在 Apple IOS 上运行这些应用程序吗 我没有资
  • C# While 循环与 For 循环?

    在 C 中 一个问题已经困扰我一段时间了 它的 While 和 For 循环之间的实际主要区别是什么 它只是纯粹的可读性吗 在 for 循环中本质上可以做的所有事情都可以在 while 循环中完成 只是在不同的地方 举这些例子 int nu
  • 获取进程的所有 DLL

    我想获取为给定进程加载的所有 dll 的列表 我目前正在使用 NET框架4 0 我知道有一个bug https connect microsoft com VisualStudio feedback details 546430 syste
  • 运行此处编译的 C 程序会导致在另一台服务器上找不到 GLIBC 库错误 - 是我的错还是他们的错?

    此处编译的 C 程序在我们的 Ubuntu 服务器上运行良好 但是当其他人尝试在他们的特定 Linux 服务器上运行它时 他们会收到以下错误 myprog install lib tls libc so 6 version GLIBC 2
  • C++中的虚方法表存放在哪里?

    我想知道类对象 不是实例 而是类 如何存储在内存中 class A public int a virtual void f virtual A class B public A public int b void f final overr
  • 在unity3D中显示数学方程

    我想使用它的 GUI 系统统一显示数学方程 有办法吗 我正在使用 C 语言在 Unity 中进行编程 如果我还可以使用 C 代码显示数学符号 这对我来说会很有用 谢谢 自 2016 年起 您可以使用TEXDraw https assetst
  • 随机排列

    我无法找到一种随机洗牌元素的好方法std vector经过一些操作后 恢复原来的顺序 我知道这应该是一个相当简单的算法 但我想我太累了 由于我被迫使用自定义随机数生成器类 我想我不能使用std random shuffle 无论如何这没有帮
  • 在 Ubuntu 16.04 上编译 PCL 1.7,CMake 生成的 Makefile 中出现错误

    我正在尝试让 PCL 1 7 点云库 而不是其他 pcl 在 Ubuntu 16 04 上运行 我最终希望用于 C 的东西 但现在我只是想让这些例子工作 我使用的是 Ubuntu GNU 5 3 1 附带的默认编译器和 Cmake 版本 3
  • 初始化二维数组时出现分段错误

    我已经检查过我的代码是否正确地划分了内存空间 但是一旦我尝试将 2D 数组初始化为某些值 然后对这些值求和 我就会在 2x2 数组上收到分段错误 我想最终将我的代码扩展到更大的数组 但我什至无法让它在这里工作 我知道有很多关于 malloc
  • Sharepoint 的 CAML 查询中的日期时间比较

    我正在尝试从共享点列表中获取某些项目 具体取决于自定义列中的日期 我已经使用 U2U Caml Builder 创建了查询 这很有效 但是当我将其放入 Web 部件中自己的代码中时 它总是返回列表中的所有项目 这是我的代码 DateTime
  • 如何正确对齐 WPF GeometryGroup 中的路径?

    我正在使用一个GeometryGroup在圆的中心绘制一个符号 下面的示例显示了我在对此进行实验时的尝试之一 它具有从同一原点 32 32 出发的三条直线
  • 有没有办法将复选框列表绑定到 asp.net mvc 中的模型

    我在这里寻找一种快速简便的方法来在模型中发生回发时绑定复选框列表项的列表 显然现在常见的做法似乎是这样的form GetValues checkboxList 0 Contains true 这看起来很痛苦而且不太安全 有没有一种方法可以绑
  • 错误:C# 尝试读取或写入受保护的内存

    我很难纠正这个错误 该应用程序在 4 台不同的机器上进行了测试 在其中 3 台上运行良好 但一台 Vista PC 在尝试通过 WebBrowser1 打开页面时出现此错误 解决这个问题的任何帮助对我都会非常有帮助 System Acces
  • 在 C# 中设置风扇速度

    我知道以前有人问过这个问题 但我似乎无法让它发挥作用 我已调用以下内容 using System Management using System Management Instrumentation using System Runtime
  • 我可以创建一个 List> 吗?

    我正在尝试创建一个列表WeakReference使用 4 5 泛型实现 这样我就可以避免类型检查和转换WeakReference目标 但 WeakReference
  • Eclipse (C/C++) 错误:平台关闭后发现作业仍在运行

    当我打开 Eclipse 时 它 在一小时前工作过 但在启动时冻结并给出错误 发生错误 请参阅日志文件 请参阅下面的日志文件 尽管其中一些信息出现在日志中 操作系统 Mac OSX 10 7 5 Eclipse 面向 C C 开发人员的 E

随机推荐

  • 仅当使用列列表且 IDENTITY_INSERT 为 ON 时,才能指定表“Table”中标识列的显式值

    有人知道这个错误是什么 仅当使用列列表且 IDENTITY INSERT 为 ON 时 才能指定表 HD AANVRAAG FASE 中标识列的显式值 描述 执行当前 Web 请求期间发生未处理的异常 请查看堆栈跟踪以获取有关错误及其在代码
  • 如何使用VBA为大文件生成md5哈希值?

    我有以下函数来生成文件的 md5 哈希值 这些函数非常适合小文件 但会崩溃并生成运行时错误 7 内存不足当我尝试对超过 250 MB 的文件进行哈希处理时 我实际上不知道它会破坏到哪个确切大小 但低于 200 MB 的文件工作正常 我不明白
  • PHP 中的“无法在写入上下文中使用函数返回值”错误

    致命错误 无法使用函数返回 第 3 行写入上下文中的值 在什么情况下会触发此类错误 我的程序 QUERY VARIABLE query select form user where user name user name and user
  • 使用自定义角度指令扩展 ng-bootstrap popover 组件

    我试图实现的是扩展 ngbPopover 指令并将所有这些属性包装在自定义指令中 而不是仅显示它们以包含我的指令 例如 我正在使用 ngbpopover 如下所示
  • 如何将模块添加到项目的 Eclipse Oxygen 模块路径?

    我有一个项目 今天有几个罐子作为 参考库 相反 我想将它们添加为模块路径上的自动模块 这样我就可以在我的 module info java 中需要它们 如何将 jar 添加到 Eclipse Oxygen 中的模块路径 以下是我如何让它工作
  • 文档正文为空

    我有一个正在使用 Mootools 1 2 4 的页面MediaboxAdvanced作为灯箱 由于特定的 javascript 错误 我似乎无法让该功能正常工作 文档正文为空 Mediabox 初始化时 document body ado
  • Process.Start 的 VB 6 等效项是什么?

    我真的被这一行困住了 在 vb net 中这很容易 但是在 vb6 中如何做到这一点 试图从谷歌搜索几个小时 但一无所获 感觉几乎很尴尬 这是代码 网 Process Start runme exe parameter1 parameter
  • MATLAB 中的特征选择方法?

    我正在尝试在 MATLAB 中使用 SVM 进行一些文本分类 并且真的很想知道 MATLAB 是否有任何特征选择方法 Chi Sq MI 因为我想尝试各种方法并保持最好的方法 我没有时间全部实施 这就是我在 MATLAB 中寻找此类方法的原
  • NetConnection.Call.Failed 在 Flex3/Tomcat/BlazeDS/Spring 中偶尔发生

    我有一个很大的问题 我使用 Flex3 Tomcat BlazeDS Spring 编写了一个大型应用程序 该应用程序在本地开发时运行良好 在部署到公共开发环境时运行良好 但在部署到我们的测试环境时经常失败 当远程处理请求花费大量时间 超过
  • 在每个套接字的基础上调整 MTU?

    我想知道是否有任何方法可以调整 在 Linux 系统上 给定套接字的 MTU 使 IP 层分段成小于实际设备 MTU 的块 当我说对于给定的套接字时 我并不是指在拥有该套接字的应用程序代码中以编程方式 而是在外部 例如通过 sysfs 条目
  • 我可以更改 json_encode 的默认选项吗

    我在 PHP 文档中找不到任何与此相关的内容 因此如果不将 json encode 包装在专有函数中 这可能是不可能的 但我想知道是否可以在 php ini 或其他地方设置 json encode 函数的默认选项 目的是始终启用 JSON
  • iOS6 - 在应用程序内购买并从 Apple 服务器下载

    我能够成功进行应用内购买并从 Apple 服务器下载内容并使用它 我的应用内购买内容是非消耗性的 所以我在我的应用程序中提供 恢复 按钮现在 当用户按下 恢复 按钮时 我将调用该方法 restoreCompletedTransactions
  • 将图像转换为颜色数组

    我在 Java 中加载图像并希望将其转换为 RGB 数组 以便我可以读取每个像素的颜色 我在谷歌上搜索 但我只找到了如何将颜色数组转换为图像 以下几行说明了 API 方法的用法 BufferedImage bi ImageIO read n
  • 字典的深层复制在 Xcode 4.2 中给出分析错误

    我在 NSDictionary 类别中有以下方法来进行深度复制 效果很好 我刚刚从 Xcode 4 1 升级到 4 2 Analyze 函数针对此代码给出了两个分析器警告 如下所示 id deepCopy id dict NSMutable
  • BackboneJS:什么是选项 || (选项={});在主干源代码中

    我正在浏览 BackboneJS 源代码 无法弄清楚这一行是什么options options 确实如此 因为没有对变量进行赋值 以下是 BackboneJS 的代码片段 var Model Backbone Model function
  • 如何隐藏 Google 表格中除一张以外的所有表格?

    我有一个其他人每天都会使用的电子表格 每天 脚本都会在其中创建许多附加工作表 最终用户无权创建 删除 隐藏或取消隐藏工作表 由于大量的工作表在一段时间内堆积起来 并且很难浏览工作表 作为清理的一部分 我想使用 Google Apps 脚本隐
  • 您如何解释与 ClearCase 的合并?

    我是一名开发人员 从来不需要担心源代码控制系统 分支 合并等的实现 我正在寻找解释这些概念但针对clearcase 用户的书籍 来自搜索亚马逊 书 IBM ClearCase 7 0 掌握监视 分析和管理软件配置的工具 作者 Marc Gi
  • 选择后组合框聚焦于文本开头

    我正在使用带有组合框的 winforms 该组合框的下拉宽度比其大小更宽 当用户从那里选择某些内容时 它仅显示文本的结尾而不是开头 我如何默认它显示以字符串开头开头的文本 IE 组合框有项目 美国佐治亚州亚特兰大 格鲁吉亚雅典 迈阿密 佛罗
  • PHP - IRC Bot 不发送消息帮助

    目前我正在制作一个 IRC 将消息发送到 IRC 主频道 这是我的代码
  • C++ microshell,输入命令并使用 fork()、dup()、pipe() 将其传送到进程。只是我没有得到我想要的结果

    include