【问题标题】:Network Programming in C with execve system calls带有 execve 系统调用的 C 网络编程
【发布时间】:2013-02-25 18:56:42
【问题描述】:

我正在尝试创建一个简单的客户端/服务器程序,它允许客户端使用 TCP 套接字连接到服务器,然后允许用户从客户端向服务器端发出系统调用并将回复返回给用户。例如:

客户端问题:ls

服务器会在 /usr/bin 或 w/e 中找到 ls,然后使用 execve() 执行它

我还会有一些类似 lls 或 lmkdir 之类的东西......它将在客户端发出系统调用。

问题是我的 execve() 似乎没有正确运行,因为实际上没有调用“ls”或任何其他命令。我之前只使用本地端(没有服务器或任何东西)完成了同样类型的程序,并且 execve() 工作正常。这是一些代码:

       pid = fork();

       if(pid){ // Child
        printf("child wait");
          pid = wait(&status);
          printf("Child dead\n");
       }else{ // Parent

          if(execPath){            

          execve(execPath, arglist, env);
          printf("Command Complete\n");

        }

       }

由于某种原因,PID 语句的子部分中的 printfs 根本没有执行。我不认为系统实际上会分叉一个进程。由于它是客户端/服务器类型的程序,我需要做一些特别的事情来完成这项工作吗?还是应该完全一样地工作?

谢谢

【问题讨论】:

  • 告诉我们execPatharglist
  • 这不太可能是你的问题,但你需要测试fork()是否返回-1,表示错误(比如你的系统上的进程太多)。
  • 孩子不能等待父母。父母可以等待孩子。
  • 父级运行第一组。孩子运行其他分支。您应该修复代码的这些 cmets。

标签: c network-programming execve


【解决方案1】:

没错,execve 不会分叉。它将当前图像替换为指定为其参数的图像,并从其开头(即main())开始。它永远不会返回到您的原始程序。

您可能希望在您的用例中使用system()

【讨论】:

    【解决方案2】:

    代码有几个问题:

    • fork() 为父级返回 pid,为子级返回零。所以 parent 运行 if 的真正分支。孩子运行 else 分支。交换这些 cmets。
    • 标准输出是行缓冲的。将新行(\n) 添加到等待之前的printf。否则在等待完成之前您看不到打印输出,第二个printf 正在通话中。
    • 确保孩子在错误情况下也会退出,否则孩子将运行父母的代码,而父母仍在等待孩子的退出。
    • execve 如果成功则不会返回。如果失败,它将返回。

    所以,固定代码可能是这样的:

       pid = fork();
    
       if(pid){  // Parent
          printf("child wait\n");
          pid = waitpid(pid, &status, 0);
          printf("Child dead\n");
       }else{ // Child
          if(execPath){            
              execve(execPath, arglist, env);
              printf("execve failed!\n");
          }
          _exit(1);
       }
    

    或者你可以使用system(3)

    【讨论】:

      【解决方案3】:

      由于子进程没有产生任何自己的子进程,wait() 调用不太可能在没有其他外部事件(如中断调用的信号)的情况下返回。您应该让父进程等待子进程。

      请注意,fork() 可能会失败,您应该对此负责。另请注意,如果execve 成功,它将不会返回。因此,如果要打印任何内容,它后面的 print 语句应该指示失败。

      使用system() 可能不会为您节省分叉,因为您可能希望将命令的输出定向到与已连接客户端关联的套接字。但是,您的代码缺少允许输出流向客户端的步骤。

      switch ((pid = fork())) {
      case -1:  /* todo: handle error */
                break;
      case 0:   /* child */
                dup2(socket, 0); /* todo: check return value */
                dup2(socket, 1); /* todo: check return value */
                dup2(socket, 2); /* todo: check return value */
                close(socket);   /* todo: check return value */
                execve(...);
                /* todo: handle failure */
                exit(EXIT_FAILURE);
      default:  /* parent */
                if (pid != waitpid(pid, 0, 0)) {
                    /* todo: handle error */
                }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-23
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-30
        • 2015-04-10
        • 2019-09-25
        相关资源
        最近更新 更多