【TCP/IP】多进程服务器的实现(进阶) - 信号处理及signal、sigaction函数

目录

信号

signal函数

sigaction函数

用信号来处理僵尸进程


        在之前我们学习了如何处理“僵尸进程”,不过可能也会有疑问:调用wait和waitpid函数时我们关注的始终是在子进程上,那么在父进程上如何实现对子进程的管控呢?为此,我们引入一个概念——信号处理。

信号

        信号这个概念大家应该不陌生,诸如汽车的鸣笛、闹钟的响铃等,这些都是信号,用以告诉人们某件事情的发生。而在计算机中,同样有这个概念。在编程上常用信号来对接收到的某些数据或者指令做出与之对应的响应处理。

signal函数

        让我们先来看看<signal.h>库中的signal函数,其结构如下:

#include <signal.h>

void (*signal (int signo , void (*func)(int))) (int);


// 为了在产生信号时调用,返回之前注册的函数指针。

// 函数名:signal
// 参数 int signo, void (* func)(int)
// 返回类型:参数为int型,返回void型函数指针。

        signo参数用来标记触发的条件,func则为将要调用的函数的指针

        与参数所相关的宏有:

  • SIGALRM: 按照已通过调用alarm函数注册的时间为信号点。
  • SIGINT: 输入CTRL+C暂停时为信号点
  • SIGCHILD: 子进程终止时为信号点。

补充:

        alarm函数的用法及意义如下:

#include <unistd.h>

unsigned int alarm (unsigned int seconds);

// 返回 以秒为单位 的,距 SIGALRM 信号发生时所剩余的时间

        其中 seconds 参数用以传入欲设定的alarm的周期(以s为单位)。若传递0至变量中,则意味着将会取消对SIGALRM信号的预约。同时,若未指定该产生信号所对应的处理函数时,则该进程将被终止。

        接下来,让我们来验证下 SIGALRMSIGINT 两种触发条件下的signal函数吧。

singal.cpp

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void alarmEvent(int sig) //包括下面的keyEvent,这类函数被称为信号处理器(Handler)
{
    if (sig == SIGALRM)
    {
        printf("Time out!\n");
    }

    alarm(2);
}

void keyEvent(int sig)
{
    if (sig == SIGINT)
    {
        printf("\nCTRL+C pressed\n");
    }
}

int main(int argc, char *argv[])
{
    //注册:设置SIGGALRM为触发条件,调用alarmEvent函数
    signal(SIGALRM, alarmEvent); 
    //注册:设置SIGINT为触发条件,调用keyEvent函数
    signal(SIGINT, keyEvent);

    //设置时钟周期为2s
    alarm(2); 

    for (size_t i = 0; i < 5; i++)
    {
        printf("Wait for an event to occur...\n");
        sleep(50);  //实际操作上无法休眠50s
    }

    return 0;
}

        运行结果:

        想法得到验证。

        Q:为什么程序在实际运行上,没有感受到在等待事件发生后的50s延迟呢?

        A:信号在响应时,尽管存在有阻塞态的进程,但操作系统为了调用信号处理器,会强制唤醒进行阻塞态(sleep中的)进程,并且该进程一旦被唤醒,将不会在进入睡眠状态,因此在操作上,我们并不会感受到会有长达50s的延迟。

sigaction函数

        sigaction是对signal函数的升级,能够更好地支持不同的操作系统(signal函数在不同的操作系统中用法和效果可能会不同)。

        让我们来看下这个函数长什么样:

#include <signal.h>

int sigaction(int signo , const struct sigaction * act , struct sigaction *
oldact) ;

// 成功时退回0,失败时退回-1。

/* 参数含义 */

// signo:与signal函数相同,传递信号信息
// act:对应第一个参数的信号处理函数
// oldact:通过此参数获取之前注册的信号处理函数指针,不需要时则传递0。

        对于sigaction,它的结构体定义如下:

 //结构体做了简化,实际上其中一些变量用宏和typedef做了进一步封装

 struct sigaction
    {
        void (*sa_handler)(int);
        sigset_t sa_mask;
        int sa_flags;
        void (*sa_restorer)(void);
    };

        参数意义参考以下: 

  • sa_handler:用以保存信号处理函数的指针值
  • sa_mask:需要滤除的附加信号集,省略
  • sa_flags:特殊标记符,省略
  • sa_restorer:欲重置的(信号)处理器,省略

        OK,让我们编写一个实例来验证这个函数的功能

sigaction.cpp

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void alarmEvent(int sig)
{
    if (sig == SIGALRM)
    {
        printf("Time out!\n");
    }
    alarm(2);
}

