Question about global environment variables & fork() exec()

Hello... And thanks in advance for any help anyone can offer me on my question! I've been doing a lot of reading to try and find my answer... But I haven't had any luck

What I'm trying to understand is where a child process inherits global environment variables from? I understand the exec() system call overwrites environment variable created by the fork()... But how does exec() cause global environment variables to be included with a newly created child process if all the environment variables are overwritten? My best guess is that global environment variables are somehow excluded from being overwritten... But I can't confirm this

Also... when does the fork() assign a PID to a child process? Before or after it copies itself into a new region of memory?

Thanks to everyone for any assistance!

Nothing prevents the child from mangling its own environment variables before exec(), which is how execle, execvpe work IIRC. Otherwise, the child receives copies.

Whether it's before or after is kind of a moot point. It's done by copy-on-write, which copies on write.

I am not sure what you exactly want to know, so maybe i will tell you something you already know. Bear with me, i hope to make things clearer and if this is not the case please ask again:

Part of what a process gets from the OS when it is created is a "process environment". This is a place in memory with a collection of strings that look all like name=value , i.e. PATH=/usr/bin:/usr/local/bin . You can inspect the environment of a shell (ksh or bash) process with the command set but all other processes have a similar environment, even if you can't inspect it that easily.

When a process is created it is created from some "father" process, which also have some environment. All processes in a system are organised in a tree-like hierarchy which goes back to init - the process to start all other processes. All these processes ( init included) have such an environment, although the environment of init is legendarily poor. This (just as an aside) is why cron jobs often fail: cron is started from init and since cron itself doesn't need any environment it can work with what it inherits from init . This might not be the case at all for the processes started by cron , aka cron-jobs, though.

Now, every process can add to the environment it inherits - or, to be precise: it can add to its own copy of inherited environment and change/delete existing or even define new name=value pairs. This only affects the processes own environment. Now there is a keyword in the shell, which reflects a certain property of these name=value -pairs (or "environment variables"): export . export will cause an environent variable to be passed to children. So every process can inherit from its father, change its envirment and then pass this changed environment to its own children.

This in fact is done i.e. when you login: the login process have a certain environment already set, then will ask you for name and password, then start your login shell as a child process (so it iherits from login) and run ~/.profile . The shell itself will run (in its own environment) ~/.bashrc or ~/.kshrc or some similar file and further change its environment. If you now start a program in there this process will inherit whatever you have export ed from this environment.

Notice that if you do not export a variable it will not be included in the environment a child process inherits. Also notice that a variable is either exported or not. Re-exporting it every time you change it like it is often seen:

export var=foo
export var=foo:bar
export var=foo:bar:baz

will not hurt but is not necessary. Once the variable is exported it remains so because it is a property of the variable itself, not just its current value.

So, to answer your initial question: whenever a new process is created a process environment is created as a part of this creation. This process environment is filled with a copy of what is exported in the environment of the father process before the process itself is started.

I hope this helps.

bakunin