用信号的知识实现司机和售票员问题。
1)售票员捕捉SIGINT(代表开车)信号,向司机发送SIGUSR1信号,司机打印(let's gogogo)
2)售票员捕捉SIGQUIT(代表停车)信号,向司机发送SIGUSR2信号,司机打印(stop the bus)
3)司机捕捉SIGTSTP(代表到达终点站)信号,向售票员发送SIGUSR1信号,售票员打印(please get off the bus)
4)司机等待售票员下车,之后司机再下车。
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
pid_t pid; // 全局变量,用于存储子进程的进程 ID
// 子进程(售货员)的信号处理函数
void saler(int sig)
{
if (sig == SIGINT)
{
// 收到 SIGINT 信号时,向父进程发送 SIGUSR1 信号
if (kill(getppid(), SIGUSR1) == -1) {
perror("kill SIGUSR1 error");
}
}
else if (sig == SIGQUIT)
{
// 收到 SIGQUIT 信号时,向父进程发送 SIGUSR2 信号
if (kill(getppid(), SIGUSR2) == -1) {
perror("kill SIGUSR2 error");
}
}
else if (sig == SIGUSR1)
{
// 收到 SIGUSR1 信号时,打印消息并退出
printf("pls get off the bus!\n");
exit(0);
}
}
// 父进程(司机)的信号处理函数
void driver(int sig)
{
if (sig == SIGUSR1)
// 收到 SIGUSR1 信号时,打印开始消息
printf("let's gogogo!!!~~\n");
else if (sig == SIGUSR2)
// 收到 SIGUSR2 信号时,打印停止消息
printf("stop the bus!\n");
else if (sig == SIGTSTP)
{
// 收到 SIGTSTP 信号时,向子进程发送 SIGUSR1 信号,并等待子进程退出
if (kill(pid, SIGUSR1) == -1) {
perror("kill SIGUSR1 error");
}
if (wait(NULL) == -1) {
perror("wait error");
}
exit(0);
}
}
int main(int argc, char const *argv[])
{
pid = fork(); // 创建子进程
if (pid < 0)
{
perror("fork error");
return -1;
}
else if (pid == 0)
{
// 子进程(售货员)
printf("I am saler!\n");
struct sigaction sa;
sa.sa_handler = saler; // 设置信号处理函数
sigemptyset(&sa.sa_mask); // 清空信号集
sa.sa_flags = 0; // 没有特殊标志
// 设置信号处理
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
// 忽略 SIGTSTP 信号
sa.sa_handler = SIG_IGN;
sigaction(SIGTSTP, &sa, NULL);
}
else
{
// 父进程(司机)
printf("I am driver!\n");
struct sigaction sa;
sa.sa_handler = driver; // 设置信号处理函数
sigemptyset(&sa.sa_mask); // 清空信号集
sa.sa_flags = 0; // 没有特殊标志
// 设置信号处理
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
sigaction(SIGTSTP, &sa, NULL);
// 忽略 SIGINT 和 SIGQUIT 信号
sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
}
while (1)
pause(); // 等待信号
return 0;
}