0%

Siganls

A signal is a mechanism for communication between processes. You can think of it like a notification that interrupts you, prompting you to pay attention to something important.


The signal is asynchronous (compared to hardware interrupts), and the arrival time and content of the signal are uncertain meaning you can’t predict when a signal will arrive

The signal is essentially an int type digital number (pre-defined)
For example:1.SIGINT (2): This signal interrupts a process. It’s typically sent when you press Ctrl+C in a terminal to stop a running program. 2.SIGTERM (15): This is a termination signal. It politely asks a process to terminate, allowing it to clean up resources before exiting.

Who sends the signal:

(1) The user presses a button on the terminal

(2) The operating system kernel sends a signal after a hardware failure

(3) The user uses the kill command to send a signal to other processes

(4) A signal is also sent when certain software conditions are met, such as when the alarm time is reached, a SIGALARM signal is generated, and when writing to a pipe whose read end has been closed, a SIGPIPE signal is generated.

Signals can be handled in three main ways:

  1. Ignore the Signal: A process can choose to completely ignore a signal. It simply won’t react to it at all, like ignoring someone who’s trying to get your attention.
  2. Default Handling:This usually means either ignoring the signal or terminating the process,
  3. Capture the Signal: A process can also set up a function to respond to a signal. This means when the signal arrives, it runs the specified function instead of just ignoring it or terminating.

进程组

When you start a process, it can create child processes, and these can be grouped together into a process group. This makes it easier to manage multiple processes as a single unit.

每个进程都都只属于一个进程组

getpgidsetpgid 来获取和设置进程组

  • int getpgid(int pid):获取指定进程的进程组 ID。
  • int setpgid(int pid, int pgid):设置指定进程的进程组 ID。

PGID(Process Group ID,进程组 ID) 和 PID(Process ID,进程 ID) 是 Linux 系统中用于标识进程和进程组的两个重要标识符。

  • 进程组通常由一个 “组长” 进程创建,它的 PGID 和它的 PID 相同。其他进程可以通过 setpgid 函数加入这个进程组。
  • 所有同一进程组中的进程共享相同的 PGID。

Shell 作为父进程,PID 为 10,PGID 也为 10,它管理了多个作业(前台和后台)

前台后台

  • 前台作业(Foreground job)
    • 由进程 PID 20(PGID 20)组成,该作业下有两个子进程(PID 21 和 PID 22),它们的 PGID 都是 20,这意味着它们属于同一个进程组。
  • 后台作业 1(Background job #1)
    • 由进程 PID 32(PGID 32)组成,这是一个独立的后台作业,其 PGID 和 PID 相同。
  • 后台作业 2(Background job #2)
    • 由进程 PID 40(PGID 40)组成,类似于后台作业 1,独立运行,PGID 也是它自己的 PID。

Let’s send a signal

  1. 用 */bin/kill* 程序发送信号

    1
    2
    # 发送信号 9 (SIGKILL)给进程组15213
    /bin/kill -9 15213
  2. 从键盘发送信号:

    通过键盘让内核向每个前台进程发送 SIGINT(SIGTSTP) 信号

    1
    2
    Ctrl+C  (SIGINT)   #默认终止进程
    Ctrl+Z (SIGTSTP) #默认挂起进程
  3. 用[kill 函数](https://so.csdn.net/so/search?q=kill 函数&spm=1001.2101.3001.7020)发送信号:

1
2
	//使用kill发送信号号码 sig 给进程 pid
int kill(pid_t pid, int sig);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
如下程序为 父进程发送 SIGKILL 信号给它的子进程:
int main()
{
pid_t pid;

/* Child sleeps until SIGKILL signal received, then dies */
if ((pid = fork()) == 0)
{
pause(); /* Wait for a signal to arrive */
printf("control should never reach here!\n");
exit(0);
}

/* Parent sends a SIGKILL signal to a child */
kill(pid, SIGKILL);
exit(0);

Blocking

Blocking signals means that while a process is handling a particular signal, it won’t be interrupted by other signals of the same type.

When a process receives a signal, it may execute a signal handler (a specific function designed to deal with that signal). For example, if it’s handling a SIGINT (interrupt signal), it runs the associated function.

Blocking Same Signals: While this handler is running, any other incoming SIGINT signals are blocked. This means that if another SIGINT arrives, it won’t interrupt the current handling process

This prevents confusion and ensures that the process can complete its response to the first signal without being interrupted, maintaining stability and clarity in how signals are processed.