DEV Community

Satoru Takeuchi
Satoru Takeuchi

Posted on • Updated on

How Linux Works: Chapter2 Process Management (Part3)

Job control in Shell

In this section, we will explain the concepts of sessions and process groups, which exist for the implementation of shell's job control.

For those unfamiliar with jobs, a job is a mechanism that shells like bash use to control processes running in the background. For example, you might use it as follows:

$ sleep infinity &
[1] 6176 # [1] is the job number
$ sleep infinity &
[2] 6200 # [2] is the job number
$ jobs # List the jobs
[1]-  Running                 sleep infinity &
[2]+  Running                 sleep infinity &
$ fg 1 # Make job 1 the foreground job
sleep infinity
^Z # Press Ctrl+z and control returns to bash
[1]+  Stopped                 sleep infinity
Enter fullscreen mode Exit fullscreen mode


A session corresponds to a login session when a user logs into the system through a terminal emulator like gterm or ssh. All sessions have a terminal attached for controlling the session. When you want to operate processes within the session, you instruct them through the terminal to processes, including the shell, and receive the output from these processes. Normally, a virtual terminal named pty/<n> is assigned to each session.

Let's consider a situation where three sessions exist:

  • Alice's session: The login shell is bash. Developing a Go program with vim on it, and currently building some program with go build.
  • Bob's session 1: The login shell is zsh. Using ps aux on it to list all processes in the system, and receiving the results with less.
  • Bob's session 2: The login shell is zsh. Running a custom calculation program called calc on it."

This situation can be illustrated as follows:

Example of sessions

Each session is assigned a unique value, called a "session ID" (or "SID"). Each session has a process called a session leader, which is typically a shell like bash. The PID of the session leader equals the ID of the session. Information about the session can be obtained by ps ajx. In the author's environment, it is as follows:

$ ps ajx
  19261   19262   19262   19262 pts/0      19647 Ss    1000   0:00 -bash
  19262   19647   19647   19262 pts/0      19647 R+    1000   0:00 ps ajx
Enter fullscreen mode Exit fullscreen mode

In this case, we can see that there is a session (SID=19262) with bash(19262) as the session leader, and ps ajx (PID=19647) belongs to this session. Commands launched from bash(19262) normally belong to this session. The TTY field in ps ajx, and in ps aux used in previous sections, is the name of the terminal. In this session, a virtual terminal pts/0 is assigned.

When the terminal associated with the session hangs up, a SIGHUP is sent to the session leader. This happens when the terminal emulator's window is closed. bash will terminate its managed jobs and then terminate itself in this case. For cases where it would be a problem if bash terminated while a long-running process was executing, the following measures can be used:

  • The nohup command: Launches a process with the setting to ignore SIGHUP. Even if the session terminates and a SIGHUP is sent afterward, the process does not terminate.
  • The disown built-in command of bash: Removes a running job from bash's management. As a result, even if bash terminates, a SIGHUP will not be sent to the job.

Process Groups

Process groups are used to control multiple processes collectively. Within a session, there exist several process groups. Essentially, you can think of the jobs created by the shell as corresponding to process groups1.

To be more precise, the shell itself also has its own process group, but for the sake of simplicity, we will omit this from the current discussion.

Let's illustrate process groups with an example. Suppose a session is set up as follows:

  • The login shell is bash.
  • From the above bash, go build <source name> & is executed.
  • From the above bash, ps aux | less is executed.

In this case, bash creates two process groups (jobs) corresponding to go build <source name> & and ps aux | less.

With process groups, signals can be thrown to all processes belonging to a certain process group. The shell uses this feature for job control. If you specify a negative value for the process ID argument of the kill command, you can send a signal to the process group. For example, if you want to send a signal to a process group with a PGID of 100, you can do so with kill -100.

Process groups within a session can be divided into two types:

  • Foreground process group: Corresponds to the foreground job in the shell. Only one exists in a session and has direct access to the session's terminal.
  • Background process group: Corresponds to the background job in the shell. When a background process tries to operate the terminal, it temporarily suspends execution as when it receives a SIGSTOP, and this state continues until it becomes a foreground process group (or a foreground job) by commands such as the fg built-in command.

The latter, the foreground process group (foreground job), is the one that can access the terminal directly. This is illustrated as follows.

Relationship between session, process group, and job

Each process group is assigned a unique ID known as a PGID. This value can be confirmed by the PGID field in ps ajx. In my environment, it looks like this:

$ ps ajx | less
  19261   19262   19262   19262 pts/0      19653 Ss    1000   0:00 -bash
  19262   19653   19653   19262 pts/0      19653 R+    1000   0:00 ps ajx
  19262   19654   19653   19262 pts/0      19653 S+    1000   0:00 less
Enter fullscreen mode Exit fullscreen mode

From the output, we can see that there is a login session led by bash(19262), within which there is a process group with a PGID of 19653. The constituents of this group are ps ajx(19653) and less(19654), which is piped to it.

Lastly, let me also mention how to distinguish foreground process groups. In the output of ps ajx, the processes belonging to the foreground process group have a + in their STAT field.

The concepts of sessions and process groups can be challenging,


You might have heard the term "daemon" in the context of UNIX or Linux countless times. This section will discuss what daemons are and how they differ from regular processes. Simply put, daemons are resident processes. While regular processes are expected to terminate after completing a series of operations initiated by a user, daemons do not necessarily behave this way and may persist from system start to finish, depending on the case.

Daemons have the following characteristics:

  • They do not require terminal I/O, so no terminal is assigned to them.
  • They possess their own session to remain unaffected even if all login sessions end.
  • Init acts as their parent process so that the process generating the daemon does not need to worry about the daemon's termination.

If illustrated, it would look like this:


However, even if they do not meet the above conditions, they may be referred to as daemons if they are resident processes.

You can determine whether a process is a daemon by looking at the results of ps ajx. Let's take a look at sshd, which operates as an ssh server.

$ ps ajx
      1     960     960     960 ?             -1 Ss       0   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
Enter fullscreen mode Exit fullscreen mode

Indeed, the parent process is init (PPID is 1), and the session ID equals the PID.

Because daemons do not possess a terminal, the SIGHUP, which signifies a terminal hang-up, can be utilized for different purposes. By convention, it is often used as a signal for daemons to reread their configuration files.

previous part
next part


This article is based on my book written in Japanese. Please contact me via if you're interested in publishing this book's English version.

Top comments (1)

ramprogrammer profile image

thanks you so much. extremely good article. I am tuned to your series of articles ahead.