IO模型-信号驱动IO

这篇具有很好参考价值的文章主要介绍了IO模型-信号驱动IO。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

linux内核中存在一个信号SIGIO,这个信号就是用于实现信号驱动IO的。当应用程序中想要以信号驱动IO的模型读写硬件数据时,首先注册一个SIGIO信号的信号处理函数,当硬件数据就绪,硬件会发起一个中断,在硬件的中断处理函数中向当前进程发送SIGIO信号,此时进程捕获到SIGIO信号,执行信号处理函数,在信号处理函数中将准备好的硬件数据读走.

对于应用程序主程序的执行和SIGIO信号的发送的过程是一个异步的过程,信号驱动IO是唯一一种异步IO。

(异步操作是指在执行操作期间不会阻塞进程或线程的操作。在驱动开发中,异步操作通常是通过使用工作队列、定时器、中断处理程序等机制来实现的。)

IO模型-信号驱动IO,驱动开发,vscode,linux,stm32,嵌入式硬件

驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/device.h>
#include<linux/uaccess.h>
#include<linux/poll.h>
struct class *cls;
struct device *dev;
unsigned int major;//定义一个变量保存主设备号
char kbuf[128]={0};
struct fasync_struct *fapp;//定义一个异步对象指针
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
ssize_t mycdev_read(struct file *file, char  *ubuf, size_t size, loff_t *lof)
{
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
      if(size>sizeof(kbuf))//用户的需求内核满足不了
     {
        size=sizeof(kbuf);
     }
      long ret;
     ret=copy_to_user(ubuf,kbuf,size);
     if(ret)
     {
        printk("copy_to_user filed\n");
        return -EIO;
     }
   
    return 0;
}
ssize_t mycdev_write(struct file *file, const char  *ubuf, size_t size, loff_t *lof)
{
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
     if(size>sizeof(kbuf))//用户的需求内核满足不了
     {
        size=sizeof(kbuf);
     }
      long ret;
     ret=copy_from_user(kbuf,ubuf,size);//表示模拟硬件数据就绪
     if(ret)
     {
        printk("copy_from_user filed\n");
        
        return -EIO;
     }
     //发送信号
     kill_fasync(&fapp,SIGIO,POLL_IN);
     
    return 0;
}
//封装fasync操作方法
int mycdev_fasync(int fd, struct file * file, int on)
{
    //完成发生信号之前的准备工作
    fasync_helper(fd,file,on,&fapp);
    return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
//定义一个操作方法结构体变量并且初始化
struct file_operations fops={
    .open=mycdev_open,
    .release=mycdev_close,
    .read=mycdev_read,
    .fasync=mycdev_fasync,
    .write=mycdev_write,
};
static int __init mycdev_init(void)
{
    
    //注册字符设备驱动
    major=register_chrdev(0,"mychrdev",&fops);
    if(major<0)
    {
        printk("注册字符设备驱动失败\n");
        return major;
    }
    printk("注册字符设备驱动成功major=%d\n",major);
    // 向上提交目录
    cls = class_create(THIS_MODULE, "myled");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录信息成功\n");
    // 向上提交设备节点信息
   
        dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycdev");
        if (IS_ERR(dev))
        {
            printk("向上提交设备节点信息失败\n");
            return -PTR_ERR(dev);
        }
    printk("向上提交设备节点成功\n");
    return 0;
}
static void __exit mycdev_exit(void)
{
    // 销毁节点信息
    device_destroy(cls, MKDEV(major, 0));
  
    // 销毁目录信息
    class_destroy(cls);
    //注销字符设备驱动
    unregister_chrdev(major,"mychrdev");

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

应用程序-读数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <signal.h>
/* According to earlier standards */
#include <sys/time.h>

char buf[128] = {0};
int fd;
// 定义信号处理函数
void sigio_handler(int sig)
{
    // 读取硬件数据
    read(fd, buf, sizeof(buf));
    printf("buf:%s\n", buf);
}
int main(int argc, char const *argv[])
{

    // 打开文件
    fd = open("/dev/mycdev", O_RDWR);
    if (fd < 0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    // 注册SIGIO的信号处理函数
    signal(SIGIO, sigio_handler);
    // 回调驱动中的fasync方法,完成驱动中发生信号之前的准备工作
    int flags = fcntl(fd, F_GETFL);     // 获取文件描述符的相关属性
    fcntl(fd, F_SETFL, flags | FASYNC); // 当文件描述符中有FASYNC这个标志时,驱动中fasync方法就会被调用
    // 设置文件描述符fd对应的驱动发生SIGIO信号只发送给当前进程
    fcntl(fd, F_SETOWN, getpid());
    while (1)
    {
        printf("aaaaa\n");
        sleep(1);
    }
    return 0;
}

应用程序-模拟中断文章来源地址https://www.toymoban.com/news/detail-627724.html

#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>


int main(int argc, char const *argv[])
{
    int a,b;
    char buf[128]="hello world";
    int fd=open("/dev/mycdev",O_RDWR);
    if(fd<0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    write(fd,buf,sizeof(buf));
    close(fd);

    return 0;
}

到了这里,关于IO模型-信号驱动IO的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32 AW9523B IO扩展芯片扩展io口驱动程序

    对AW9523B驱动模块进行初始化 对AW9523B驱动模块进行操作 初始化AW9523B单个引脚 读取AW9523B单个引脚 读取AW9523B单个端口 用于存储单个ic中的数据,如需管理更多的结构体,可以再增加定义 3060793968@qq.com 

    2024年01月20日
    浏览(30)
  • 关于stm32推挽带有上下拉电阻的思考、IO口驱动能力是什么

    1.1、stm32手册 记忆中推挽是不需要上下拉的,没关注过,但是我真的理解上下拉吗,下图来自stm32f4的中文版和英文版的数据手册,没有翻译错,就是“推挽带有上下拉的能力”。 1.2、查找相关信息 搜索到一篇推挽上下拉的文章,实际测试表格如下,从他的数据来看,推挽不

    2024年02月10日
    浏览(31)
  • 讲解STM32驱动WS281x灯珠的多种实现方式:普通IO、SPI+DMA、以及PWM+DMA驱动方法

    STM32作为一款高性能、功能丰富的单片机,其丰富的外设和强大的性能,使其在嵌入式领域得到了广泛的应用。本篇文章将介绍如何利用STM32驱动WS281x系列的LED灯珠。我们会使用三种不同的驱动方式进行实现:一种是普通IO方式驱动,一种是SPI+DMA方式驱动,最后一种是PWM+DMA方

    2024年02月11日
    浏览(29)
  • STM32驱动开发

    本文简单介绍STM32标准库下的部分驱动开发流程(F1系列芯片),扩展介绍部分重要的属性。 复用功能 将某些功能复用到其他引脚上使用。 属性 引脚(GPIO_Pin):芯片对应的引脚。 速率(GPIO_Speed):输出驱动电路的响应速度,做输入时此功能无效。芯片内部在I/O口的输出部分安排了

    2024年02月15日
    浏览(27)
  • vscode 搭建STM32开发环境

    1.1 vscode 1.2 STM32CubeMX,这个不是必须的,我是为了方便生成STM32代码 2.1安装keil Assistant 2.2配置keil Assistant          

    2024年02月13日
    浏览(42)
  • 基于STM32的pca9535、pca9555IO扩展板开发

    之前使用的pca9535由于芯片本身有些中断问题和采购问题,目前换成了pca9555的IO扩展芯片来使用,本文章适用于这两款芯片。 编译器: keil5 工程库: HAL库 芯片型号:STM32F072 pca9535和pca9555基本一样,这里我就主要说9535的手册了。 手册下载地址网上有很多,直接去百度搜索就行

    2024年02月11日
    浏览(29)
  • STM32MP157驱动开发——按键驱动(中断)

    对于使用中断的按键驱动,内核自带的驱动程序 drivers/input/keyboard/gpio_keys.c 就可以,需要做的只是修改设备树指定引脚及键值 中断是引入其他基础知识的前提:休眠-唤醒、POLL 机制、异步通知、定时器、中断的线程化处理都离不开中断 设备树相关 查看原理图确定按键使用的

    2024年02月15日
    浏览(32)
  • vscode stm32cubemx 优雅开发stm32,最简单步骤教程

    下载STM32cubeMX,这个大家可以自己在stm的官网下载到 下载VSCode 下载arm-none-eabi-gcc 下载MinGW-w64,为了实现里面的makefile 等功能 下载OpenOCD这里用来调试stm32,支持jlink stlink daplink 上述安装步骤1、安装步骤2在这里比较简单,就不赘述了  此处我们下载zip包,方便安装。 以我为例

    2024年02月12日
    浏览(44)
  • STM32的vscode开发环境配置

    此文章写给我即将到来的Robocon学弟 目录 前言 一、vscode的下载安装 二、编译环境的下载 1.make工具 2.gcc-arm-none-eabi工具链 3.OpenOCD烧录 三、STM32CubeMX生成项目 总结 关于STM32的开发环境,新手最熟悉的应该就是Keil了,但是Keil这个软件的界面实在是太难看了,而且添加文件结构也

    2024年02月07日
    浏览(44)
  • 模仿 STM32 驱动开发格式实验

    为了开发方便, ST 官方为 STM32F103 编写了一个叫做 stm32f10x.h 的文件,在这个文件 里面定义了 STM32F103 所有外设寄存器,我们可以使用其定义的寄存器来进行开发,比如我 们可以用如下代码来初始化一个 GPIO: 上述代码是初始化 STM32 的 PE5 这个 GPIO 为推挽输出,需要配置的就

    2024年02月21日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包