2

在 execve 函数中,参数由指针数组传递。如果这些指针指向前一个堆栈中的内存,那么这些内存是否仍然可以在新的进程映像中访问。

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

int main(void)
{
    char filename[20] = "a.out";
    char str[20] = "hello\n";
    char *argv[3];

    argv[0] = filename;
    argv[1] = str;
    argv[2] = NULL;
    execve("/hel/a.out", argv, NULL);
    return 0;
}

/*   /hel/a.out code   */
#include <stdio.h>

int main(int argc, char *argv[], char *envp[])
{
    printf("%s\n", argv[1]);  /** Here, should the memory pointed by argv[1]
                               *  be freed after execve  has been called?
                               */ 
    return 0;
}
4

1 回答 1

5

仔细阅读execve(2)的文档(以及Advanced Linux Programming以获得更广阔的视野)。阅读有关虚拟内存分页MMU进程的信息。

execve 系统调用正在您的进程安装一个新的虚拟地址空间(因此成功执行的程序的旧虚拟地址空间execve 消失了,被新的虚拟地址空间覆盖),因此您不会与前一个共享任何数据(并且asuccessexecve不会返回,因为新程序已启动)。您的新程序稍后将能够更改虚拟地址空间,例如使用mmap(2) ...

新虚拟地址空间中字符串的地址与;argv的参数地址无关 execve字符串内容相同。旧的虚拟地址空间和新的虚拟地址空间之间没有数据共享,但新程序(和程序环境)的参数被复制。另请阅读关于ASLR

的参数execve是在新虚拟地址空间的新调用堆栈上复制的字符串_start(其副本被推送),用于其起始函数( 在crt0中调用main)。当然,您不应该free有任何argv[i-]那将是未定义的行为

因此int a; argv[1]=(char*)&a;... execvewith argv, 是未定义的行为,因为您不能保证地址处的内存区域a是正确的以空值结尾的字符串。阅读有关字节序ABI的信息。

所以execve 想要一个NULL终止argv的正确字符串数组(不是任意指针)和另一个NULL 终止env的字符串数组,并且每个字符串都应该以零字节终止。从旧地址空间通过&ARG_MAX复制到新地址空间的总内存空间有一个相当小的限制(通常为 128 KB) 。argvenv

您可能使用共享内存(请参阅shm_overview(7))在各个进程之间共享内存(并且您将与信号量同步,请参阅sem_overview(7) ...);但您通常更喜欢其他进程间通信技术(例如pipe(7) -s、fifo(7) -s、socket(7) -s 等...)。

顺便说一句,还可以使用strace(1)来了解您的程序涉及哪些系统调用,并使用proc(5),特别是通过运行cat /proc/$$/maps和了解更多关于虚拟地址空间的信息。cat /proc/$pidofyourprogram/maps

你甚至可以把你的两个main函数都放进去(execve在第一个之前,return 0;在第二个之前),比如

 char cmd[64];
 snprintf(cmd, sizeof(cmd), "/bin/cat /proc/%d/maps", (int)getpid());
 printf("before running %s\n", cmd);
 fflush(NULL);
 int err = system(cmd);
 if (err) fprintf(stderr, "system failed err=%d\n", err);
 else printf("system %s done\n", cmd);

这将向您显示虚拟地址空间的视图。当然,更严肃的程序应该fopen是一个/proc/1234/maps文件并循环fgets读取每一行,直到EOF那时fclose

请耐心等待,阅读此处的所有参考资料,并花时间了解有关 POSIX 编程的更多信息。学习一些自由软件源代码(例如在http://github.com/你可以选择一些有趣的项目......)并为它们做出贡献应该是值得的。

于 2015-12-20T08:12:07.187 回答