17.1.1.  Processes and Environment

[ fromfile: environment.xml id: environment ]

Environment variables are <name, value> string pairs that can be stored quite easily in a map or a hash table. The variable name must be a legal identifier and, by convention, it usually does not contain lowercase letters. Every running process has an environment, consisting of a collection of environment variables. Most programming languages support a way of getting and setting these variables.

Some environment variables that we use are

  1. PATH, a list of directories to search for executables (also DLLs on windows).

  2. HOME, the location of your home directory.

  3. CPPLIBS, where the C++ Libraries from this book's source examples are installed.

  4. HOSTNAME (*nix) or COMPUTERNAME (win32), which usually gives you the name of your machine.

  5. USER (*nix) or USERNAME (Win32), which usually gives you the currently logged in user id.

Environment variables and their values are generally set by the parent process. Programs that depend on specific variables or values are generally not portable but depend somehow on their parent process. Variables provide a convenient cross-language mechanism for communicating information between processes.

Operating system shells enable the user to set environment variables for a process and its future children. Here are some examples.

Most programming languages support getting and setting environment variables, too, as shown here.

Changing the environment does not affect other processes that are already running. Environments are inherited from the parent process at process creation time.

Any program that you run is quite possibly a few levels deep in the process tree. This is because the typical desktop operating system environment consists of many processes running concurrently. In Figure 17.3 indentation levels indicate the parent-child relationships. Processes that are at the same indentation level are siblings (i.e., children of the same parent). Figure 17.3 shows the lifetimes, and the parent-child relationships between processes running on a typical KDE/Linux system while the environment example runs from konsole.

Figure 17.3.  KDE/Linux process hierarchy

KDE/Linux process hierarchy

Whenever program A runs program B, A is the parent process of B. B inherits (a copy of) A's environment when B is created. Changes to B's environment from inside B affects only B and B's future children, and are always invisible to A.

Example 17.5 demonstrates that the value given to setenv() is propagated to its child process.

Example 17.5. src/environment/setenv.cpp

#include <QCoreApplication>
#include <QTextStream>
#include <QProcess>
#include <QCoreApplication>
#include <QTextStream>
#include <QStringList>
#include <cstdlib>

class Fork : public QProcess {
    public:
    Fork(QStringList argv = QStringList() ) {
        execute("environment", argv); 1
    }
    ~Fork() {
        waitForFinished();
    }
};

QTextStream cout(stdout);
int main(int argc, char* argv[]) {

    QCoreApplication qca(argc, argv);
    QStringList al = qca.arguments();
    al.removeAt(0);
    bool fork=al.contains("-f");
    if(fork) {
       int i = al.indexOf("-f");
       al.removeAt(i);
    }

    QStringList extraVars;
    if (al.count()  > 0) {
        setenv("PENGUIN", al.first().toAscii(), true);
    }
    cout << " HOME=" << getenv("HOME") << endl;
    cout << " PWD=" << getenv("PWD") << endl;
    cout << " PENGUIN=" << getenv("PENGUIN") << endl;
    
    if (fork) {
        Fork f;   
    }
}

1

Runs this same app as a child.


When this program is run, the output looks like this:

src/environment> export PENGUIN=tux
src/environment> ./environment -f
HOME=/home/lazarus
PWD=src/environment
PENGUIN=tux
HOME=/home/lazarus
PWD=src/environment
PENGUIN=tux
src/environment> ./environment -f opus
HOME=/home/lazarus
PWD=src/environment
PENGUIN=opus
HOME=/home/lazarus
PWD=src/environment
PENGUIN=opus
src/environment> echo $PENGUIN
tux
src/environment>