网络编程之 信号捕捉器(函数指针与回调函数)(1)

简介: 接着我们的信号说下去 之前博主给大家分享到了信号的概念和初步介绍signal函数的形式后就没有继续往下介绍了,实在是因为时间不够,那个时候博主还要上课,现在博主放假了就好好给大家分享一下如何注册信号捕捉,以及信号捕捉器的妙用。

接着我们的信号说下去    

之前博主给大家分享到了信号的概念和初步介绍signal函数的形式后就没有继续往下介绍了,实在是因为时间不够,那个时候博主还要上课,现在博主放假了就好好给大家分享一下如何注册信号捕捉,以及信号捕捉器的妙用。

 

  利用信号来处理子进程的回收是非常方便和高效的,因为所有的工作你都可以交给内核,当子进程终止时,会发出一个信号,一旦你注册的信号捕捉器捕捉到了这个信号,那么就可以去回调自己的函数(处理处理子进程的函数),去回收子进程了。

在引入函数指针和回调函数之前我们先介绍一下alarm()闹钟函数!


alarm()闹钟函数

alarm:设置定时器(闹钟)。在指定秒数(seconds)后,内核会给当前进程发送14)SIGALRM信号(前面的博客有所介绍)。进程收到该信号,默认动作终止。

20191101165529436.png

#include<unistd.h>
unsigned int alarm(unsigned int seconds);
返回值: 返回0或剩余的秒数,这个函数调用不存在失败!!!!
每个进程有且只有一个定时器!

20191101170048255.png

用大白话来描述上述图片就是:你在里面传入的正整数参数就是你要定时的秒数,在此期间不管你的进程处于何种状态(就绪、运行、挂起(阻塞、暂停)、终止、僵尸.)alarm都会进行计时,当计时完成就会发送 14)SIGALRM信号------>进程收到该信号,默认动作终止(也就是终止当前进程不做任何处理。)

       但是如果你注册了信号捕捉器那么就会进行函数回调,在信号捕捉器接收到14号信号之后就回调你自己定义的函数,这样你的程序不但不会终止,而且还能进行子进程的回收。


取消定时器: alarm(0),返回旧闹钟余下秒数。


小补充:20191101171406179.png

       除了alarm()之外还有一个计时函数,setitimer()---->精确度更高,可代替alarm函数。精度微秒us,可以实现周期定时。各位朋友能掌握alarm()已经足够了,如果想要了解更多的可以自行百度,博主在这里就不在介绍了。

你说那么多都还没有讲到信号捕捉器啊!!!!

