Linux第89步_了解异步通知及其结构和函数

news2024/11/26 15:37:29

1、了解“异步通知”

“异步通知”的核心就是信号。信号是采用软件模拟的“中断”,它由“驱动程序”主动向“应用程序”发送信号,并报告自己可以访问了,“应用程序”收到信号以后,就从“驱动设备”中读取或者写入数据。整个过程就相当于“应用程序”收到了“驱动程序”发送过来了的一个中断,然后由“应用程序”去响应这个中断,在整个处理过程中,“应用程序”并没有去查询“驱动设备”是否可以访问,而是由“驱动设备”主动报告给“应用程序”的。

“异步通知”和处理器“处理硬件中断”有点相似。硬件中断是处理器提供的一种异步机制。中断被配置好以后,处理器就去处理其他的事情了。当中断发生时,就会调用与之对应的中断服务函数,处理具体的事务。

2、信号定义

在“arch/xtensa/include/uapi/asm/signal.h”文件中,定义了Linux所支持的所有信号,这些信号如下所示:

#define  SIGHUP       1     /* 终端挂起或控制进程终止 */

#define  SIGINT       2     /* 终端中断(Ctrl+C组合键) */

#define  SIGQUIT      3     /* 终端退出(Ctrl+\组合键) */

#define  SIGILL       4     /* 非法指令 */

#define  SIGTRAP      5     /* debug使用,有断点指令产生 */

#define  SIGABRT      6     /* 由abort(3)发出的退出指令 */

#define  SIGIOT       6     /* IOT指令 */

#define  SIGBUS       7     /* 总线错误 */

#define  SIGFPE       8     /* 浮点运算错误 */

#define  SIGKILL      9     /* 杀死、终止进程 */

#define  SIGUSR1      10    /* 用户自定义信号1 */

#define  SIGSEGV      11    /* 段违例(无效的内存段) */

#define  SIGUSR2      12    /* 用户自定义信号2 */

#define  SIGPIPE      13    /* 向非读管道写入数据 */

#define  SIGALRM      14    /* 闹钟 */

#define  SIGTERM      15    /* 软件终止 */

#define  SIGSTKFLT    16    /* 栈异常 */

#define  SIGCHLD      17    /* 子进程结束 */

#define  SIGCONT      18    /* 进程继续 */

#define  SIGSTOP      19    /* 停止进程的执行,只是暂停 */

#define  SIGTSTP      20    /* 停止进程的运行(Ctrl+Z组合键) */

#define  SIGTTIN      21    /* 后台进程需要从终端读取数据 */

#define  SIGTTOU      22    /* 后台进程需要向终端写数据 */

#define  SIGURG       23    /* 有"紧急"数据 */

#define  SIGXCPU      24    /* 超过CPU资源限制 */

#define  SIGXFSZ      25    /* 文件大小超额 */

#define  SIGVTALRM    26    /* 虚拟时钟信号 */

#define  SIGPROF      27    /* 时钟信号描述 */

#define  SIGWINCH     28    /* 窗口大小改变 */

#define  SIGIO        29    /* 可以进行输入/输出操作 */

#define  SIGPOLL SIGIO

/* #define SIGLOS 29 */

#define  SIGPWR       30    /* 断点重启 */

#define  SIGSYS       31    /* 非法的系统调用 */

#define  SIGUNUSED    31    /* 未使用信号 */

这些信号就相当于中断号,不同的中断号代表了不同的中断,不同的中断所做的处理不同,因此,“驱动程序”通过向“应用程序”发送不同的信号来实现不同的功能。

3、应用程序中的信号处理

信号处理函数原型:

typedef void (*sighandler_t)(int)

sighandler_t signal(int signum, sighandler_t handler)

在应用程序中,使用signal()函数来设置指定信号的处理函数

signum:要设置处理函数的信号,

handler:信号的处理函数。

返回值:若设置成功,则返回信号的前一个处理函数;若设置失败,则返回 SIG_ERR。

举例:

打开终端

输入“ls回车”,列举“/home/zgq/”的子目录

输入“cd linux/回车”,切换到“/home/zgq/linux/”的目录

输入“ls回车”,列举“/home/zgq/linux/”的子目录

输入“cd Linux_Drivers/回车”,切换到“/home/zgq/linux/Linux_Drivers/”的目录

输入“ls回车”,列举“/home/zgq/linux/Linux_Drivers/”的子目录

