进程间的通信方式之一信号,是如何在应用进程和内核之间交互的?

本文详细解释了SIGCHLD信号在Unix和类Unix系统中的作用,它是如何通知父进程子进程状态变化的,尤其是在子进程终止时。通过流程图和C语言示例展示了信号执行流程以及如何通过waitpid处理子进程退出状态,包括正常退出和异常退出的情况。
摘要由CSDN通过智能技术生成

信号的基本概念

关于信号的详细说明可见 5.2 进程间有哪些通信方式? | 小林coding (xiaolincoding.com) 的“信号”部分,这里不再赘述。

关于信号的问题——信号是如何在应用进程和内核之间交互的?

上面给出的链接中有个“总结”部分,其中关于信号的介绍见下图:

在这里插入图片描述
上图中的划线处可引出一个问题——信号是如何在应用进程和内核之间交互的?详细过程可用下面的一张信号执行流程图说明:

在这里插入图片描述
图源:信号执行流程_云的小站的博客-CSDN博客

针对信号执行流程图的一些疑问

17号信号是SIGCHLD信号,那SIGCHLD信号是什么

(解答来自ChatGPT)

SIGCHLD 是一个在 Unix 和类 Unix 操作系统中用于通知父进程子进程状态变化的信号。当子进程终止时,内核会向其父进程发送 SIGCHLD 信号。这个信号的主要作用是通知父进程子进程的终止状态,以便父进程可以采取适当的处理。

主要情况包括:

  1. 子进程终止: 当一个子进程终止时,内核向其父进程发送 SIGCHLD 信号。
  2. 子进程停止: 如果子进程停止或恢复执行,也会发送 SIGCHLD 信号,通知父进程子进程的状态发生了变化。
  3. 父进程对子进程状态的处理: 父进程通常通过调用 waitwaitpid 系统调用来获取子进程的退出状态,以防止出现僵尸进程(zombie process)。

SIGCHLD 信号的处理通常包括以下几个步骤:

  • 等待子进程退出: 父进程调用 waitwaitpid 等待子进程退出。这样父进程就能够获取子进程的退出状态,避免子进程成为僵尸进程。
  • 处理子进程退出状态: 父进程通过检查子进程的退出状态,了解子进程是正常退出还是异常退出,以及退出时的返回值等信息。

示例代码(C语言):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

void sigchld_handler(int signo) {
    pid_t pid;
    int status;

    // 等待子进程退出
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if (WIFEXITED(status)) {
            printf("Child process %d exited with status %d\n", pid, WEXITSTATUS(status));
        } else if (WIFSIGNALED(status)) {
            printf("Child process %d terminated by signal %d\n", pid, WTERMSIG(status));
        }
    }
}

int main() {
    signal(SIGCHLD, sigchld_handler);

    // 创建子进程
    pid_t pid = fork();

    if (pid == 0) {
        // 子进程
        printf("Child process\n");
        sleep(2);
        exit(42);
    } else if (pid > 0) {
        // 父进程
        printf("Parent process\n");

        // 父进程可以继续执行其他操作

        // 等待 SIGCHLD 信号处理子进程退出
        while (1) {
            sleep(1);
        }
    } else {
        perror("fork");
        return 1;
    }

    return 0;
}

在上述示例中,父进程通过 waitpid 函数等待子进程退出,并通过 WIFEXITEDWIFSIGNALED 宏检查子进程的退出状态。当子进程终止时,会触发 SIGCHLD 信号,执行 sigchld_handler 处理函数。

pid_t pid = fork();的含义是什么

pid_t pid = fork(); 是在 C 语言中创建一个新进程的方式之一,使用了 fork 系统调用。这行代码的含义是创建一个子进程,并且在父子进程中分别返回不同的值。

具体来说:

  • fork 是一个系统调用,调用一次,返回两次。它创建了一个新的进程,新进程是调用进程的副本,称为子进程。在父进程和子进程中,fork 的返回值是不同的。
  • 在父进程中,fork 返回新创建的子进程的进程ID(PID),即子进程的PID。
  • 在子进程中,fork 返回 0,表示当前进程是子进程。

示例代码:

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid == -1) {
        // 创建子进程失败
        perror("fork");
        return 1;
    } else if (pid == 0) {
        // 子进程代码
        printf("This is the child process. PID: %d\n", getpid());
    } else {
        // 父进程代码
        printf("This is the parent process. Child PID: %d\n", pid);
    }

    // 这里的代码会在父子进程中都执行

    return 0;
}

在这个例子中,fork 调用后,父进程和子进程都会执行 ifelse if 语句块后面的代码,但由于 fork 的返回值不同,它们会在不同的分支中执行。在父进程中,pid 是子进程的PID;在子进程中,pid 是0。

exit(42);的含义是什么

exit(42) 是一个在 C 语言中用于终止程序执行的语句。具体来说,exit 函数用于正常地终止程序,并返回一个退出状态码(exit status)。在这里,42 是退出状态码的值。

在 Unix/Linux 等操作系统中,程序的退出状态码是一个整数,通常用于传递程序的退出状态给调用它的进程。约定上,一个程序返回 0 表示正常退出,而其他非零值则表示某种错误或异常情况。

WIFEXITED和WIFSIGNALED的含义是什么

在C语言的进程控制中,WIFEXITEDWIFSIGNALED 是两个宏,用于判断子进程的终止状态。WIFEXITED(status) 用于判断子进程是否正常终止。WIFSIGNALED(status) 用于判断子进程是否因为信号而终止。因此,用exit(42)正常退出时,WIFEXITED(status)返回true。

参考

  1. 5.2 进程间有哪些通信方式? | 小林coding (xiaolincoding.com)
  2. 信号执行流程_云的小站的博客-CSDN博客
  3. chatGPT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值