首页 > 其他分享 >用io跟信号实现售票

用io跟信号实现售票

时间:2024-09-26 17:19:55浏览次数:8  
标签:售票 io SIGUSR1 信号 进程 sa sigaction SIGQUIT

一、实现目标

1)售票员捕捉SIGINT(代表开车)信号,向司机发送SIGUSR1信号,司机打印(let's gogogo)

2)售票员捕捉SIGQUIT(代表停车)信号,向司机发送SIGUSR2信号,司机打印(stop the bus)

3)司机捕捉SIGTSTP(代表到达终点站)信号,向售票员发送SIGUSR1信号,售票员打印(please get off the bus)

4)司机等待售票员下车,之后司机再下车。

二、代码思路

  1. 程序启动后,创建子进程。
  2. 子进程输出自身身份并设置其信号处理程序。
  3. 父进程输出身份并设置其信号处理程序。
  4. 两个进程通过信号进行通信:
  5. 子进程可通过 SIGINT 或 SIGQUIT 向父进程发送信号。
  6. 父进程在接收到信号时会做出相应的响应(如打印信息或终止子进程)。

三、实现原理

  1. 全局变量:pid:用于存储子进程的进程 ID。

  2. 信号处理函数:

    子进程(售货员):
  3. saler(int sig):处理不同信号:
    • SIGUSR1:接收到后打印消息并退出。
    • SIGQUIT:向父进程发送 SIGUSR2 信号。
    • SIGINT:向父进程发送 SIGUSR1 信号。
    • 父进程(司机):

    • driver(int sig):处理不同信号:

      • SIGTSTP:向子进程发送 SIGUSR1,等待子进程退出后终止自己。
      • SIGUSR2:打印停止消息。
      • SIGUSR1:打印开始消息。
  4. 主函数 (main):

    • 创建子进程,使用 fork()
    • 在子进程中设置信号处理函数,并忽略 SIGTSTP
    • 在父进程中设置信号处理函数,并忽略 SIGINT 和 SIGQUIT
    • 使用 pause() 循环等待信号的到来。

  信号处理机制

  • 信号的处理:
    • 子进程和父进程各自设定了对特定信号的处理方式。
    • 子进程处理 SIGINT 和 SIGQUIT,通过发送信号给父进程进行通信。
    • 父进程处理来自子进程的 SIGUSR1 和 SIGUSR2,并在接收到 SIGTSTP 时处理逻辑以终止子进程。

四、实现代码

#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;
}

标签:售票,io,SIGUSR1,信号,进程,sa,sigaction,SIGQUIT
From: https://blog.csdn.net/weixin_63207763/article/details/142566950

相关文章

  • Reflections库
    Reflections是一个Java库,它使用扫描、查询和分析的方式来简化Java反射API的使用。它允许开发者在运行时查询类、字段、方法、注解等元数据,而不必直接使用Java内置的反射机制,从而使得代码更加简洁易读。核心功能1.扫描预定义的URLs:Reflections可以扫描项目的类路径、特定的目录或......
  • Record of ABC Notation Used in Obsidian
    Whentypingcodesnippet %%linebreak<none> X:1 K:Ctreble %Cmajor,fouroctaves: C,D,E,F,G,A,B,C|CDEFGABc| cdefgabc'|c'e'g'c''|inMakingMusicwithAbc2-ApracticalguidetotheA......
  • MySQL variables:max_connections&&max_user_connections
    结论1:max_connections变量的意义是限制当前mysqlserver中允许同时连接的不同用户数,并不对相同用户的多次连接进行限制结论2:max_user_connections变量的意义是限制当前mysqlserver中允许同时连接的相同用户的连接数,不对连接的不同用户数进行限制结论3:对max_connections变量的......
  • 面试官:谈谈你对IO多路复用的理解?
    “IO多路复用”是编程中常见的技术词汇,使用这种技术的框架有很多,如,Redis、Kafka、Netty、Nginx中都用到了此技术。那问题来了,什么是IO多路复用?它的具体实现技术有哪些?这些技术之间有什么区别?今天我们就来简单的探讨一下。1.什么是IO多路复用?IO多路复用技术是一种允许单个......
  • Meta公布首款AR眼镜Orion,成本1万美元;OpenAI CTO Mira Murati离职丨RTE开发者日报
     开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑的个......
  • C++学习,信号处理
    C++信号处理,依赖于操作系统提供的API。信号处理主要用于响应外部事件,如中断信号(如SIGINT,SIGTERM等),这些信号可以由操作系统、其他程序或用户生成。在Unix-like系统(如Linux和macOS)中,信号处理可以通过signal函数或更灵活的sigaction函数来设置。在C++程序中直接使用这些函数是......
  • 2024年模式识别与图像分析国际学术会议(PRIA 2024) 2024 International Conference on P
    文章目录一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询一、会议详情二、重要信息大会官网:https://ais.cn/u/vEbMBz提交检索:EICompendex、IEEEXplore、Scopus2024年10月18-20日南京三、大会介绍2024年模式识别与图像分析国际学术会......
  • 2024年自动化、电气控制系统与设备国际学术会议(AECSE 2024) 2024 International Confer
    文章目录一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询一、会议详情二、重要信息大会官网:https://ais.cn/u/vEbMBz提交检索:EICompendex、IEEEXplore、Scopus2024年10月18-20日,南京三、大会介绍2024年自动化、电气控制系统与设备国际......
  • 【VUE】[Violation] Added non-passive event listener to a scroll-blocking...
    1.问题[Violation]Addednon-passiveeventlistenertoascroll-blocking<某些>事件.Considermarkingeventhandleras'passive'tomakethepagemoreresponsive.See<URL>译:[违规]向滚动阻止添加了非被动事件侦听器<某些>事件.请考虑将事件处理程序标记为“被......
  • 导航信号转发器 北斗转发器 gps信号放大转发器
    卫星信号不能够穿透建筑物,生产车间、实验室等室内环境,对相应环境下的测试工作造成困难。GNSS信号转发器可实现将卫星信号从室外转发到室内,广泛的应用在大型基站实验室、隧道、矿井、航空制造,航空维修等行业。SYN2309型GNSS信号转发器产品概述SYN2309型GNSS信号转发器是由西安同步电......