莫急,在正式开始信号捕捉起之前我们还需要了解一下函数指针和回调函数(这个是必须要学会的,不然后面的内容你是看不懂的,这可不是博主在乱说所以,骚年加油吧!!

20191101171329618.png

好啦,博主在这里举一个小例子来给大家讲一下(极速入门!)。

请看代码!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Function_pointer(const void *a, const void *b) {
  printf("成功调用 函数指针啦,你好骚气哦! \n");
  return 1;
}
int main(void) {
  int x = 10;
  int y = 20;
  //函数指针的定义 把函数声明移过来,把函数名改成 (* 函数指针名)
  int(*fp)(const void *, const void *);
  /*贝尔实验室的C和UNIX的开发者采用第1种形式,而伯克利的UNIX推广者却采用第2
  种形式ANSI C 兼容了两种方式*/
  fp = &Function_pointer; //
  (*fp)(&x, &y); //第1种,按普通指针解引的放式进行调用,(*fp) 等同于compare_int
  fp(&x, &y); //第2种 直接调用
  system("pause");
  return 0;
}


2019110118364763.png

下面就让我们理一理函数指针吧。

首先大家要明白函数本身就是地址是一个指针。

那么肯定就可以有一个指针来指向我们的函数了,这个指针就是我们所说的函数指针(这个我们宿舍的学霸(刘老板)都有点懵比),那么我们看看函数指针有啥特别的。

在子函数的声明和正常的函数是一样的!!!

想要快速创建一个函数指针就最佳方法就是把函数声明ctrl+c、ctrl+v复制下来,然后把函数的名字改成 (* 自定义的函数指针名),就好了。里面的形参你想加变量名就加变量名,纯属个人喜好。

接下来只需要让你自定义的函数指针名指向你之前的函数声明即可(18行)。

调用有两种方法,见代码。这样就是我们的函数指针了

大家好好看我上面的实例看懂函数指针应该是不难了,接下来我们就来看看回调函数吧。(不要急,书上不是说了吗,这两个不懂的话是看不懂后面的内容的,这可不是博主不想马上讲解信号捕捉器哟

我们的函数指针是一个指针变量,那么它能不能作为一个函数的参数呢?答案时是肯定的。在我们的操作系统源码,以及在linux中许多系统调用中,有许多这样的函数我们等下要接触到的 信号捕捉器就会用到,但是我们先来一个引入吧!!


观看博客的小可爱:我去,博主,你咋一直在搞引入啊?,我要直接看回调!!

博主:我也是为了大家好呀.

观看博客的小可爱:那好吧最后一次了。

博主:好的

    好了,回到正式上来,该引入我们的回调函数了(需要把之前的函数小小的改造一下)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Function_pointer(const void *a, const void *b) {
    printf("成功回调 Function_pointer 啦,你好骚气哦! \n");
    int *a1 = (int *)a;
    int *b1 = (int *)b;
    return *a1 - *b1;
}
int main(void) {
  int x = 10;
  int y = 20;
  //函数指针的定义 把函数声明移过来,把函数名改成 (* 函数指针名)
  int(*fp)(const void *x, const void *y);
  /*贝尔实验室的C和UNIX的开发者采用第1种形式,而伯克利的UNIX推广者却采用第2
  种形式ANSI C 兼容了两种方式*/
  fp = &Function_pointer; //
  //(*fp)(&x, &y); //第1种,按普通指针解引的放式进行调用,(*fp) 等同于compare_int
  //fp(&x, &y); //第2种 直接调用
  int arr[] = { 2, 10, 30, 1, 11, 8, 7, 111, 520 };
  qsort(arr, sizeof(arr) / sizeof(int), sizeof(int), Function_pointer);
  for (int i = 0; i < sizeof(arr) / sizeof(int); i++) {
    printf(" %d", arr[i]);
  }
  system("pause");
  return 0;
}

20191101190023621.png

讲解:

     回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当 这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调 用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

    我们C语言库函数中就有一个典型的案例:qsort 函数(就是我们的26行),
  void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
第一个参数: void *base, size_t num:
        --->泛型指针,这样就能接受任何值
第二个参数: size_t width:
        --->大小
第三个参数:int (__cdecl *compare )(const void *elem1, const void *elem2 )
    -->看到了吧 函数指针"__cdecl这个不用管,在你声明函数的时候系统给你处理好了"

希望大家通过上面的代码能明白回调函数。

---->其实就是,在函数里调用函数去执行你要执行的那个函数。(希望没把大家搞晕。)我还特意把我们之前的函数指针调用给注释了哟,哈哈哈!


     前戏已经做足相信大家也已经迫不及待了吧,哈哈,我们的信号捕捉器正式开!!!

我们已经了解到了 信号、alarm()闹钟函数、函数指针和回调函数了,再看之前的图片。

20191101191515908.png

是不是不在瑟瑟发抖啦。哈哈哈,其实只要你认真看了我之前的信号捕捉器开端篇,书上给你介绍的宏(有点没说清楚),理解也会更深刻!

再给出我们之前的signal()函数

#include<signal.h>
void (*signal)(int signo, void(*func)(int)))(int);
函数名: signal
参数: int signo, void(* func)(int)
返回类型:参数类型为 int 型, 返回 void 型函数指针。
--->为了在产生信号时调用, 返回之前注册的函数指针
现在看这个是不是有些感觉了,哈哈。

调用上述函数时,第一个参数的信息,就是博主前面的博客提到的那些信号类型。

第二个参数为特殊情况下要调用的函数的地址值(指针==函数名),当发生第一个参数的情况下,就会调用第二个参数所指向的函数了。


下面给出signal()函数中用到的一些信号(部分),更多的可以在我的信号的介绍博客看到详细的信号处理。


SIGALRM: 已到通过调用 alarm 函数注册的时间

SIGINT:输入 CTRL+C

SIGCHIL:子进程终止

了解到这些我们就能去看一看书本中的代码了!!!!

20191101194324830.png

下面是更加详细的解释,相信大家也能看懂了吧。

20191101194455578.png

博主主要是为了让大家能明白书中的信号捕捉器而讲了那么多,也相信大家已经明白了。所以博主还要告诉大家一件事,signal()函数用到的不多,更多的是另一个函数来处理信号那就是:sigaction()函数。


朋友们坚持不!博主保证,这是最后一个了

网络编程之 信号捕捉器(函数指针与回调函数)(2)https://developer.aliyun.com/article/1414739?spm=a2c6h.13148508.setting.14.4d4d4f0erzCTC6

目录
相关文章
|
3月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GRU网络的MQAM调制信号检测算法matlab仿真,对比LSTM
本研究基于MATLAB 2022a,使用GRU网络对QAM调制信号进行检测。QAM是一种高效调制技术,广泛应用于现代通信系统。传统方法在复杂环境下性能下降,而GRU通过门控机制有效提取时间序列特征,实现16QAM、32QAM、64QAM、128QAM的准确检测。仿真结果显示,GRU在低SNR下表现优异,且训练速度快,参数少。核心程序包括模型预测、误检率和漏检率计算,并绘制准确率图。
114 65
基于GRU网络的MQAM调制信号检测算法matlab仿真,对比LSTM
|
12月前
指针(5)---回调函数
指针(5)---回调函数
43 0
|
12月前
|
编译器 C语言
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。(下)
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。
85 0
|
7月前
|
C++
指针中的回调函数与qsort的深度理解与模拟
本文详细介绍了回调函数的概念及其在计算器简化中的应用,以及C++标准库函数qsort的原理和使用示例,包括冒泡排序的模拟实现。
46 1
|
7月前
魔法指针 之 函数指针 回调函数
魔法指针 之 函数指针 回调函数
32 0
|
10月前
|
机器学习/深度学习 边缘计算 量子技术
ICML 2024:信号表征指数级强、内存节省超35%,量子隐式表征网络来了
【7月更文挑战第6天】QIREN,量子隐式表征网络,借助量子计算增强信号处理能力,内存效率提升35%以上。该技术旨在改进高频信号建模,提升图像和音频处理任务的性能,同时在资源受限环境下减少内存需求。尽管面临量子技术成熟度和训练复杂性的挑战,QIREN为机器学习开辟了新途径。[论文链接: https://arxiv.org/abs/2406.03873]**
135 3
|
11月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
12月前
|
算法 搜索推荐 C语言
c函数指针与回调函数
c函数指针与回调函数
75 2
|
11月前
|
机器学习/深度学习 网络协议 C语言
程序技术好文:网络编程中的SIGPIPE信号
程序技术好文:网络编程中的SIGPIPE信号
187 0
|
11月前
|
机器学习/深度学习 算法 语音技术
基于语音信号MFCC特征提取和GRNN神经网络的人员身份检测算法matlab仿真
**语音识别算法概览** MATLAB2022a中实现,结合MFCC与GRNN技术进行说话人身份检测。MFCC利用人耳感知特性提取语音频谱特征,GRNN作为非线性映射工具,擅长序列学习,确保高效识别。预加重、分帧、加窗、FFT、滤波器组、IDCT构成MFCC步骤,GRNN以其快速学习与鲁棒性处理不稳定数据。适用于多种领域。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等