After boot time and before you run a program, you can think of your computer as containing a zoo of processes that are all waiting for something to do. They're all waiting on events. An event can be you pressing a key or moving a mouse. Or, if your machine is hooked to a network, an event can be a data packet coming in over that network.
The kernel is one of these processes. It's a special one, because it controls when the other user processes can run, and it is normally the only process with direct access to the machine's hardware. In fact, user processes have to make requests to the kernel when they want to get keyboard input, write to your screen, read from or write to disk, or do just about anything other than crunching bits in memory. These requests are known as system calls.
Normally all I/O goes through the kernel so it can schedule the operations and prevent processes from stepping on each other. A few special user processes are allowed to slide around the kernel, usually by being given direct access to I/O ports. X servers are the most common example of this.
You will run programs in one of two ways: through your X server or through a shell. Often, you'll actually do both, because you'll start a terminal emulator that mimics an old-fashioned textual console, giving you a shell to run programs from. I'll describe what happens when you do that, then I'll return to what happens when you run a program through an X menu or desktop icon.
The shell is called the shell because it wraps around and hides the operating system kernel. It's an important feature of Unix that the shell and kernel are separate programs communicating through a small set of system calls. This makes it possible for there to be multiple shells, suiting different tastes in interfaces.
The normal shell gives you the ‘$’ prompt that you see after logging in (unless you've customized it to be something else). We won't talk about shell syntax and the easy things you can see on the screen here; instead we'll take a look behind the scenes at what's happening from the computer's point of view.
The shell is just a user process, and not a particularly special one. It waits on your keystrokes, listening (through the kernel) to the keyboard I/O port. As the kernel sees them, it echoes them to your virtual console or X terminal emulator. When the kernel sees an ‘Enter’ it passes your line of text to the shell. The shell tries to interpret those keystrokes as commands.
Let's say you type ‘ls’ and Enter to invoke the Unix
directory lister. The shell applies its built-in rules to figure out that
you want to run the executable command in the file
/bin/ls
. It makes a system call asking the kernel to
start /bin/ls as a new child process and give it
access to the screen and keyboard through the kernel. Then the shell goes
to sleep, waiting for ls to finish.
When /bin/ls is done, it tells the kernel it's finished by issuing an exit system call. The kernel then wakes up the shell and tells it that it can continue running. The shell issues another prompt and waits for another line of input.
Other things may be going on while your ‘ls’ is executing, however (we'll have to suppose that you're listing a very long directory). You might switch to another virtual console, log in there, and start a game of Quake, for example. Or, suppose you're hooked up to the Internet. Your machine might be sending or receiving mail while /bin/ls runs.
When you're running programs through the X server rather than a shell (that is, by choosing an application from a pull-down menu, or double-clicking a desktop icon), any of several programs associated with your X server can behave like a shell and launch the program. I'm going to gloss over the details here because they're both variable and unimportant. The key point is that the X server, unlike a normal shell, doesn't go to sleep while the client program is running — instead, it sits between you and the client, passing your mouse clicks and keypresses to it and fulfilling its requests to point pixels on your display.