输入“mkdir signaltest回车”,创建“/home/zgq/linux/signaltest/”目录

输入“cd signaltest/回车”,切换到“/home/zgq/linux/signaltest/”的目录

输入“vim signaltest.c”

输入signaltest.c程序如下:

#include <stdlib.h>

#include <stdio.h>

#include <signal.h>

//信号的处理函数

void sigint_handler(int num)

{

printf("\r\nSIGINT signal!\r\n");

exit(0);

}

int main(void)

{

signal(SIGINT, sigint_handler);

//设置SIGINT信号的处理函数sigint_handler()

/*按下键盘上的“CTRL+C”组合键,会向当前正在占用终端的应用程序发出“SIGINT信号”,SIGINT信号默认的动作是关闭当前应用程序*/

while(1);

return 0;

}

按下“ESC键”,输入“:wq”,保存退出

编译:

gcc signaltest.c -o signaltest

运行程序:

输入“./signaltest回车”,打开signaltest这个应用程序;

若发送“SIGINT信号”,则按下键盘上的“CTRL+C”组合键

4、驱动程序中的信号处理

#include <linux/fs.h> //使能fasync_struct结构

fasync_struct结构体如下:

struct fasync_struct {

spinlock_t  fa_lock; /* 自旋锁fa_lock */

int magic;

int fa_fd;

struct fasync_struct  *fa_next; /* singly linked list */

struct file *fa_file;

struct rcu_head  fa_rcu;

};

设备驱动中file_operations操作集中的fasync()函数格式如下:

int (*fasync) (int fd, struct file *filp, int on)

fasync_helper()函数原型如下:

int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)

//fasync_helper()函数的前3个参数和fasync()函数一样

//fasync_helper()函数的第4个参数fasync_struct结构体指针变量。

/*当“应用程序”通过“fcntl(fd,F SETFL, flags|FASYNC)”改变fasync标记的时候,“驱动程序” file_operations操作集中的fasync()函数就会被执行*/

举例:

#include <linux/fs.h> //使能fasync_struct结构

struct xxx_dev{

  dev_t devid; /*声明32位变量devid用来给保存设备号*/

  int major;   /*主设备号*/

  int minor;   /*次设备号*/

  struct cdev  cdev; /*字符设备结构变量cdev */

  struct class *class;     /*类*/

  struct device *device;  /*设备*/

  atomic_t lock;  /*原子变量*/

  struct fasync_struct *async_queue; /* fasync_struct结构体,即“异步通知”结构体 */

};

/*fasync函数,用于处理异步通知

fd : 文件描述符

filp : 要打开的设备文件(文件描述符)

on : 模式

返回值: 负数表示函数执行失败

*/

/*当“应用程序”通过“fcntl(fd,F SETFL, flags|FASYNC)”改变fasync标记的时候,

“驱动程序” file_operations操作集中的xxx_fasync()函数就会被执行*/

static int xxx_fasync(int fd, struct file *filp, int on)

{

struct xxx_dev *dev = filp->private_data;

if (fasync_helper(fd, filp, on, &dev->async_queue) < 0)

{

return -EIO;

}

return 0;

}

/*声明file_operations结构变量MyCharDevice_fops*/

/*它是指向设备的操作函数集合变量*/

const struct file_operations xxx_fops = {

  .owner = THIS_MODULE,

  .open = xxx_open,

  .read = xxx_read,

  .write = xxx_write,

  .release = xxx_release,

.fasync = xxx_fasync,

};

在关闭驱动文件时,需要在file_operations操作集中的release()函数中释放fasync_struct,fasync_struct的释放函数同样为 fasync_helper,release()函数参数参考实例如下:

/* 关闭/释放设备 */

static int xxx_release(struct inode *inode, struct file *filp)

{

  struct xxx_dev *dev = filp->private_data;

  atomic_inc(&dev->lock);

  /*关闭驱动文件的时候释放原子变量,便于其它线程使用*/

  printk("xxx_release!\r\n");

  return xxx_fasync(-1, filp, 0); /* 删除异步通知 */

}

当设备可以访问时,“驱动程序”则向“应用程序”发出信号,相当于产生“中断”。Kill_fasync()函数负责发送指定的信号,kill_fasync()函数原型如下:

void kill_fasync(struct fasync_struct **fp, int sig, int band)

