Webserver(2.6)信号

目录

  • 信号的概念
  • 信号相关的函数
    • kill
    • raise
    • abort
    • alarm
      • 1s钟电脑能数多少个数?
    • setitimer
      • 过3s以后,每隔2s定时一次
  • 信号捕捉函数
    • signal
    • sigaction
  • 信号集
    • sigprocmask
      • 编写一个程序,把所有的常规信号未决状态打印到屏幕
  • sigchld信号

信号的概念

比如ctrl+c会进程发送一个中断信号
硬件发生异常,比如被0除,野地址
系统状态变化,alarm定时器、超过cpu时间片,子进程退出
kill命令

信号相关的函数

kill

给某个进程pid发送某个信号sig

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>int main(){pid_t pid=fork();if(pid==0){//子进程for(int i=0;i<5;i++){printf("child process\n");sleep(1);}}else if(pid>0){//父进程printf("parent process\n");sleep(2);printf("kill child process now\n");kill(pid,SIGINT);}return 0;
}

在这里插入图片描述

raise

给当前进程发送信号(kill可以给任何进程)

abort

alarm

设置定时器
开始倒计时,当倒计时为0时终止当前进程
每一个进程只有唯一的一个定时器,如果第二次出现alarm(重新倒计时),返回值是上一个剩余的时间
该函数不阻塞

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>int main(){int secondes=alarm(5);printf("seconds:%d\n",secondes);sleep(2);secondes=alarm(10);printf("seconds:%d\n",secondes);while(1){}return 0;
}

在这里插入图片描述

1s钟电脑能数多少个数?

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>int main(){alarm(1);int i=0;while(1){printf("%i\n",i++);}return 0;
}

在这里插入图片描述
实际上更多,因为在这边写到终端上i/o缓冲也占了时间,就是没全部打印出来,就已经显示闹钟了
在这里插入图片描述
有五百万次
在这里插入图片描述
实际的时间=内核时间+用户时间+消耗的时间
进行文件IO操作的时候比较浪费时间

alarm是自然计时,不受sleep的影响

setitimer

设置定时器,且精度更高,到微秒
每个阶段发送信号

过3s以后,每隔2s定时一次

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>int main(){struct itimerval new_value;//设置间隔的时间new_value.it_interval.tv_sec=2;new_value.it_interval.tv_usec=0;//设置延迟的时间,3s之后开始第一次定时new_value.it_value.tv_sec=3;new_value.it_value.tv_usec=0;int ret=setitimer(ITIMER_REAL,&new_value,NULL);printf("定时器开始了...\n");if(ret==-1){perror("setitimer");exit(0);}getchar();return 0;
}

信号捕捉函数

signal

sigkill(9号信号) sigstop不能被捕捉,不能被忽略

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>int main(){//注册信号捕捉signal(SIGALRM,SIG_IGN);struct itimerval new_value;//设置间隔的时间new_value.it_interval.tv_sec=2;new_value.it_interval.tv_usec=0;//设置延迟的时间,3s之后开始第一次定时new_value.it_value.tv_sec=3;new_value.it_value.tv_usec=0;int ret=setitimer(ITIMER_REAL,&new_value,NULL);printf("定时器开始了...\n");if(ret==-1){perror("setitimer");exit(0);}getchar();return 0;
}

捕捉到信号之后,信号忽略,原先终止,现在啥都不做
在这里插入图片描述

signal(SIGALRM,SIG_DFL);

换成默认,默认就是终止进程,倒计时结束就结束
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

sigaction

SIGKILL和SIGSTOP不能被忽略也不能被捕捉

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>void myalarm(int num){printf("捕捉到了信号的编号是:%d\n",num);printf("xxxx\n");
}int main(){struct sigaction act;act.sa_flags=0;act.sa_handler=myalarm;sigemptyset(&act.sa_mask);//清空零时阻塞信号集//注册信号捕捉sigaction(SIGALRM,&act,NULL);struct itimerval new_value;//设置间隔的时间new_value.it_interval.tv_sec=2;new_value.it_interval.tv_usec=0;//设置延迟的时间,3s之后开始第一次定时new_value.it_value.tv_sec=3;new_value.it_value.tv_usec=0;int ret=setitimer(ITIMER_REAL,&new_value,NULL);printf("定时器开始了...\n");if(ret==-1){perror("setitimer");exit(0);}while(1);return 0;
}

每两秒捕捉一次定时器的alarm信号,然后调用回调函数
在这里插入图片描述

信号集

#include<signal.h>
#include<stdio.h>int main(){//创建一个信号集sigset_t set;//清空信号集的内容sigemptyset(&set);//判断sigint是否在信号集set里int ret=sigismember(&set,SIGINT);if(ret==0){printf("SIGINT 不阻塞\n");}else if(ret==1){printf("SIGINT 阻塞\n");}//添加几个信号到信号集中sigaddset(&set,SIGINT);sigaddset(&set,SIGQUIT);//判断sigint是否在信号集set里ret=sigismember(&set,SIGINT);if(ret==0){printf("SIGINT 不阻塞\n");}else if(ret==1){printf("SIGINT 阻塞\n");}//判断sigquit是否在信号集set里ret=sigismember(&set,SIGQUIT);if(ret==0){printf("SIGQUIT 不阻塞\n");}else if(ret==1){printf("SIGQUIT 阻塞\n");}//从信号集中删除一个信号sigdelset(&set,SIGQUIT);//判断sigquit是否在信号集set里ret=sigismember(&set,SIGQUIT);if(ret==0){printf("SIGQUIT 不阻塞\n");}else if(ret==1){printf("SIGQUIT 阻塞\n");}return 0;
}

