Linux Processes and Signals | Bash

In Linux, a process is a fundamental concept representing an instance of a running program. Each process has its own unique identifier (PID) assigned by the operating system and consists of program code, data, and system resources such as file descriptors and memory allocations. Processes can be in various states including running, stopped, sleeping, or zombie. They interact with the kernel for resource allocation, system calls, and communication with other processes through mechanisms like signals.

Processes can be created by other processes (forking), by the operating system in response to user commands or events, or by the kernel itself. Understanding processes is essential for managing system resources, multitasking, and controlling program execution on Linux systems.

Types of Processes in Linux

Processes can be categorized into various types based on different criteria. Here are some common types of processes in Linux:

  1. Foreground Processes: These processes are initiated by a user and interact directly with the user through the terminal. They typically require user input or provide output to the terminal.
  2. Background Processes: Background processes are initiated by a user but do not require direct interaction with the user. They continue executing in the background while allowing the user to perform other tasks in the terminal.
  3. System Processes: System processes are initiated and managed by the operating system kernel. They perform essential system tasks such as managing hardware, scheduling tasks, and handling system events.
  4. User Processes: User processes are initiated and managed by users. They include applications, services, and tasks initiated by users to perform specific functions or operations.
  5. Daemon Processes: Daemons are background processes that run continuously, often without user intervention. They perform system-related tasks such as managing services, handling requests, and monitoring system events. Examples include web servers (e.g., Apache), database servers (e.g., MySQL), and network services (e.g., SSH).
  6. Parent and Child Processes: Processes in Linux can form parent-child relationships, where a parent process spawns one or more child processes. Parent processes typically initiate child processes, and child processes inherit certain attributes from their parent, such as file descriptors and environment variables.
  7. Zombie Processes: Zombie processes are processes that have completed execution but still have an entry in the process table. They exist in a terminated state but have not yet been removed from the process table because their parent process has not yet retrieved their exit status.
  8. Orphan Processes: Orphan processes are processes whose parent process has terminated or been killed. They are adopted by the init process (PID 1) and continue execution independently.

Process Table

The process table is a data structure maintained by the kernel to keep track of all the processes currently running on the system. It stores information about each process, such as its Process ID (PID), Parent Process ID (PPID), status, priority, CPU and memory usage, and more. The process table is essential for process management, resource allocation, and system monitoring.

Here are some key points about the process table in Linux:

  1. PID (Process ID): A unique identifier assigned to each process by the operating system. This allows processes to be identified and managed.
  2. PPID (Parent Process ID): The PID of the parent process that created the current process. This helps in organizing processes into a hierarchical structure.
  3. Status: Indicates the current state of the process, such as running, sleeping, stopped, or zombie.
  4. Priority: The scheduling priority of the process, which determines its importance in CPU allocation.
  5. CPU and Memory Usage: Information about the amount of CPU time and memory resources consumed by the process.
  6. Command: The command or program associated with the process.

Initializing a process

Linux processes are brought into existence by creating a new process and establishing its environment, which is then followed by the execution of the desired program or command. The first prevalent approach that is often used to boot a process is via utilization of shell commands and scripts. Here's an example using a shell script:Here's an example using a shell script:

#!/bin/bash # Example script to initialize a process # This script creates a new process and executes a command within it # Print a message to indicate the start of the process initialization echo "Initializing a new process..." # Execute a command within the new process # Example: Run the 'ls' command to list files in the current directory ls -l # Print a message to indicate the end of the process initialization echo "Process initialization complete."

To run this script, save it to a file (e.g., initialize_process.sh), make it executable using chmod +x initialize_process.sh, and then execute it using ./initialize_process.sh. The script will create a new process and execute the specified command within it.

Tracking ongoing processes

Tracking ongoing processes in Linux involves monitoring and managing the execution of active processes on the system. There are various commands and tools available for tracking processes. One commonly used command is ps, which stands for "processes status". Here's an example of how to track ongoing processes using ps:

# Display a list of all processes running on the system ps aux
Explanation:
  1. ps: Command to display information about processes.
  2. aux: Options to display all processes (a), along with those of other users (u), and in a format that includes additional details (x).