fp:要操作的 fasync struct
sig:要发送的信号
band:可读时设置为POLL_IN,可写时设置为POLL_OUT

返回值:无

5、应用程序对异步通知的处理:

应用程序对异步通知的处理包括以下三步:

1、注册信号处理函数

“应用程序”根据“驱动程序”所使用的信号来设置信号的处理函数;应用程序使用signal() 函数来设置信号的处理函数。

signal(SIGIO, sigio_signal_func);

/* 设置信号SIGIO的处理函数为sigio_signal_func() */

2、将本应用程序的进程号告诉给内核

fcntl(fd,F_SETOWN, getpid();/*将本应用程序的进程号告诉给内核*/

3、开启异步通知

使用如下两行程序开启异步通知:

flags = fentl(fd, F GETFL);/*获取当前的进程状态*/

fcntl(fd,F SETFL, flags |FASYNC);/*开启当前进程异步通知功能 */

重点就是通过fcntl()函数设置进程状态为FASYNC,经过这一步,驱动程序中的fasync()函数就会被执行。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

npm install 报 ERESOLVE unable to resolve dependency tree 异常解决方法

问题 在安装项目依赖时&#xff0c;很大可能会遇到安装不成功的问题&#xff0c;其中有一个很大的原因&#xff0c;可能就是因为你的npm版本导致的。 1.npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree 2.ERESOLVE unable to resolve dependenc…

赋能未来:AI技术革新中的创业契机

目录 前言 一、行业解决方案 1、行业参考说明 2、操作步骤建议 二、智能产品和服务 1、行业参考说明 2、操作步骤建议 三、教育和培训 1、行业参考说明 2、操作步骤建议 总结 前言 随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;越来越多的创业…

高质量ChatGPT Prompts 精选

通用超级 Prompt GPT4实用。通用超级 prompt &#xff0c;根据你想要的输出和你的反馈&#xff0c;自动使用相应的专家角色帮你解决问题。如果需要升级ChatGPT Plus&#xff0c;可以参考教程 升级 GPT4.0 保姆教程 您是一位具有多领域专长的专家级ChatGPT提示工程师。在我们…

IP证书申请流程

目录 域名与IP的关系 SSL证书绑定域名还是绑定IP&#xff1f; IP证书支持免费申请吗&#xff1f; 如何申请IP地址证书 IP类型的SSL证书&#xff0c;又称之为IP SSL&#xff0c;这种SSL证书是专门用于公网IP地址验证的一种数字证书。 主要功能就是解决IP地址明文传输的安全…

【JAVA基础篇教学】第八篇:Java中List详解说明

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第八篇&#xff1a;Java中List详解说明。 在 Java 编程中&#xff0c;List 接口是一个非常常用的集合接口&#xff0c;它代表了一个有序的集合&#xff0c;可以包含重复的元素。List 接口提供了一系列操作方法&#xff0c;…

Pytorch: 利用预训练的残差网络ResNet50进行图像特征提取,并可视化特征图热图

1. 残差网络ResNet的结构 2.图像特征提取和可视化分析 import cv2 import time import os import matplotlib.pyplot as plt import torch from torch import nn import torchvision.models as models import torchvision.transforms as transforms import numpy as npimgname…

Windows 2003 R2与Windows 2022建立域信任报错:本地安全机构无法跟域控制器获得RPC连接。请检查名称是否可以解析,服务器是否可用。

在Windows Server 2003 R2与Windows Server 2022之间建立域信任时遇到“本地安全机构无法与域控制器获得RPC连接”的错误&#xff0c;可能是由于以下几种原因&#xff1a; DNS 解析问题&#xff1a; 确保源域和目标域的DNS配置正确&#xff0c;能够互相解析对方的域名和IP地址。…

Kubernetes学习笔记12

k8s核心概念&#xff1a;控制器&#xff1a; 我们删除Pod是可以直接删除的&#xff0c;如果生产环境中的误操作&#xff0c;Pod同样也会被轻易地被删除掉。 所以&#xff0c;在K8s中引入另外一个概念&#xff1a;Controller&#xff08;控制器&#xff09;的概念&#xff0c;…

搭建个人智能家居 4 -WS2812B-RGB灯

搭建个人智能家居 4 - WS2812B-RGB灯 前言说明ESPHomeHomeAssistant 前言 上一篇文章我们已经完成了第一个外设的添加&#xff08;一个LED灯&#xff09;&#xff0c;今天接着来“壮大”这个系统&#xff0c;添加第二个外设“RGB灯”。 环境搭建可以回顾前面的文章。前文回顾&…

界面控件DevExtreme JS ASP.NET Core 2024年度产品规划预览(二)

在本文中我们将介绍今年即将发布的v24.1附带的主要特性&#xff0c;这些特性既适用于DevExtreme JavaScript (Angular、React、Vue、jQuery)&#xff0c;也适用于基于DevExtreme的ASP.NET MVC/Core控件。 注意&#xff1a;本文中列出的功能和特性说明官方当前/预计的发展计划&a…

PrimeKG:为精准医学分析设计的多模态知识图谱

PrimeKG&#xff1a;为精准医学分析设计的多模态知识图谱 PrimeKG简介数据资源和覆盖范围构建方法和技术细节PrimeKG多模态知识图谱的概览构建PrimeKG的过程PrimeKG 数据 多模态特性和临床应用PrimeKG 设计逻辑 论文&#xff1a;https://www.nature.com/articles/s41597-023-01…

盘点“整容”成功的国漫男主,唐三萧炎谁才是顶级颜值?

国漫男主千千万&#xff0c;可不是每一位都能做到颜值与实力并存&#xff01;有些男性角色的建模起初受限于技术和审美等原因&#xff0c;呈现出的效果并不理想&#xff0c;好在越来越多的作品开始尝试给角色模型更新换代&#xff0c;本期为您盘点那些成功更换模型的国漫男主&a…

Acrobat Pro DC 2023 for mac直装激活版 pdf编辑处理工具

Acrobat Pro DC 2023 for Mac是一款功能强大的PDF编辑器&#xff0c;为用户提供了全面且高效的PDF处理体验。 软件下载&#xff1a;Acrobat Pro DC 2023 for mac直装激活版下载 首先&#xff0c;它支持用户从现有文档创建PDF&#xff0c;或者将其他文件格式如图片、网页等轻松转…

【fastapi】搭建第一个fastapi后端项目

本篇文章介绍一下fastapi后端项目的搭建。其实没有什么好说的&#xff0c;按照官方教程来即可&#xff1a;https://fastapi.tiangolo.com/zh/ 安装依赖 这也是我觉得python项目的槽点之一。所有依赖都安装在本地&#xff0c;一旦在别人电脑上编写项目就又要安装一遍。很扯淡。…

JavaSEhomework2

题目&#xff0c;上图&#xff01;&#xff01; 上代码 import java.util.Scanner; public class homework01 {public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.print("Enter the number of values: ");int num input.…

MySQL 表管理

目录 建库 语法&#xff1a; 库名命名规则&#xff1a; 相关命令&#xff1a; 建表 语法&#xff1a; 相关命令&#xff1a; 修改表 语法&#xff1a; 常用操作命令 复制表 数据类型 MySQL的10种常用数据类型&#xff1a; 数据的导入和导出 导入&#xff1a; 格…

CSS特效---HTML+CSS实现3D旋转卡片

1、演示 2、一切尽在代码中 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title&…

MongoDB爬虫:(某扑)实战

https://bbs.hupu.com/bxj网页地址: https://bbs.hupu.com/bxj 然后我们在网页上定义帖子名称、帖子链接、创建时间、回复数、最后回复用户...... 除此之外,我们发现虎扑步行街最多显示的页数(20): 、 当我们打开第3页的时候,网页的URL的地址变为了:https://bbs.hupu.…

迭代器模式:统一访问集合元素的优雅方式

在面向对象的软件开发中&#xff0c;迭代器模式是一种行为型设计模式&#xff0c;它提供了一种方法来顺序访问一个聚合对象中的各个元素&#xff0c;而又无需暴露该对象的内部表示。这种模式是集合处理特别是遍历集合的核心机制。本文将详细介绍迭代器模式的定义、实现、应用场…

RISC-V技术变革:一颗芯片,CPU与GPU合二为一

一颗万能的RISC-V芯片: 将CPU和GPU整合到一个核中 X-Silicon 推出创新的 RISC-V 芯片架构,将 CPU、矢量功能和 GPU 加速无缝集成。这种开源混合芯片专为多功能工作负载而设计,包括人工智能,旨在通过高效处理提升性能。 革命性的 CPU/GPU 混合处理器全新的 RISC-V CPU/GPU 混…