在这里插入图片描述

sigprocmask

对内核的信号集进行操作

编写一个程序,把所有的常规信号未决状态打印到屏幕

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>int main(){//设置2号、3号信号阻塞sigset_t set;sigemptyset(&set);//将2号和3号信号添加到信号集中sigaddset(&set,SIGINT);sigaddset(&set,SIGQUIT);//修改内核中的阻塞信号sigprocmask(SIG_BLOCK,&set,NULL);while(1){//获取当前的未决信号集的数据sigset_t pendingset;sigemptyset(&pendingset);sigpending(&pendingset);//遍历前32位for(int i=1;i<=32;i++){if(sigismember(&pendingset,i)==1){printf("1");}else if(sigismember(&pendingset,i)==0){printf("0");}else{perror("sigismember");exit(0);}}printf("\n");}return 0;
}

在这里插入图片描述
在这里插入图片描述

未决信号集和阻塞信号集

sigchld信号

子进程终止时,产生
子进程接收到SIGSTOP信号(暂停进程,不是停止)
子进程处于停止态(暂停),接受到SIGCONT唤醒时

以上三种情况,内核会发送SIGCHLD信号给父进程,父进程默认忽略该信号。
用于解决僵尸进程问题,不需要父进程来wait,子进程结束之后发送信号。
然后父进程捕捉该信号,再去调用pid来wait回收资源,之后父进程继续做自己的事情。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include<sys/stat.h>int main(){//创建一些子进程pid_t pid;for(int i=0;i<20;i++){pid=fork();if(pid==0){break;}}if(pid>0){//父进程while(1){printf("parent process pid:%d\n",getpid());sleep(2);}}else if(pid==0){//子进程printf("child process pid:%d\n",getpid());}return 0;
}

创建20个子进程,产生了僵尸进程
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include<sys/stat.h>
#include <signal.h>void myFun(int num){printf("捕捉到的信号:%d\n",num);
}int main(){//创建一些子进程pid_t pid;for(int i=0;i<20;i++){pid=fork();if(pid==0){break;}}if(pid>0){//父进程//捕捉子进程死亡时发送的sigchld信号struct sigaction act;act.sa_flags=0;act.sa_handler=myFun;sigemptyset(&act.sa_mask);sigaction(SIGCHLD,&act,NULL);while(1){printf("parent process pid:%d\n",getpid());sleep(2);}}else if(pid==0){//子进程printf("child process pid:%d\n",getpid());}return 0;
}

子进程死了之后,就捕捉到了17号信号(SIGCHLD)
在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include<sys/stat.h>
#include <signal.h>
#include<sys/wait.h>void myFun(int num){printf("捕捉到的信号:%d\n",num);//回收子进程PCB的资源while(1){int ret=waitpid(-1,NULL,WNOHANG);if(ret>0){printf("child die,pid=%d\n",ret);}else if(ret==0){//说明还有子进程活着break;}else if(ret==-1){//所有子进程结束了break;}}}int main(){//创建一些子进程pid_t pid;for(int i=0;i<20;i++){pid=fork();if(pid==0){break;}}if(pid>0){//父进程//捕捉子进程死亡时发送的sigchld信号struct sigaction act;act.sa_flags=0;act.sa_handler=myFun;sigemptyset(&act.sa_mask);sigaction(SIGCHLD,&act,NULL);while(1){printf("parent process pid:%d\n",getpid());sleep(2);}}else if(pid==0){//子进程printf("child process pid:%d\n",getpid());}return 0;
}

