在C语言中,要让一个进程正确接收并处理来自父线程的信号,你需要遵循以下几个步骤:
1. 使用信号处理函数
在C语言中,可以通过signal()或sigaction()函数来设置信号处理函数。下面分别介绍这两种方法。
1.1 使用 signal() 函数
signal() 函数允许你为特定信号指定一个处理函数。下面是一个使用 signal() 函数的例子:
#include <stdio.h>
#include <signal.h>
void handle_sigint(int sig) {
printf("Received signal %d\n", sig);
}
int main() {
signal(SIGINT, handle_sigint);
while (1) {
printf("Parent process running...\n");
sleep(1);
}
return 0;
}
在上面的代码中,我们为 SIGINT 信号(通常由Ctrl+C触发)设置了一个处理函数 handle_sigint。
1.2 使用 sigaction() 函数
sigaction() 提供了比 signal() 更多的灵活性,允许你设置信号处理的许多细节,比如处理信号时的阻塞状态。以下是一个使用 sigaction() 的例子:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handle_sigint(int sig, siginfo_t *info, void *context) {
printf("Received signal %d from child with PID %d\n", sig, info->si_pid);
}
int main() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handle_sigint;
sigfillset(&sa.sa_mask);
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
while (1) {
printf("Parent process running...\n");
sleep(1);
}
return 0;
}
在这个例子中,我们为 SIGINT 信号设置了一个处理函数 handle_sigint,它接受三个参数:信号号、与信号相关的信息,以及信号的上下文信息。
2. 创建子线程
为了让父线程能够接收来自子线程的信号,你需要创建一个子线程。在Unix-like系统中,可以使用 pthread_create() 函数来实现。
以下是一个父线程和子线程之间传递信号的例子:
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
void *child_thread(void *arg) {
// 子线程中设置信号处理函数
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN; // 忽略信号
sigaction(SIGINT, &sa, NULL);
// 子线程中执行一些操作
printf("Child process running...\n");
sleep(2);
return NULL;
}
int main() {
pthread_t child_pid;
if (pthread_create(&child_pid, NULL, child_thread, NULL) != 0) {
perror("pthread_create");
return 1;
}
// 等待子线程执行完毕
pthread_join(child_pid, NULL);
// 父线程中设置信号处理函数
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handle_sigint;
sigfillset(&sa.sa_mask);
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
printf("Parent process running...\n");
while (1) {
sleep(1);
}
return 0;
}
在这个例子中,父线程和子线程都设置了 SIGINT 的信号处理函数。父线程通过 pthread_create() 创建了子线程,然后等待子线程执行完毕。父线程会持续运行,直到接收到 SIGINT 信号。
3. 父进程接收子进程的信号
如果你想要父进程接收来自已终止的子进程的信号,可以使用 sigwait() 函数。以下是一个示例:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void handle_sigchld(int sig) {
printf("Child process terminated with PID %d\n", waitpid(-1, NULL, 0));
}
int main() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handle_sigchld;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// 创建并终止子进程
pid_t pid = fork();
if (pid == 0) {
printf("Child process (PID %d) is running...\n", getpid());
sleep(2);
exit(0);
} else if (pid > 0) {
printf("Parent process: Child created with PID %d\n", pid);
}
printf("Parent process running...\n");
while (1) {
sleep(1);
}
return 0;
}
在这个例子中,父进程通过 fork() 创建了一个子进程。子进程运行了2秒钟后退出。父进程使用 waitpid() 函数等待子进程的终止,并在 handle_sigchld() 函数中处理 SIGCHLD 信号。
通过以上步骤,你可以在C语言程序中让进程正确接收并处理来自父线程的信号。注意,在实际开发中,你可能需要根据具体需求调整信号处理函数的行为和程序的整体结构。
