C语言信号功能异常:偶数信号处理函数未执行求助
The primary issue here is an uninitialized variable in the first child process that prevents it from setting up the SIGUSR1 handler. Let's break down what's happening:
1. Uninitialized pid2 in Child 1
When the parent forks pid1 (child 1), the child 1 process skips the pid2 = fork() line because pid1 is 0 in the child context. This means pid2 in child 1 is uninitialized (holds a random garbage value). The condition !pid1 && pid2 for child 1 will almost certainly evaluate to false (since pid2 could be 0 or an invalid value), so child 1 never installs the SIGUSR1 handler.
When the parent sends SIGUSR1 to child 1, the default signal action (termination) is triggered instead of your custom handler. That's why you see no output for even numbers—child 1 dies immediately after the first even signal is sent.
2. Additional Issues & Fixes
Beyond the main bug, there are several other problems in the code that need addressing for reliability and correctness:
a. Poor Process Structure
Your original code puts parent and child logic in the same infinite loop, leading to redundant signal handler setup and uninitialized variables. Instead, handle child processes immediately after forking.
b. Unclosed Pipe File Descriptors
Each process should close unused pipe ends to avoid unexpected behavior (like read() hanging waiting for EOF that never arrives).
c. Non-Async-Signal-Safe Functions in Handlers
printf() and sleep() are not async-signal-safe, which means using them in a signal handler can cause undefined behavior. Replace printf() with write() (a safe alternative) and avoid sleep() in handlers.
d. Unseeded Random Number Generator
rand() will generate the same sequence of numbers every run unless you seed it with srand(time(NULL)).
Fixed Code Implementation
Here's the corrected code with all these fixes applied:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <string.h> pid_t pid1, pid2; int fd[4]; // Async-signal-safe handler for even numbers (SIGUSR1) void handler_one() { int ric1; read(fd[0], &ric1, sizeof(int)); char buf[100]; ssize_t len = snprintf(buf, sizeof(buf), "I'm the first child process...the even received number is...%d\n", ric1); write(STDOUT_FILENO, buf, len); } // Async-signal-safe handler for odd numbers (SIGUSR2) void handler_two() { int ric2; read(fd[2], &ric2, sizeof(int)); char buf[100]; ssize_t len = snprintf(buf, sizeof(buf), "I'm the second child process...the odd received number is...%d\n", ric2); write(STDOUT_FILENO, buf, len); } int main() { // Initialize pipes if (pipe(fd) == -1 || pipe(fd + 2) == -1) { perror("pipe failed"); exit(1); } // Fork first child pid1 = fork(); if (pid1 == -1) { perror("fork pid1 failed"); exit(1); } else if (pid1 == 0) { // Child 1 setup: handle SIGUSR1, close unused pipes signal(SIGUSR1, handler_one); close(fd[1]); // Close write end of first pipe close(fd[2]); // Close read end of second pipe close(fd[3]); // Close write end of second pipe // Wait indefinitely for signals while (1) { pause(); } } // Fork second child (only parent reaches here) pid2 = fork(); if (pid2 == -1) { perror("fork pid2 failed"); exit(1); } else if (pid2 == 0) { // Child 2 setup: handle SIGUSR2, close unused pipes signal(SIGUSR2, handler_two); close(fd[0]); // Close read end of first pipe close(fd[1]); // Close write end of first pipe close(fd[3]); // Close write end of second pipe // Wait indefinitely for signals while (1) { pause(); } } // Parent setup: close unused pipes, seed random generator close(fd[0]); // Close read end of first pipe close(fd[2]); // Close read end of second pipe srand(time(NULL)); // Parent loop: generate random numbers and send to children while (1) { printf("I'm the parent and I'm gonna send a random number\n"); int r = rand() % 10 + 1; if (r % 2 == 0) { write(fd[1], &r, sizeof(int)); kill(pid1, SIGUSR1); } else { write(fd[3], &r, sizeof(int)); kill(pid2, SIGUSR2); } sleep(1); } return 0; }
Key Changes Explained
- Process Structure: Each child is handled immediately after forking, eliminating uninitialized variables and redundant handler setup.
- Pipe Cleanup: Unused pipe ends are closed in each process to prevent resource leaks and unexpected behavior.
- Safe Signal Handling: Replaced
printf()withwrite()to avoid undefined behavior in signal handlers. - Seeded Randomness:
srand(time(NULL))ensures different random sequences on each run. - Proper Waiting: Children use
pause()to wait for signals efficiently instead of looping unnecessarily.
This should resolve the issue with the even signal handler not responding, and make the code more robust overall.
内容的提问来源于stack exchange,提问作者Hackasim