全部被捕捉并处理,没有僵尸进程
在这里插入图片描述
还有个问题就是,如果在捕捉信号注册还没完成的时候,子进程就已经全部结束了,那这个时候就不会再发生sigchld了,那就不会被回收了。
如何让信号注册结束在子进程之前
设置阻塞信号集,信号注册完之前,子进程阻塞,信号发不了。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include<sys/stat.h>
#include <signal.h>
#include<sys/wait.h>void myFun(int num){printf("捕捉到的信号:%d\n",num);//回收子进程PCB的资源while(1){int ret=waitpid(-1,NULL,WNOHANG);if(ret>0){printf("child die,pid=%d\n",ret);}else if(ret==0){//说明还有子进程活着break;}else if(ret==-1){//所有子进程结束了break;}}}int main(){//提前设置好阻塞信号集,阻塞sigchld因为有可能子进程很快结束,父进程还没有注册完sigset_t set;sigemptyset(&set);sigaddset(&set,SIGCHLD);sigprocmask(SIG_BLOCK,&set,NULL);//创建一些子进程pid_t pid;for(int i=0;i<20;i++){pid=fork();if(pid==0){break;}}if(pid>0){//父进程//捕捉子进程死亡时发送的sigchld信号struct sigaction act;act.sa_flags=0;act.sa_handler=myFun;sigemptyset(&act.sa_mask);sigaction(SIGCHLD,&act,NULL);//注册完信号捕捉以后,解除阻塞sigprocmask(SIG_UNBLOCK,&set,NULL);while(1){printf("parent process pid:%d\n",getpid());sleep(2);}}else if(pid==0){//子进程printf("child process pid:%d\n",getpid());}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AprilTag在相机标定中的应用简介

1. AprilTag简介 相机标定用的标靶类型多样,常见的形式有棋盘格标靶和圆形标靶。今天要介绍的AprilTag比较特别,它是一种编码形式的标靶。其官网为AprilTag,它是一套视觉基准系统,包含标靶编解码方法(Tag生成)和检测算法(Tag检测),可用于AR、机器人、相机标定等领域。…

Qt报错QOCI driver not loaded且QOCI available的解决方法

参考 Linux Qt 6安装Oracle QOCI SQL Driver插件&#xff08;适用WSL&#xff09; 安装 QOCI 插件完成后运行 Qt 项目报错&#xff1a; qt.sql.qsqldatabase: QSqlDatabase: QOCI driver not loaded qt.sql.qsqldatabase: QSqlDatabase: available drivers: QMIMER QPSQL QODBC…

【MySQL】 穿透学习数据库理论与知识剖析

前言&#xff1a;本节内容讲述一些数据库的基本概念。 第一个部分就是数据库相关的概念&#xff0c; 比如什么是数据库&#xff0c; 如何理解mysqld以及mysql。第二部分理解数据库和表在系统层面的形式。 第三部分就是mysql的一些操作分类。 第四部分就是数据库的插件配置这些。…

Web Broker(Web服务应用程序)入门教程(1)

1、介绍 Web Broker 组件&#xff08;位于工具面板的“Internet”选项卡中&#xff09;可以帮助您创建与特定统一资源标识符&#xff08;URI&#xff09;相关联的事件处理程序。当处理完成后&#xff0c;您可以通过编程方式构建 HTML 或 XML 文档&#xff0c;并将它们传输给客…

网络安全法详细介绍——爬虫教程

目录 [TOC](目录)一、网络安全法详细介绍1. 网络安全法的主要条款与作用2. 网络安全法与爬虫的关系3. 合法使用爬虫的指南 二、爬虫的详细教程1. 准备环境与安装工具2. 使用requests库发送请求3. 解析HTML内容4. 使用robots.txt规范爬虫行为5. 设置请求间隔6. 数据清洗与存储 三…

25国考照片处理器使用流程图解❗

1、打开“国家公务员局”网站&#xff0c;进入2025公务员专题&#xff0c;找到考生考务入口 2、点击下载地址 3、这几个下载链接都可以 4、下载压缩包 5、解压后先看“使用说明”&#xff0c;再找到“照片处理工具”双击。 6、双击后会进入这样的界面&#xff0c;点击&…

Go 语言之搭建通用 Web 项目开发脚手架