int main(int argc, char *argv[])
{
    //声明sigaction结构体变量act
    struct sigaction act;
    //将信号处理函数存入结构体中
    act.sa_handler = alarmEvent;
    //将sa_mask成员的所有位初始化为0
    sigemptyset(&act.sa_mask);
    //将sa_flags成员同样初始化为0
    act.sa_flags = 0;
    //注册:触发条件为SIGALARM,调用act信号处理器中的信息
    sigaction(SIGALRM, &act, 0);

    alarm(2);

    for (size_t i = 0; i < 5; i++)
    {
        printf("Wait for an event to occur...\n");
        sleep(50);
    }

    return 0;
}

        运行结果:

        结果验证了之前的想法。

用信号来处理僵尸进程

        当我们掌握signal、sigaction两个函数后,便可更好地去管控父、子进程了。在之前我们采用的是wait、waitpid函数来销毁僵尸进程。接下来,请大家尝试一下用信号来消灭“僵尸进程”吧!

        欢迎大家在评论区贴出你们的代码~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/29635.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零基础速成simulink代码生成——简单滤波器实现2

simulink setting 找到model settings solver求解器配置 Code Generation 代码生成配置 生成代码报告 添加stateflow注释 可以将变量保存在定义的文件(选) 实践 简单一阶滤波器

使用一键安装工具快速搭建 ESP-IDF 开发环境 (Windows)

我们收到用户对 ESP-IDF SDK 软件开发环境感到搭建难、门槛高的反馈。为解决用户在此方面的问题。为此&#xff0c;我们推出本期教程介绍在 Windows 操作系统下使用一键安装工具快速搭建 ESP-IDF 开发环境。 您可以观看下面的教程视频&#xff0c;也可以阅读接下来本篇的图文教…

CVPR 2023 | 图像超分,结合扩散模型/GAN/部署优化,low-level任务,视觉AIGC系列

1、Activating More Pixels in Image Super-Resolution Transformer 基于Transformer的方法在低级别视觉任务中&#xff0c;如图像超分辨率&#xff0c;表现出了令人印象深刻的性能。Transformer的潜力在现有网络中仍未得到充分发挥。为了激活更多的输入像素以实现更好的重建&a…

有哪些工具软件一旦用了就离不开?

&#x1f496;前言 目前&#xff0c;随着科技的快速发展&#xff0c;电脑已经进入了许许多多人的生活 &#xff0c;在平日的学习、工作和生活里&#xff0c;我们会用的各种各样的强大软件。市面上除了某些大公司开发在强大软件&#xff0c;还有各路大神开发具有某些功能的强大…

Java阶段四Day01

Java阶段四Day01 文章目录 Java阶段四Day01Security框架通配符Vue脚手架 Vue-cli关于VUE关于VUE Cli创建Vue Cli工程解决端口被占用 Vue工程的工程结构[.idea]【重要】[node_modules]【重要】[public]favicon.icoindex.html [src][assets][compnents]【重要】[router][store]【…

Spring基础知识(二)

目录 1.Spring Bean是什么 2.Spring提供的配置方式 3.Spring bean中的scope 4.Spring bean容器的生命周期 5.Spring的内部bean 6.Spring装配是什么 7.自动装配模式 8.自动装配的局限性 9.基于注解配置容器 10.如何启动注解装配 1.Spring Bean是什么 Spring官方文档对…

客户端负载均衡工具Ribbon

一 什么是Ribbon Ribbon介绍 目前主流的负载方案分为以下两种&#xff1a; 集中式负载均衡&#xff0c;在消费者和服务提供方中间使用独立的代理方式进行负载&#xff0c;有硬件的&#xff08;比如 F5&#xff09;&#xff0c;也有软件的&#xff08;比如 Nginx&#xff09;…

10大白帽黑客专用的 Linux 操作系统

平时在影视里见到的黑客都是一顿操作猛如虎&#xff0c;到底他们用的都是啥系统呢&#xff1f; 今天给大家分享十个白帽黑客专用的Linux操作系统。 ▍1. Kali Linux Kali Linux是最著名的Linux发行版&#xff0c;用于道德黑客和渗透测试。Kali Linux由Offensive Security开发&…

哨兵架构redisCluster-Redis(五)

上篇文章介绍了主从架构以及lua脚本。 主从架构&lua脚本-Redis&#xff08;四&#xff09;https://blog.csdn.net/ke1ying/article/details/131159229 Sentinel集群 主从的搭建我们已经完成&#xff0c;但如果主节点宕机&#xff0c;这时候导致整个redis服务不可用怎么办…

