UNIX:在fork之后在父进程上调用exec

时间:2010-09-25 05:12:14

标签: unix exec fork

我正在写我的语法,用LEX,一些代码来fork()我的进程并运行一个孩子。孩子实际上从父母那里获得了一些输入,然后返回一个结果。

我需要在加载父节点的同一个二进制文件上调用exec,但是我遇到了问题。我知道exec并不意味着完全意义,但我这样做是因为我在LEX中有一些以前的语法,我只是想摆脱它,所以重新加载过程更容易。

我在fork()之后的子代中有以下代码:

char *path = strdup(getenv("PWD"));
size_t size = strlen(path) + strlen("/shell") + 1;
path = (char *) realloc(path, sizeof(char) * size);
path = strcat(path, "/shell");

// call exec
execl(path, NULL);

这段代码的问题在于,如果从同一目录启动进程,它会起作用,但如果我尝试从这个目录中的文件夹加载,比如说,.. / shell,那么路径实际上是错误的,它将包含此目录。

我想知道我如何能够获得正确的流程路径,如果有办法也可以获得流程的实际名称吗?我查看了环境变量,但没有找到任何有用的东西。

非常感谢,

Jary

1 个答案:

答案 0 :(得分:0)

根据我的理解,目标是让子进程重新执行代表父进程的相同程序。

如果没有使用来自/proc文件系统的数据的技巧,我认为没有一种完全可靠的方法来实现它。

通常,您依靠argv[0]足以查找该计划的值,并使用execvp()通过$PATH查找该计划。

尝试2 - 可能不那么混乱

  

如果你不介意,我会重新解释[问题]:现在,execl()确实执行了二进制文件,但只有当我直接从其文件夹中加载父文件时。如果我进入子文件夹,让我们称之为fd,那么路径将是“correctPath / fd / shell”而不是“correctPath / shell”。问题似乎是调用getenv(“PWD”)找到路径并不总是正确的。

     

所以目标是加载相同的进程或二进制文件;我们假设二进制文件称为“shell”。问题是找到路径。我展示的代码适用于shell从它本身的文件夹加载(父),否则它不起作用。我怀疑打电话给getenv(“PWD”)是对的,但我不确定还有什么要打电话。

您是正确的,使用getenv("PWD")getcwd()通常不正确。

char *arg0 = 0;

int main(int argc, char **argv)
{
    ...declarations...

    arg0 = argv[0];

    ...actions...
}

因此,主程序将其argv[0]的值保存在全局变量arg0中,以使其可用于进程的其他部分 - 特别是要转到的代码(re )运行命令。

如果使用“./shell”在与可执行文件所在的目录相同的目录中调用该程序,则argv[0](以及arg0)将包含该路径名。如果使用依赖$ PATH定位程序的“shell”执行它,那么argv[0]将只包含“shell”或绝对路径名“shell”(不常见)。

如果从fd子目录调用该程序,它可能被调用为“../shell”,或者可能被调用为“/ absolute / path / to / shell”或者可能被调用作为“shell”依靠$ PATH来查找可执行文件。同样,在任何这些情况下,arg0中的值是最初调用程序的名称,或者等同于它。

这次失败的唯一一次是,如果有人故意开始混淆可执行文件,那么(幸运的是)很少会这样。

因此,在子代码中,您可以使用:

char *args[] = { arg0, 0 };
execvp(arg0, args);

重新执行最初执行的命令(除了最初传递的任何辅助参数)。

尝试1 - 有点混乱

假设argv[0]的值可以通过变量char *arg0获得,那么所有必要的是:

char *args[] = { arg0, 0 };
execvp(arg0, args);

如果您必须使用execl(),则需要:

execl(arg0, arg0, (char *)0);

演员是必要的; execl()是一个变量参数列表函数,如果你写0,它将被转换为int,它将在64位系统上失败,其中int是32位和一个指针是64位。但是,如果arg0不表示可执行文件的路径(相对或绝对),则会失败。然后,您必须决定execl()返回时该怎么做 - 您可以通过$PATH放弃或搜索该计划,但在这种情况下,为什么不在execvp()中使用{{1}}第一个为自己省去痛苦的地方。