Background Processes

Parallel universes

When I start a program on the console, the console remains occupied by this program for the time being. If I want to do something else on the RevPi, I have to wait until the program is finished (or open a second console). If the program is designed as an endless process, I can wait until the never ending day. Often I also want to run several programs in parallel. Then the time has come when I have to deal with background processes.

A small program for demonstration

To demonstrate the functionality of background processes I wrote a little program RevPiBlink. As basis I use RevPiTestOutput from a previous post. I only changed the program to replace the for loop with an endless while loop.

while(true) {
    spiValue.i8uValue = spiValue.i8uValue^0x01;
    piC.SetBitValue(&spiValue);
    sleep(1);
}

Jobs

When I start the program in the command line, LED A1 flashes until I end the current appointment session or manually stall the program. The latter I can do with Ctrl-C. As long as the program is running, I cannot use the command line session.

Linux makes it really easy to use background processes. If I start a program and append & to the command, the program starts in the background and I can continue working on the console.

So I start my example program with

./revpiblink &

Now I get two numbers displayed, one of them in square brackets.  SSH console showing the output of the command "./revpiblink &"

The number in square brackets is the Job ID, the other is the Process ID. The process ID is valid globally for the entire system. The job ID is always only valid within the respective terminal session.

If I want to bring a process back into the foreground I can do this with fg %<Job ID>. So in my case

fg %1

SSH console showing the output of the command "fg %1"

Now the process can be terminated with e.g. Ctrl-C (we will not do that now). Much more interesting is that I can pause the process with Ctrl-Z. Now I have control over the command line again. I can now start the process in the background again with bg <Job ID>. If I cannot remember the job ID, the jobs command helps.

SSH console showing the output of the command "jobs": [1]+ Running ./revpiblink &

If I want to end a process in the background I can do this with kill %<job ID>.

SSH console showing the output of the command "kill %1": [1]+ Terminated ./revpiblink &

Declaration of independence

If I start a background process in a console, this process only lives as long as the terminal session exists. This can easily be shown with RevPiBlink. If you start the program with revpiblink & and end the SSH session, A1 stops flashing.

This can be prevented by uncoupling the process from the console session. This is done with disown <Job ID>. If I start ./revpiblink & again and run disown %1, the program is preserved even if the SSH session is terminated. I can also combine the commands to

./revpiblink & disown

If you now run jobs, the list remains empty. Sure, the current session has no more “own jobs”.

If we want to end the process now, we need the process ID, pid for short. With kill <pid> I can then send the process to the eternal hunting grounds. If I don’t know the process ID, I can simply find it out with the ps command. Without any further parameters, ps only lists me processes that were started from the current terminal session and that run under the current user. Processes that were started with sudo, for example, will not appear. With ps -A I get all processes displayed. In addition, ps allows countless parameters for filtering and sorting the processes and other options.  The easiest way to find my revpiblink is with

ps -A | grep revpiblink

SSH console showing the output of the command "ps -A | grep revpiblink": 2892 pts/0 00:00:00 revpiblink

The first number is the pid. I can now give that to kill.

By the way, kill without parameters tries to end processes “gently”. To do this, kill sends a signal to the process, telling it to terminate the process. So the process has the possibility to finish its work cleanly.  However, the process can also veto it. If a process should prove to be stubborn, it can be terminated hard with kill -9 <pid>.