The output of ps aux typically includes information such as the PID (Process ID), the user who owns the process, CPU and memory usage, command being executed, and more.

Additionally, you can track specific processes by name using pgrep, which searches for processes based on a given pattern. For example:

# Display PIDs of processes named "firefox" pgrep firefox

This command will return the PID(s) of any processes with the name "firefox".

Another useful tool for tracking ongoing processes is top, which provides a dynamic real-time view of system processes along with their resource usage. Simply run top in the terminal to launch the interactive display.

top

You can use this display to monitor CPU and memory usage, as well as sort processes by various criteria such as CPU or memory usage.

Stopping a process

Stopping a process in Linux involves sending a signal to the process, instructing it to suspend its execution temporarily. The most common signal used for stopping a process is SIGSTOP (signal number 19). You can stop a process using the kill command or its equivalent killall to target processes by name. Here's an example:

# Stop a process with a specific PID kill -STOP <PID>
Explanation:
  1. kill: Command to send signals to processes.
  2. -STOP: Signal option indicating to stop the process. The signal number for stopping a process is 19, but you can use either the number or its name.
  3. <PID>: The Process ID of the process you want to stop.

For instance, if you want to stop a process with PID 1234, you would execute:

kill -STOP 1234

Alternatively, you can use the killall command to stop processes by name:

# Stop all processes named "my_process" killall -STOP my_process

This command sends the SIGSTOP signal to all processes with the name "my_process", causing them to stop their execution temporarily.

Process Priority

Process priority, also known as scheduling priority, determines the importance or urgency of a process relative to other processes in the system. The priority influences how the scheduler allocates CPU time to processes. Linux provides several priority levels, typically ranging from -20 to 19, where lower numbers represent higher priorities. The scheduler typically favors processes with higher priority when allocating CPU time.

Setting Process Priority

You can set the priority of a process using the nice and renice commands.

nice: The nice command is used to launch a new process with a specified priority. The default priority is 0.
nice -n <priority><command>
Example:
nice -n 10 ./my_long_running_task.sh
renice: The renice command changes the priority of an existing process.
renice <priority> -p <PID>
Example:
renice +10 -p 1234

Viewing Process Priorities

You can view process priorities using commands like top, ps, or htop.

top: Displays a dynamic real-time view of system processes and their priorities.
top
ps: Lists processes along with their priorities.
ps -eo pid,ppid,nice,cmd

Signals

Signals are software interrupts sent to processes to notify them of various events or requests. They can be used for inter-process communication or to instruct a process to perform a certain action, such as termination or reinitialization.

Common Signals

  1. SIGTERM (15): Terminate signal, typically used to terminate a process.
  2. SIGKILL (9): Kill signal, used to forcibly terminate a process.
  3. SIGINT (2): Interrupt signal, usually generated by pressing Ctrl+C in the terminal.
  4. SIGHUP (1): Hangup signal, often used to instruct a process to reload its configuration.

Sending Signals

kill: The kill command sends signals to processes. By default, it sends SIGTERM.
kill <PID>
Example:
kill 1234

You can also specify a signal using - <signal> option.

kill -9 1234 # Sends SIGKILL
killall: Similar to kill, but it sends signals to all processes matching a given name.
killall <process_name>
Example:
killall my_process

Handling Signals in Scripts

In bash scripts, you can handle signals using the trap command to specify actions to take when a signal is received.

trap 'echo "SIGINT received"' SIGINT

This will execute echo "SIGINT received" whenever a SIGINT signal is received.

Example Scenario:

Let's say you have a long-running process and you want to change its priority and also send signals to control its behavior.

# Start a process with increased priority nice -n 10 ./my_long_running_task.sh & # Send SIGTERM to terminate the process kill <PID> # If the process doesn't terminate, send SIGKILL to forcefully terminate it kill -9 <PID>

Conclusion

Processes are independent instances of running programs, each with a unique Process ID (PID) and various attributes such as status, priority, and resource usage. Signals in Linux are software interrupts used for inter-process communication and process management, allowing processes to respond to events such as termination requests, user inputs, or system events, with common signals including SIGTERM for termination and SIGINT for interrupting processes. Understanding Linux processes and signals is crucial for managing system resources, controlling process behavior, and facilitating communication between processes.