打造智能生活方式

2个互联网工具与你分享 分享一&#xff1a; 随记单词是一款功能强大的单词记忆和管理应用程序。它为用户提供了便捷的学习工具和智能化的记忆方式&#xff0c;帮助用户轻松有效地记忆和掌握单词。 随记单词的特点之一是个性化记忆计划。用户可以根据自己的学习进度和需求&am…

【LeetCode热题100】打卡第21天:最小路径和爬楼梯

文章目录 【LeetCode热题100】打卡第21天&#xff1a;最小路径和&爬楼梯⛅前言 最小路径和&#x1f512;题目 爬楼梯&#x1f512;题目&#x1f511;题解 【LeetCode热题100】打卡第21天&#xff1a;最小路径和&爬楼梯 ⛅前言 大家好&#xff0c;我是知识汲取者&#…

牛客网基础语法41~50题

牛客网基础语法41~50题&#x1f618;&#x1f618;&#x1f618; &#x1f4ab;前言&#xff1a;今天是咱们第五期刷牛客网上的题目。 &#x1f4ab;目标&#xff1a;熟练用数学知识来解决编程问题&#xff0c;会利用每种循环。 &#x1f4ab;鸡汤&#xff1a;压抑了&#xff0…

什么是远程工具,远程工具推荐

在当今数字化时代&#xff0c;远程工作正在变得越来越普遍。这种趋势不仅使企业管理更加便利&#xff0c;节省了时间和资源&#xff0c;同时也使员工更加自由和灵活。许多远程工作都需要使用到远程工具。本文将对远程工具进行简介和阐述。 什么是远程工具 远程工具是一种数字…

互斥锁实现线程互斥(嵌入式学习)

互斥锁实现线程互斥 互斥锁的概念互斥锁的函数示例代码 互斥锁的概念 互斥锁&#xff08;Mutex&#xff09;是一种用于多线程编程的同步原语&#xff08;synchronization primitive&#xff09;&#xff0c;用于实现线程之间的互斥访问共享资源。互斥锁提供了一种机制&#xff…

wsl安装ubuntu并设置gnome图形界面详细步骤(win11+ubuntu18)

0.前言 wsl确实是个好东西&#xff0c;不过之前配了好几次都没有成功&#xff0c;因为wsl本身确实是有bug。当时配的时候查到GitHub上的一个issue还没被修好。现在重新配一下。 我的环境是Windows11家庭版。区别于win10&#xff0c;win11安装完默认就是wsl2。 1.下载 首先打…

[RPC]:Feign远程调用

文章目录 摘要1 RPC框架-Feign1.1 什么是Feign1.2 Feign解决的问题1.2.1 使用RestTemplate发送远程调用代码1.2.1.1 项目示例调用链路1.2.1.2 代码逻辑1.2.1.3 代码实现1.2.1.4 存在的问题 1.3 Feign如何使用1.3.1 使用逻辑1.3.2 引入依赖1.3.3 启动类添加注释开启feign功能 摘…

3.数据操作

SQL句子中语法格式提示&#xff1a; 1.中括号&#xff08;[]&#xff09;中的内容为可选项&#xff1b; 2.[&#xff0c;...]表示&#xff0c;前面的内容可重复&#xff1b; 3.大括号&#xff08;{}&#xff09;和竖线&#xff08;|&#xff09;表示选择项&#xff0c;在选择…

网络安全|渗透测试入门学习,从零基础入门到精通—渗透中的开发语言

目录 前面的话 开发语言 1、html 解析 2、JavaScript 用法 3、JAVA 特性 4、PHP 作用 PHP 能做什么&#xff1f; 5、C/C 使用 如何学习 前面的话 关于在渗透中需要学习的语言第一点个人认为就是可以打一下HTML&#xff0c;JS那些基础知识&#xff0c;磨刀不误砍柴…

键盘按键事件 通过键盘上下左右按键移动界面上图标

#main.c文件 #include “keyevent.h” #include int main(int argc, char *argv[]) { QApplication a(argc, argv); KeyEvent w; w.show(); return a.exec();} #include “keyevent.h”//头文件 #ifndef KEYEVENT_H #define KEYEVENT_H #include #include #include cl…

机器学习、计算机视觉和深度学习

机器学习、计算机视觉和深度学习 1 什么是机器学习&#xff1f;2 机器学习的类型3 什么是计算机视觉&#xff1f;4 计算机视觉的机器学习应用5 总结参考 这篇博客将简要介绍&#xff1a;机器学习和用于计算机视觉的机器学习。 想象一下&#xff1a;你可以使用人脸检测算法在图…