如何调用execvp系统调用工作?

时间:2018-04-19 20:42:45

标签: c exec system-calls

我正在研究另一个StackOverflow question的内容,我认为现在是了解unix系统调用知识的好时机。

在尝试使用execvp没有叉子)的时候,我遇到了让我困惑的事情

我写了4个测试程序

计划1

#include <stdio.h>

int main() {
        //printf("Doge\n");
        execvp("ls");
        printf("Foo\n");
        return 0;
}

该程序按预期工作,目录的内容被打印,Foo打印语句不是

计划2

但是,当我取消注释第一个print语句并将程序设为此

#include <stdio.h>

int main() {
        printf("Doge\n");
        execvp("ls");
        printf("Foo\n");
        return 0;
}

execvp返回-1,并发出两个打印语句。为什么呢?

计划3

我依稀记得在试用大学的unix系统调用时必须使用unistd.h

所以我把它包括在内,但不是execvp有一个不同的签名,它需要更多的args而不仅仅是程序的名称。所以我做了这个

#include <stdio.h>
#include <unistd.h>

int main() {
        printf("Doge\n");
        char *const parmList[] = {"ls", NULL};
        execvp("ls", parmList);
        printf("Foo\n");
        return 0;
}

这很有效。这让我很困惑。为什么exec在第一个程序中工作? 我还使用This作为系统调用的引用。

最后我写了

计划4

#include <stdio.h>
//#include <unistd.h>

int main() {
        printf("Doge\n");
        char *const parmList[] = {"ls", NULL};
        execvp("ls", parmList);
        printf("Foo\n");
        return 0;
}

哪个也按预期工作。

有人能解释一下发生了什么吗?

1 个答案:

答案 0 :(得分:3)

使用此代码段

#include <stdio.h>

int main() {
        execvp("ls");
        printf("Foo\n");
        return 0;
}

您正在调用未定义的行为。您没有提供execvp的原型,它需要一个参数列表(以空值终止)作为第二个参数。

在没有任何警告选项的情况下使用gcc以隐式声明的方式静默使用execvp,并且不会检查参数。它只是调用函数。然后该函数查找第二个参数并遇到...调用堆栈剩余的内容(或寄存器,具体取决于调用约定),这就是为什么先前的printf调用可以改变行为。< / p>

使用gcc -Wall会发出以下警告:

test.c:5:9: warning: implicit declaration of function 'execvp' [-Wimplicit-function-declaration]
         execvp("ls");

包括正确的包含(#include <unistd.h>)会导致:

test.c:6:9: error: too few arguments to function 'execvp'
         execvp("ls");
         ^~~~~~

这就是为什么你有奇怪的行为。别再看了。使用带有2个参数的execvp,句点。在您的情况下&#34;计划3&#34;是可行的方法,并始终将警告级别设置为最大值(gccclang-Wall -Wextra -pedantic -Werror