使用execve系统调用的C语言网络编程

使用execve系统调用的C语言网络编程,c,network-programming,execve,C,Network Programming,Execve,我试图创建一个简单的客户机/服务器程序,该程序允许客户机使用TCP套接字连接到服务器,然后允许用户从客户机端向服务器端发出系统调用,并将应答返回给用户。例如: 客户问题:ls 服务器将在/usr/bin或w/e中找到ls,然后使用execve()执行它 我还将有类似lls或lmkdir等的东西,它将在客户端发出系统调用 问题是我的execve()似乎没有正确运行,因为没有实际调用“ls”或任何其他命令。我以前只使用本地端(没有服务器或任何东西)执行过类似的程序,execve()工作得很好。下面是

我试图创建一个简单的客户机/服务器程序,该程序允许客户机使用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根本没有执行。我认为这个系统实际上从来没有分叉过一个过程。由于这是一个客户机/服务器类型的程序,我是否需要做一些特殊的事情才能使它工作,或者它应该完全一样工作


非常感谢,
execve
不会分叉。它将当前图像替换为指定为其参数的图像,并从其开始处开始(即
main()
)。它永远不会回到你原来的计划


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

确切地说,
execve
不会分叉。它将当前图像替换为指定为其参数的图像,并从其开始处开始(即
main()
)。它永远不会回到你原来的计划


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

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

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

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

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 */
          }
}

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

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

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

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 */
          }
}

代码中有几个问题:

  • fork()
    为父对象返回pid,为子对象返回零。因此父级运行if的真正分支。child负责else分支。交换这些评论
  • 标准输出是行缓冲的。将新行
    (\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);
   }

或者您可以使用
系统(3)

代码中有几个问题:

  • fork()
    为父对象返回pid,为子对象返回零。因此父级运行if的真正分支。child负责else分支。交换这些评论
  • 标准输出是行缓冲的。将新行
    (\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);
   }

或者您可以使用
系统(3)

向我们显示
execPath
arglist
。这可能不是您的问题,但您需要测试
fork()
是否返回
-1
,指示错误(如系统上的进程太多)。子进程不能等待父进程。父级可以等待子级。父级运行第一个banch。child负责else分支。您应该修复这些代码注释。向我们显示
execPath
arglist
。这可能不是您的问题,但您需要测试
fork()
是否返回
-1
,指示错误(如系统上的太多进程)。子进程不能等待父进程。父级可以等待子级。父级运行第一个banch。child负责else分支。您应该修复这些代码注释。