I’ve got a question with how Linux process the environment varibales passed to execve():
Synoposis for execve():
int execve(const char *filename, char *const argv[], char *const envp[]);
Before calling execve(), we allocate the memory for holding envs/args from current process’s memory mapping. But after execve(), all the text/data/bss/stack of the calling process are overwriten by the new program, and all the memory mappings of the old process are not preserved (including the memory for passed envs/args).
For the new program, where to read the envs/args? Does the kernel make a copy of the passed envs/args and placed it onto the new memory mapping, or some other tricks?
Yes.
When a process calls
exec, the kernel copies the entireargvandenvparrays. Then, these are copied into the new process image — notably, when the program starts running, its stack looks like:The Glibc startup code in
_startmassages this into the proper form to invokemain.(For more details, the copy from the old process is done in
linux/fs/exec.c, the copy to the new process is done inlinux/fs/binfmt_elf.c, and program startup is done in architecture-specific code such asglibc/sysdeps/i386/start.S,glibc/sysdeps/x86_64/start.S, orglibc/ports/sysdeps/arm/start.S, which exist just to kick off into__libc_start_maininglibc/csu/libc-start.cwhich launchesmain.)