在execve之后,是否在上一个进程中添加了addr的内存?

时间:2015-12-20 07:30:30

标签: linux execve

在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;
}

1 个答案:

答案 0 :(得分:2)

仔细阅读 execve(2)(以及Advanced Linux Programming的文档以获取更广泛的视图)。阅读virtual memorypagingMMU s,processes

execve system call正在virtual address space中安装全新的process (因此,该程序的旧虚拟地址空间正在{ {1}}成功消失,被新的一个覆盖),因此您不会与之前的数据共享任何数据(并且成功的execve不会返回,因为新程序已启动)。您的新程序以后可以更改虚拟地址空间,例如与mmap(2) ...

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

execve的参数是字符串在新虚拟地址空间的新新调用堆栈上复制(推送其副本)以获取其启动函数(execvecrt0中调用_start)。当然,您不应main任何freeargv[ - undefined behavior

因此,] ... int a; argv[1]=(char*)&a;execve是未定义的行为,因为您无法保证argv地址处的内存区域是正确的以null结尾的字符串。阅读endianness&amp; ABI

因此a需要execve终止正确字符串的数组NULL(非任意指针),而另一个argv终止{{1}字符串数组,每个字符串应以零字节结束。从旧地址空间复制到新地址空间的总内存空间有一个相当小的限制NULL(通常为128K字节)通过env&amp; ARG_MAX

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

顺便说一下,还可以使用strace(1)来了解您的计划涉及哪些系统调用,并使用proc(5),特别是通过运行argvenv {{ 1}} 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

请耐心等待,阅读此处的所有参考资料,并time了解有关POSIX编程的更多信息。研究一些free software源代码(例如在http://github.com/上,您可以选择一些有趣的项目......)并为它们做出贡献应该是值得的。