Читать тщательно документация execve(2) (а также Advanced Linux Programming получить более широкое представление). Читайте о virtual memory, paging, MMU s, processes.
execve
system 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/, вы можете выбрать несколько интересных проектов ...), и вклад в них должен быть полезен.
Вы действительно должны использовать 'strace' –
Yeah.I положил ваш код трассировки в основном, а результат немного сложнее. Я изучаю Расширенное программирование в среде UNIX и хочу закончить его, чтобы получить глобальную концепцию. После этого, может быть, пришло время изучать каждую деталь. – hel
Возможно, я понял. Если a = 13; (старший байт 00, младший байт 0d) argv [1] = (char *) (&a); Во втором главном корректно выводится формат: printf («% s», argv [1]); // print '\ n' Скопируйте только аргументы и строки окружения в новые места в execve. Я не знаю, прав я или нет. Спасибо за все ответы, и я буду изучать его глубоко после этого. – hel