一、实现目标
1)售票员捕捉SIGINT(代表开车)信号,向司机发送SIGUSR1信号,司机打印(let's gogogo)
2)售票员捕捉SIGQUIT(代表停车)信号,向司机发送SIGUSR2信号,司机打印(stop the bus)
3)司机捕捉SIGTSTP(代表到达终点站)信号,向售票员发送SIGUSR1信号,售票员打印(please get off the bus)
4)司机等待售票员下车,之后司机再下车。
二、代码思路
- 程序启动后,创建子进程。
- 子进程输出自身身份并设置其信号处理程序。
- 父进程输出身份并设置其信号处理程序。
- 两个进程通过信号进行通信:
- 子进程可通过
SIGINT
或SIGQUIT
向父进程发送信号。 - 父进程在接收到信号时会做出相应的响应(如打印信息或终止子进程)。
三、实现原理
-
全局变量:
pid
:用于存储子进程的进程 ID。 -
信号处理函数:
子进程(售货员): saler(int sig)
:处理不同信号:SIGUSR1
:接收到后打印消息并退出。SIGQUIT
:向父进程发送SIGUSR2
信号。SIGINT
:向父进程发送SIGUSR1
信号。-
父进程(司机):
-
driver(int sig)
:处理不同信号:SIGTSTP
:向子进程发送SIGUSR1
,等待子进程退出后终止自己。SIGUSR2
:打印停止消息。SIGUSR1
:打印开始消息。
-
主函数 (
main
):- 创建子进程,使用
fork()
。 - 在子进程中设置信号处理函数,并忽略
SIGTSTP
。 - 在父进程中设置信号处理函数,并忽略
SIGINT
和SIGQUIT
。 - 使用
pause()
循环等待信号的到来。
- 创建子进程,使用
信号处理机制
- 信号的处理:
- 子进程和父进程各自设定了对特定信号的处理方式。
- 子进程处理
SIGINT
和SIGQUIT
,通过发送信号给父进程进行通信。 - 父进程处理来自子进程的
SIGUSR1
和SIGUSR2
,并在接收到SIGTSTP
时处理逻辑以终止子进程。
四、实现代码
标签:售票,io,SIGUSR1,信号,进程,sa,sigaction,SIGQUIT From: https://blog.csdn.net/weixin_63207763/article/details/142566950#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;
}