设备 IO

作者: Lmmmmbbb | 来源:发表于2017-06-11 15:25 被阅读23次

IO有两个特性:阻塞/非阻塞 与 同步/异步,组合一下就是四种情况。

  • 同步
    设备驱动中,read/write方法属于同步IO
    在资源不可用时,read/write阻塞,比如等待队列等实现,就属于阻塞/同步的IO方式。
    如果是立即返回(EAGAIN,EBUSY等),就属于非阻塞。
    具体实现可以根据应用程序打开设备文件时是否带O_NONBLOCK标志来决定。
static ssize_t xxx_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
    if(!ready_to_read) {
        if(filp->f_flag & O_NONBLOCK) {
            //非阻塞方式打开,则直接返回
            return -EAGAIN;
        }
        //阻塞方式,等待资源可用
        wait_event_interruptible(waitqueue, read_to_read);
    }
   .........
}
  • 异步
    所谓异步,就是在应用程序发送读写请求后,立即返回但并不立即获取数据,只是相当于向系统发送了一个读写请求,待驱动程序准备好后,再通知应用程序,再进行真正的读写。

异步的非阻塞方式有fasync方法:
应用程序设置了设备文件的 FASYNC属性后,驱动程序就可以在恰当的时候通过消息通知应用程序。
应用程序操作步骤:

//设置信号处理函数,驱动程序应当通过SIGIO来通知
signal(SIGIO, sig_handler); 
//设置设备文件的属主,设置为进程本身
fcntl(fd, F_SETOWN, getpid());
//设置设备文件FASYNC属性
f_flags  = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, f_flags | FASYNC); //此时会调用驱动 fasync方法

驱动程序实现:

//定义fasync_struct 
struct fasync_struct *async_queue;
//实现fasync方法
int xxx_fasync(int fd, struct file *filp, int mode)
{
   ...............
    //注意async_queue是二级指针,fasync_help作用就是初始化async_queue
    ret = fasnc_helper(fd, filp, mode, &async_queue);
}
//在合适的时机通知应用程序
kill_fasync(&fasync_queue, SIGIO, POLL_IN); //POLL_IN为可读,POLL_OUT为可写

异步阻塞方式:IO多路复用(poll-select)
使用poll-select方法可以监视一组文件(fd_set),其中只要有一个文件可读/写,应用程序中select就会返回。
驱动程序中实现设备的poll方法:

static unsigned int xxx_poll(struct file *filp, poll_table *wait)
{
    unsigned mask = 0;
    poll_wait(filp, &rd_wait_queue, wait);
    poll_wait(filp, &wr_wait_queue, wait);
    if(is_readable) {
        mask |= POLL_IN | POLLRDNORM;
    }
    if(is_writeable) {
        mask |= POLL_OUT | POLL_WRNORM;
    }
    return mask;
}

驱动程序中 poll方法要做的事很少:
1、首先调用 poll_wait 将一个等待队列添加到poll_table中,该等待队列一般在设备文件变得可读/写时被唤醒。这里只是加入,并不开始在等待队列上休眠。
2、判断文件当前是否可读/写,这个一般有一个全局变量来表示。
3、如果判断时可读/写了,就置位mask并返回,否则返回0.
4、在我们的poll方法之上,有一个调用它的上级函数,在这个函数里会阻塞等待,当之前阻塞的等待队列被唤醒时,就会再次调用poll方法,直到返回非0.
参考:

理解poll_waite
问答:
如果当前不可读,那么在sys_poll->do_poll中当前进程就会睡眠在等待队列上,这个等待队列是由驱动程序提供的(就是poll_wait中传入的那个)。当可读的时候,驱动程序可能有一部分代码运行了(比如驱动的中断服务程序),那么在这部分代码中,就会唤醒等待队列上的进程,也就是之前睡眠的那个,当那个进程被唤醒后do_poll会再一次的调用驱动程序的poll函数,这个时候应用程序就知道是可读的了。

相关文章

  • 操作系统io小结

    io分为内存io,磁盘io与网络io,一般认为是后两种 1. io设备 io设备块设备:块设备是以块为单位读写的设...

  • 设备 IO

    IO有两个特性:阻塞/非阻塞 与 同步/异步,组合一下就是四种情况。 同步设备驱动中,read/write方法属于...

  • 操作系统--IO设备

    什么是IO设备? IO设备是输入输出设备,包括计算机系统中除CPU和内存以外的所有设备和装置。 IO设备是一个文件...

  • [现代操作系统] I/O软件

    IO软件目标 IO处理方式 IO软件层次中断处理程序设备驱动程序位置功能运行与设备无关的I/O软件用户空间的IO软...

  • Android-Java-I/O流概述

    IO:I:Input输入O:Output输出 IO流: IO:用于处理设备上数据的一种技术,处理设备上数据包括(I...

  • IO控制的App

    流程 创建对象 配置IO 循环读取IO在IO中进行设备动作在设备动作过程中没有进行动作的响应 IBitHelp 这...

  • IO流

    IO流 使用IO流技术读取文件的内容数据。 IO流解决问题: 解决设备与设备之间的数据传输问题。 内存--->硬...

  • 《深入浅出nodejs》读书笔记

    I/O设备:与计算机进行输入输出数据传输的硬件设备(机械部分)设备控制器:控制IO设备与CPI的通信的电子设备IO...

  • PCIe扫盲——Memory & IO 地址空间

    早期的PC中,所有的IO设备(除了存储设备之外的设备)的内部存储或者寄存器都只能通过IO地址空间进行访问(Inte...

  • File类(操作文件)

    IO流(Input Output) IO技术主要的作用是解决设备与设备之间 的数据传输问题。硬盘 -> 内存内存的...

网友评论

      本文标题:设备 IO

      本文链接:https://www.haomeiwen.com/subject/bircqxtx.html