我正在尝试创建一个简单的客户端/服务器程序,允许客户端使用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根本没有执行。我不认为系统实际上是在分配过程。有什么特别的东西我必须做才能使这项工作,因为它是一个客户端/服务器类型的程序或它应该工作完全相同?
由于
答案 0 :(得分:2)
确切地说,execve
没有分叉。 用指定的参数取代当前图像并从其开始(即main()
)开始。它永远不会返回到您的原始程序。
您可能希望在用例中使用system()
。
答案 1 :(得分:1)
由于子进程没有生成自己的子进程,因此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 */
}
}
答案 2 :(得分:1)
代码中有几个问题:
fork()
返回父级的pid,子级返回0。所以父运行if的真正分支。而孩子则运行其他分支。交换这些评论。(\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)
。