Go 语言之搭建通用 Web 项目开发脚手架 MVC 模式 MVC 模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。这种模式用于应用程序的分层开发。 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑&…

江协科技STM32学习- P34 I2C通信外设

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

windows在两台机器上测试 MySQL 集群实现实时备份

在两台机器上测试 MySQL 集群实现实时备份的基本步骤&#xff1a; 一、环境准备 机器配置 确保两台机器&#xff08;假设为服务器 A 和服务器 B&#xff09;能够互相通信&#xff0c;例如它们在同一个局域网内&#xff0c;并且开放了 MySQL 通信所需的端口&#xff08;默认是 …

【MIT-OS6.S081笔记1】xv6环境搭建

最近开始做一个操作系统的神课MIT-OS6.S081&#xff0c;我做的是老版本的2020版本的&#xff0c;环境使用的是VirtualBox的Ubuntu系统&#xff0c;在这里记录一下学习的过程。首先需要搭建一下环境&#xff0c;参考官网Tools Used in 6.S081&#xff0c;这个知乎文章也写得很好…

深度学习基础—语言模型和序列生成

引言 深度学习基础—循环神经网络&#xff08;RNN&#xff09;https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 上…

kdd比赛方案

解决方案概述 采用两阶段的方法来解决比赛任务。在第一阶段&#xff0c;采用与 SciBERT 集成的跨编码器模型来确定源论文是否是最重要的参考文献之一。在第二阶段&#xff0c;利用了从目标和源论文中得出的特征&#xff0c;以及第一阶段的输出&#xff0c;输入到几个二进制分类…

抖音Ai图文故事号,AI一键生成故事图片变现,涨粉变现超快!

今天分享2个简单好上手&#xff0c;可批量复制&#xff0c;出单超快的Ai项目&#xff0c;那就是AI绘画壁纸号Ai图文故事号。 在抖音、小红书上&#xff0c;壁纸号火的一塌糊涂&#xff0c;新号3天涨粉1500&#xff0c;变现利润超过了4位数 壁纸看起来平平无奇&#xff0c;市场需…

面试题:JVM(三)

1. 面试题 说一说JVM的内存结构是什么样子的,每个区域放什么&#xff0c;各有什么特点&#xff1f;&#xff08;快手、搜狐&#xff09; JVM的内存结构&#xff0c;及各个结构的内容。&#xff08;vivo&#xff09; 详细介绍一下内存结构&#xff08;墨迹天气&#xff09; JVM…

ELK的ElasticStack语法

目录 传送门前言一、索引&#xff08;数据库&#xff09;1、创建索引2、获取索引3、删除索引 二、文档&#xff08;Row行&#xff09;1、创建文档2、获取文档3、修改文档4、删除文档5、高级查询&#xff08;精辟&#xff09;条件查询分页、指定、排序、范围查询全文检索、分组查…

leaflet绘制圆形方案

电子围栏绘制方案: 采用leaflet绘制电子围栏 可以看对应api文档 。原生是英文,所以要重定义,直接覆盖下面的 leaflet.draw-cn.js 文件L.drawLocal = {draw: {toolbar: {// #TODO: this should be reorganized where actions are nested in actions// ex: actions.undo or a…

新能源汽车空调压缩机:科技驱动的冷暖核心

一、新能源汽车空调系统概述 新能源汽车空调系统在车辆中起着至关重要的作用&#xff0c;它直接影响着驾乘人员的舒适度。新能源汽车空调系统主要由制冷系统、加热系统、送风系统、操纵控制系统和空气净化系统等组成。 制冷系统通常由电动压缩机、冷凝器、压力传感器、电子膨…

Javaweb梳理8——数据库设计

Javaweb梳理8——数据库设计 8 数据库设计8.1 数据库设计简介8.2 表关系(一对多)8.3 表关系&#xff08;多对多&#xff09;8.4 表关系&#xff08;一对一&#xff09; 8 数据库设计 8.1 数据库设计简介 软件的研发步骤 数据库设计概念 数据库设计就是根据业务系统的具体需…

IDEA - 快速去除 mapper.xml 黄色警告线和背景色----简化版

1.打开设置 2.去掉黄色警告线设置 3.去掉背景色设置 4.示范图

vue3中使用vue-diff工具来比较数据差异

1.安装vue-diff npm i vue-diff 2.main.js中全局注册 import VueDiff from "vue-diff"; import "vue-diff/dist/index.css";app.use(VueDiff) 3.使用 <template><div class"contain-page"><el-scrollbar height"100vh&…