2015-12-20 2 views
2

В функции execve аргументы передаются массивом указателей. Если эти указатели помещают в память в предыдущем стеке, можно ли получить доступ к этой памяти в новом образе процесса.после execve, являются ли память в предыдущем процессе addr освобождены?

#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; 
} 
+0

Вы действительно должны использовать 'strace' –

+0

Yeah.I положил ваш код трассировки в основном, а результат немного сложнее. Я изучаю Расширенное программирование в среде UNIX и хочу закончить его, чтобы получить глобальную концепцию. После этого, может быть, пришло время изучать каждую деталь. – hel

+0

Возможно, я понял. Если a = 13; (старший байт 00, младший байт 0d) argv [1] = (char *) (&a); Во втором главном корректно выводится формат: printf («% s», argv [1]); // print '\ n' Скопируйте только аргументы и строки окружения в новые места в execve. Я не знаю, прав я или нет. Спасибо за все ответы, и я буду изучать его глубоко после этого. – hel

ответ

1

Читать тщательно документация execve(2) (а также Advanced Linux Programming получить более широкое представление). Читайте о virtual memory, paging, MMU s, processes.

execvesystem call устанавливает в своих process (так старое виртуальном адресном пространстве программы делает execve успешно исчезает, будучи переписано новым), так что вы не разделяете каких-либо данные свежего virtual address space с предыдущий (и успешный execve не возвращается, так как запускается новая программа). Ваша новая программа сможет впоследствии изменить виртуальное адресное пространство, например. с mmap(2) ...

Адрес argv строк в новом виртуальном адресном пространстве не зависит от адреса аргументов к execve; содержимое строки одинаково. Нет данныеобщий между старым виртуальным адресным пространством и новым, но аргументы новой программе (и программной среде): скопировано. Читайте также о ASLR

Аргументы execve является строками скопированных (с их копией толкает) на новом стеке свежего вызова нового виртуального адресного пространства для своей начальной функции (_start в crt0, которая вызывает main). Конечно, вы не должны free любой argv[ i ] - это будет undefined behavior.

Следовательно int a; argv[1]=(char*)&a; ... execve с argv, это неопределенное поведение, потому что вы не можете гарантировать, что зона памяти по адресу a является собственным завершающим нулем строку. Читайте перевод информации о endianness & ABI.

execve Так хочет NULL -завершённого массива argv правильных строк (не произвольные указатели), а другой NULL завершается env массива строк, каждая строка должна заканчиваться нулевым байтом. Существует довольно небольшой предел ARG_MAX (обычно 128 Кбайт) на общем пространстве памяти, скопированном из старого адресного пространства в новое через argv & env.

Вы можете возможно использование разделяемой памяти (см shm_overview(7)) для совместного использования памяти между различными процессами (и вы будете синхронизировать с семафорами, см sem_overview(7) ...); но вы часто предпочитаете другие методы inter-process communication (например, pipe(7) -s, fifo(7) -s, socket(7) -s и т. д.).

BTV, используют также 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 a /proc/1234/maps file и loop on fgets читать каждую строку до EOF, затем fclose.

Будьте терпеливы, прочтите все ссылки здесь и возьмите time, чтобы узнать больше о программировании POSIX. Изучая исходный код free software (например, на http://github.com/, вы можете выбрать несколько интересных проектов ...), и вклад в них должен быть полезен.

+0

Да, спасибо. Я нахожу a. (2) снова и ничего не находите в этом вопросе. – hel

+0

Переменные находятся внутри виртуального адресного пространства. А поскольку весь VAS заменен, ваш вопрос не имеет смысла. Вам действительно нужно потратить несколько часов на чтение ссылок, которые я дал в своем ответе. –

+0

Различные VAS после независимого адреса, но то же содержимое о строках. Я тестирую такой код 'int a = 3; argv [1] = (char *) & a; 'и в исходном файле a.out:' printf ("% d \ n", * ((int *) argv [1])); Вывод - случайное число. – hel

Смежные вопросы