Home  >  Article  >  System Tutorial  >  An in-depth discussion of Linux driver technology (4)_The implementation principles and related technologies of asynchronous notification technology

An in-depth discussion of Linux driver technology (4)_The implementation principles and related technologies of asynchronous notification technology

PHPz
PHPzforward
2024-02-09 20:24:141003browse

In the process of writing Linux drivers, asynchronous notification technology is a very important technology. It can achieve efficient event processing and data transmission, improving system performance and response speed. In this article, we will delve into the implementation principles and related technologies of Linux driver technology (4) _asynchronous notification technology.

The full name of asynchronous notification is "signal-driven asynchronous IO". Through the "signal" method, when the resources expected to be obtained are available, the driver will actively notify the specified application, corresponding to the "signal" of the application layer, here The signal "SIGIO" is used. The steps are

  1. The application layer program registers itself as a process that receives the SIGIO signal from the device file
  2. The driver implements the corresponding interface in order to have the ability to send SIGIO signals to all applications registered to receive SIGIO signals from this device driver.
  3. The driver calls the sending function at the appropriate location, and the application can receive the SIGIO signal.

The framework of the entire mechanism:

深入探讨Linux驱动技术(四) _异步通知技术的实现原理和相关技术

Application layer receives SIGIO

Like other signals, the application layer needs to register a signal processing function,
The registration method is still to use signal() or sigaction()

In addition, the application layer also needs to add itself to the driver's notification list. The code to add is as follows

fcntl(dev_fd,F_SETOWN,getpid());
int oflags = fcntl(dev_fd,F_GETFL);
fcntl(dev_fd,F_SETFL,oflags|FASYNC);
...
while(1);

After completing the above work, the application layer program can wait for the arrival of SIGIO.

Driver sends SIGIO

After the application layer is registered, the final sending depends on the processing method of the device driver. In order to make the device support the asynchronous notification mechanism, referring to the interface of the application layer, the driver involves three tasks.

  1. Supports the F_SETOWN command. In this command, filp->f_owner can be set to the ID of the corresponding process. This part of the kernel has already been done
  2. Support F_SETFL, whenever the FASYNC flag changes, **fasync() in the driver will be executed, so, fasync() must be implemented in the driver **.
  3. When device resources are available, Send SIGIO via kill_fasync()

In order to implement the above three functions in the kernel, the driver needs to use 1 structure and 2 APIs, the structure is struct fasync_struct, and the function is fasync_helper ()andkill_fasync()

struct fasync_struct {                                    
        spinlock_t              fa_lock;
        int                     magic;
        int                     fa_fd;
        struct fasync_struct    *fa_next; /* singly linked list */
        struct file             *fa_file;
        struct rcu_head         fa_rcu;
};

fasync_helper() is used to register a fasync_struct object into the kernel. When the application layer executes **fcntl(dev_fd, F_SETFL, oflags|FASYNC) Callback-driven fops.fasync(), so fasync_helper() is usually placed in the implementation of fasync()**.

/**
 *fasync_helper - 将一个fasync_struct对象注册进内核
 *@fd:文件描述符,由fasync传入
 *@filp:file指针,由fasync传入
 *@sig:信号类型,通常使用的就是SIGIO
 *@dev_fasync:事前准备的fasync_struct对象指针的指针
 */
int fasync_helper(int fd, struct file * filp, int sig, struct fasync_struct ** dev_fasync);   

The following API is to release SIGIO and put it in different locations according to different needs.

/**
 *kill_fasync - 释放一个信号
 *@dev_fasync:事前使用fasync_helper注册进内核的fasync_struct对象指针的指针
 *@filp:file指针,由fasync传入
 *@sig:信号类型,通常使用的就是SIGIO
 *@flag:标志,通常,如果资源可读用POLLIN,如果资源可写用POLLOUT
 */
void kill_fasync(struct fasync_struct **dev_fasync, int sig, int flag);

Driver template

The following driver template is designed to signal the application layer when a hardware interrupt arrives (resources are available). In actual operations, there are many situations where resources are available

static struct fasync_struct *fasync = NULL;

static irqreturn_t handler(int irq, void *dev)
{
    kill_fasync(&fasync, SIGIO, POLLIN);
    return IRQ_HANDLED;
}
static int demo_fasync(int fd, struct file *filp, int mode)
{
    return fasync_helper(fd, filp, mode, &fasync);
}
struct file_operations fops = {
    ...
    .fasync = demo_fasync,
    ...
}
static int __init demo_init(void)
{
    ...
    request_irq(irq, handler, IRQF_TRIGGER_RISING, "demo", NULL);
    ...
}

总之,异步通知技术是Linux驱动程序编写过程中不可或缺的一部分。它可以实现高效的事件处理和数据传输,提高系统的性能和响应速度。希望本文能够帮助读者更好地理解Linux驱动技术(四) _异步通知技术的实现原理和相关技术。

The above is the detailed content of An in-depth discussion of Linux driver technology (4)_The implementation principles and related technologies of asynchronous notification technology. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:lxlinux.net. If there is any infringement, please contact admin@php.cn delete