The device driver notifies the asynchronous asynchronous I / O

Using asynchronous notification may be in the device driver so that further access device, the driven actively notify the user program access. Replaced this way, the use of non-blocking I / O applications that do not need a polling mechanism to query the device is accessible, while blocking access may also be similar to the "break" asynchronous notification. In addition to asynchronous notification that the application can also be launched in the I / O request and return immediately. Thereafter, the query I / O completion, or I / O after the completion of return. This process is asynchronous I / O.

Blocking and non-blocking access, poll function provides a better solution device access mechanism, but if you have asynchronous notification, the entire mechanism is more complete. Meaning asynchronous notification is: Once the equipment is ready, take the initiative to inform the user program, so that the user program does not need to query the device status, which is very similar to the "break" on the hardware concept is more accurate to call "signal is driven asynchronous I / O ". Signal is at the level of an analog terminal software mechanism, in principle, a process receives a hand signal processor receives an interrupt request can be said to be the same. Signal is asynchronous, a process that does not require any action to wait for the arrival of the signal, in fact, the process signals in the end do not know what time to arrive.

Blocking I / O means that after the device has been waiting for accessible access, non-blocking I / O used in the poll function means that the query or No equipment is accessible, and it means the asynchronous notification notifies the user can access the program itself, after the user performing I / O processing. Thus, these types of I / O mode can complement each other. Blocking, non-blocking, asynchronous notification itself is not good or bad, should be chosen according to different scenarios should be shipped.

Use asynchronous notification signal to achieve, the signal is a mechanism for inter-process communication (IPC), there are 30 kinds of signals linux available, you can Baidu query. In addition to SIGSYOP with two SIGKILL signal, processes can be ignored or get all the other signals. A signal is captured when a sense signal reaches the corresponding code is processed it. If a signal is not caught this process, the kernel will be taken to deal with the default behavior.

Function of the signal received

void (*singal(int signum,void(* handler))(int))(int);
//分解为
typedef void (* sighsndler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
//第一个参数是指定信号的值,第二个参数时指定针对前面信号值的处理函数,若为SIG_IGN,表示忽略给信号,若为SIG_DFL,表示使用
系统默认的方式处理信号,若为用户自定义的函数,则信号被捕获后,该函数将被执行。若signal()函数调用成功,他返回最后一次为
信号signum绑定的处理函数的handler值,失败返回SIG_ERR。

Get "Ctrl + C" and prints the respective signal values

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void sigtem_handler(int signo)
{
    printf("Have change sig N.O %d\n",signo);
    exit(0);
}

int main()
{
    signal(SIGINT,sigtem_handler);
 //   signal(SIGTERM,sigtem_handler);
    while(1);
    return 0;
}

In addition to the signal function, the sigaction () function can be used to change the behavior of the process receives the signal, which is the prototype:

int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
//第一个参数为信号的值,可以是除却SIGKILL及SIGSTOP外的任何一个特定有效的信号。第二个参数是指向结构体sigaction的一个实例的指针,
在结构体sigaction的实例中,指定了对特定信号的处理函数,若为空,则进程会以缺省方式对信号处理;第三个参数oldcat 指向的对象用来
保存原来对相应信号的处理函数,可指定oldact为NULL。如果把第二、第三个参数都设置为NULL,那么刚函数可以用来检测信号的有效性。

In order to make the device supports asynchronous notification mechanism, the driver involved in three work

  1. F_SETOWN support command, can be provided filp-> f_owner process ID corresponding control command in this process. But Xixiang works have been completed kernel, device drivers without treatment. ,
  2. F_SETFL support processing commands whenever FASYNC flag change, fasync driver () function will be performed. Thus, driving should be implemented fasync () function.
  3. When the device resources available, call kill_fasync () function corresponding excitation signal.

Asynchronous notification device driver programming relatively simple, mainly uses a two functions and data structures, the data structure is a structure fasync_struct, two functions are:

//处理FASYNC标志变更的函数
int fasync_helper(int fd,struct file *filp,int mode,struct fasync_struct **fa);
//释放信号用的函数
void kill_fasync(struct fasync_struct **fa,int sig,int band);

 Asynchronous notification function template

1.在设备结构体中添加异步结构体
struct xxx_dev{
    struct cdev cdve;
    ...
    struct fasync_struct *async_queue; //异步通知结构体
};
2.file_operations结构体中添加fasync
static struct file_operations xxx_fops{
    ...
    .fasync = xxx_fasync,
};
3.设备驱动fasync()函数模板
static int xxx_fasync(int fd,struct file *filp,int mode)
{
    struct xxx_dev *dev = filp->private_data;
    return fasync_helper(fd,filp,mode,&dev->async_queue);
} //即只需要把 异步结构体 作为fasync_helper的第四个参数返回即可
4.在write函数中添加 异步信号的读取
static ssize_t xxx_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos)
{
    struct xxx_dev *dev = filp->private_data;
    ...
    if(dev->async_queue) //产生异步读信号
        kill_fasync(&dev->async_queue,SIGIO,POLL_IN);//调用kill_fasync 释放信号
}
5.在文件关闭,即release函数中应用函数fasync将文件从异步通信列表中删除
static int xxx_release(struct inode *inode,struct file *filp)
{
    xxx_fasync(-1,filp,0);
    ...
    return 0;
}

 Modify blocking I / O Bowen driver code, the compiler loads, test code

#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

static void signalio_handler(int signum)
{
    printf("receive a signal from mymodules,signalnum:%d\n",signum);
}

int main()
{
    int fd,oflags;
    fd = open("/dev/mymodules",O_RDWR,S_IRUSR | S_IWUSR);
    if(fd != -1){
        signal(SIGIO,signalio_handler);
        fcntl(fd,F_SETOWN,getpid());
        oflags = fcntl(fd,F_GETFL);
        fcntl(fd,F_SETFL,oflags | FASYNC);
        while(1){
            sleep(100);
        }
    }else
        printf("open device error\n");
    return 0;
}

After compiling test

Published 45 original articles · won praise 7 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_42005898/article/details/104818078