Read carefully the documentation of execve(2) (and also Advanced Linux Programming to get a broader view). Read about virtual memory, paging, MMUs, processes.
The execve
system call is installing a fresh new virtual address space in your process (so the old virtual address space of the program doing execve
successfully disappears, being overwritten by the new one), so you don't share any data with the previous one (and a successful execve
does not return, since the new program is started). Your new program would be able to later change the virtual address space, e.g. with mmap(2)...
The address of argv
strings in the new virtual address space are independent of the address of arguments to execve
; the string contents are the same. No data is shared between the old virtual address space and the new one, but arguments to the new program (and program environment) are copied. Read also about ASLR
The arguments of execve
are strings copied (with their copy being pushed) on the new fresh call stack of the new virtual address space for its starting function (_start
in crt0 which calls main
). Of course you should not free
any argv[
i]
- that would be undefined behavior.
Hence int a; argv[1]=(char*)&a;
... execve
with argv
, is undefined behavior, because you cannot guarantee that the memory zone at the address of a
is a proper null-terminated string. Read about endianness & ABI.
So execve
wants a NULL
terminated array argv
of proper strings (not arbitrary pointers), and another NULL
terminated env
array of strings, and each string should be terminated by a zero byte. There is a rather small limit ARG_MAX
(typically 128Kbytes) on the total memory space copied from the old address space to the new one thru argv
& env
.
You might perhaps use shared memory (see shm_overview(7)) to share memory between various processes (and you'll synchronize with semaphores, see sem_overview(7)...); but you often would prefer other inter-process communication techniques (e.g. pipe(7)-s, fifo(7)-s, socket(7)-s, etc...).
BTW, use also strace(1) to understand which system calls are involved by your program, and use proc(5), notably by running cat /proc/$$/maps
and cat /proc/
$pidofyourprogram
/maps
to understand more about virtual address space.
You could even put in both of your main
functions (before execve
in the first one, before return 0;
the second one) something like
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);
This will show you a view of the virtual address space. Of course, a more serious program should fopen
a /proc/1234/maps
file and loop on fgets
to read every line until EOF
then fclose
.
Be patient, read all the references here, and take time to learn more about POSIX programming. Studying some free software source code (e.g. on http://github.com/ you can chose some interesting projects...) and contributing to them should be worthwhile.
strace
– Basile Starynkevitch