使用execve系统调用的C语言网络编程
我试图创建一个简单的客户机/服务器程序,该程序允许客户机使用TCP套接字连接到服务器,然后允许用户从客户机端向服务器端发出系统调用,并将应答返回给用户。例如: 客户问题:ls 服务器将在/usr/bin或w/e中找到ls,然后使用execve()执行它 我还将有类似lls或lmkdir等的东西,它将在客户端发出系统调用 问题是我的execve()似乎没有正确运行,因为没有实际调用“ls”或任何其他命令。我以前只使用本地端(没有服务器或任何东西)执行过类似的程序,execve()工作得很好。下面是一些代码:使用execve系统调用的C语言网络编程,c,network-programming,execve,C,Network Programming,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 */
}
}
代码中有几个问题:
为父对象返回pid,为子对象返回零。因此父级运行if的真正分支。child负责else分支。交换这些评论fork()
- 标准输出是行缓冲的。将新行
添加到等待之前的(\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)
代码中有几个问题:
为父对象返回pid,为子对象返回零。因此父级运行if的真正分支。child负责else分支。交换这些评论fork()
- 标准输出是行缓冲的。将新行
添加到等待之前的(\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分支。您应该修复这些代码注释。