信号的基本概念

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

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

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

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

图源:信号执行流程_云的小站的博客-CSDN博客

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

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

(解答来自ChatGPT)

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

主要情况包括:

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

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

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

示例代码(C语言):

#include

#include

#include

#include

#include

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 函数等待子进程退出,并通过 WIFEXITED 和 WIFSIGNALED 宏检查子进程的退出状态。当子进程终止时,会触发 SIGCHLD 信号,执行 sigchld_handler 处理函数。

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

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

具体来说:

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

示例代码:

#include

#include

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 调用后,父进程和子进程都会执行 if、else if 语句块后面的代码,但由于 fork 的返回值不同,它们会在不同的分支中执行。在父进程中,pid 是子进程的PID;在子进程中,pid 是0。

exit(42);的含义是什么

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

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

WIFEXITED和WIFSIGNALED的含义是什么

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

参考

5.2 进程间有哪些通信方式? | 小林coding (xiaolincoding.com)信号执行流程_云的小站的博客-CSDN博客chatGPT

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: