recap on linux basic -- process tree

The processes in UNIX® are - unlike in other systems you may have seen - organized in a tree. Every process has a parent process that started it or is responsible for it. Also, every process has an own context memory (I don't mean the memory where the process stores its data, I mean memory where data is stored that doesn't directly belong to the process, but is needed to run the process): The environment.

 

Attention: A variable that is set, like with MYVAR=Hello, is not automatically part of the environment. You need to put it into the environment with the export utility:

 

Let's take a short look what happens when you "execute a program" from the Bash prompt, a program like "ls":

 

$ ls

Bash will now perform two steps:

  • It will make a copy of itself
  • The copy will replace itself with the "ls" program

The copy of Bash will inherit the environment from the "main Bash" process: All environment variables will also be copied to the new process. This step is called forking.

For a short moment, you have a process tree that might look like this...

xterm ----- bash ----- bash(copy)

...and after the "second Bash" (the copy) replaced itself by the ls-program (it execs it), it might look like

xterm ----- bash ----- ls

If everything was okay, the two steps resulted in one program being ran. The copy of the environment from the first step (forking) results in the environment for the final running program (ls in this case).

What is so important about it? Well, in our example, whatever the program ls will do inside its own environment, it can't have any effect to the environment of its parent process (bash here). The environment was copied when ls was executed. That's a one-way! Nothing will "copy it back" when ls terminates!

 

| Pipe create new process 

 

Well, imagine some Bash-code that reads data from a pipe. Let's take the internal command read, which reads data from stdin and puts it into a variable. We run it in a loop here - we count input lines...:

 

counter=0cat /etc/passwd | while read LINE; do ((counter++)); doneecho Lines: $counter

What? It's 0? Yes! The number of lines might not be 0, but the variable $counter still is 0. Why?Remember the diagram from above? I'll rewrite it a bit:

                   +-- cat /etc/passwdxterm ----- bash --|                   +-- bash (while read LINE; do ((counter++)); done)

See the relation? The forked Bash will count the lines like a charm. It will also set the variable counter like you wanted it. But if everything ends, this extra process will be terminated - your variable is gone - R.I.P. You see a 0 because in the main shell it always was 0 and never something else!

Aha! And now, how to count those lines?Easy: Avoid the subshell. How you do it in detail doesn't matter, the important thing is that the shell that sets the counter must be the "main shell". For example do it like this:

 

counter=0while read LINE; do ((counter++)); done </etc/passwd
echo Lines: $counter


Actions that create a subshell

Executing commands

Pipes

Explicit subshell

If you group commands by enclosing them in parentheses, these commands are run inside a subshell:
(echo PASSWD follows; cat /etc/passwd; echo GROUP follows; cat /etc/group) >output.txt

Command substitution

With command substitution you re-use the output of another command as text in your commandline, for example to set a variable. This other command is run in a subshell:

NUMBER_OF_USERS=$(cat /etc/passwd | wc -l)
Note that, in this example, you create a second subshell by using a pipe in the command substitution (just as sidenote):
                                            +-- cat /etc/passwdxterm ----- bash ----- bash (cmd. subst.) --|                                            +-- wc -l


echo $$ return current process id; ps -p $$ show the current shell info. Remember $ returns the PID (process identification number)
of the current process, and the current process is your shell
posted @ 2010-10-08 17:40  Simon.Yang  阅读(219)  评论(0编辑  收藏  举报