Asynchronous Notification and Asynchronous I/O in Linux Device Drivers

Publisher:Lihua521Latest update time:2024-08-21 Source: cnblogsKeywords:Linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Asynchronous notification concept: The concept of asynchronous notification is that once the device is ready, it will actively notify the application, so that the application does not need to query the device status at all. This is very similar to the concept of "interrupt" in hardware. The more accurate name is "signal-driven asynchronous IO". The signal is a simulation of the interrupt mechanism at the software level. In principle, a process receiving a signal is the same as the processor receiving an interrupt request. The signal is asynchronous, and a process does not have to wait for the arrival of the signal through any operation. In fact, the process does not know when the signal will arrive.


Asynchronous notification and device access: Blocking IO means waiting for the device to be accessible before accessing it; non-blocking IO using poll means querying whether the device is accessible; and asynchronous notification means that the device notifies itself that it is accessible, thus realizing asynchronous I/O.


Use the kill -l command to view the available signals in Linux

Signal reception

signal() function to set the processing function of the corresponding signal.

void (*signal(int signum,void(*handler))(int)))(int);

//The first parameter specifies the value of the signal; the second parameter specifies the processing function for the previous signal value. If it is SIN_IGN, it means ignoring the signal; if it is SIG_DFL, it means using the system default method to process the signal; if it is user-defined

function, the signal is captured and the function will be executed

//The prototype of this function is hard to understand, and can be broken down into: typedef void(*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler));

If the signal call succeeds, it returns the handler value of the last signal signum binding, and returns SIG_ERR if it fails.

The sigaction() function can be used to change the behavior of a process after receiving a specific signal.

int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));

//The first parameter of this function is the value of the signal, which can be any specific valid signal except SIGKILL and SIGSTOP; the second parameter is a pointer to an instance of the structure sigaction.

Specifies the processing function for a specific signal. If it is empty, the process will process the signal in the default way. The object pointed to by the third parameter oldact is used to save the original processing function for the corresponding signal. You can specify oldact as NULL.

If the second and third parameters are set to NULL, the function is used to detect the validity of the signal.

An example application using signals for asynchronous notifications:

#include

#include

#include

#include

#include

#include

#define MAX_LEN 100

void input handler(int num)

{

char data[MAX_LEN];

int len;

len=read(STDIN_FILENO,&data,MAX_LEN); //Read and output input on STDIN_FILENO.

data[len]=0;

printf("input available:%sn",data);

}

main()

{

int oflags;

//Start the signal drive mechanism

signal(SIGIO,input_handler); //Install input_handler() as the processing function for SIGIO signal

fcntl(STDIN_FILENO,F_SETOWN,getpid()); //The getpid() here is to obtain the current process. Note that without this step, the kernel does not know which process to send the signal to.

In Linux, the functions for implementing file locking are lock and fcntl. flock is used to apply advisory locks to files, while fcntl can not only apply advisory locks, but also mandatory locks. At the same time, fcntl can also lock a record of a file, that is, record lock.

Record locks can be divided into read locks and write locks. Read locks are also called shared locks, which enable multiple processes to establish read locks on the same part of a file. Write locks are also called exclusive locks, and only one process can establish a write lock on a certain part of a file at any time. Of course, read locks and write locks cannot be established on the same part of a file at the same time.

Notice:

fcntl is a very general function that can also change various attributes of file processes. In this section, we mainly introduce how to establish record locks. Readers who are interested in other users can refer to the fcntl manual.

oflags=fcntl(STDIN_FILENO,F_GETFL); //In order to start the one-step notification mechanism, you also need to set the FASYNC flag on the device


fcntl(STDIN_FILENO,F_SETFL,oflags|FASYNC);


//Finally enter an infinite loop, just to keep the process from terminating. If there is no infinite loop in the program, the execution will be completed immediately.


while(1);


}


Signal release:

In the asynchronous notification interaction between the device driver and the application, the application captures the signal and the driver releases the signal.


In order for a device to support asynchronous notification mechanism, three tasks are involved in the driver.


(1) Supports the F_SETOWN command, which can set filp->f_owner to the corresponding process ID in this control command processing. However, this work has been completed by the kernel and the device driver does not need to handle it.


(2) Support the processing of F_SETFL command. Whenever the FASYNC flag changes, the fasync() function in the driver will be executed. Therefore, the fasync() function should be implemented in the driver.


(3) When device resources are available, call the kill_fasync() function to trigger the corresponding signal.


Interaction between user space and device drivers during asynchronous notification processing.

Asynchronous notification mainly uses a data structure and two functions. The data structure is the fasync_struct structure, and the two functions are fasync_helper and kill_fasync.


int fasync_helper(int fd,struct file *filp,int mode,struct fasync_struct **fa); //Handle FASYNC flag change


void kill_fasync(struct fasync_struct **fa,int sig,int band); //Release signal


Device structure template that supports asynchronous notification


struct xxx_dev{


struct cdev cdev; //cdev structure


...


struct fasync_struct *async_queue; //Asynchronous structure pointer


};


Device driver fasync() function template that supports asynchronous notification


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);


}


When the device resources are available, kill_fasync() should be called to release the SIGIO signal. The third parameter is set to POLL_IN when readable and POLL_OUT when writable.


An example of a device driver signal release that supports asynchronous notification:


static ssize_t xxx_write(struct file *filp,const char_user *buf,size_t count,loff_t *f_pos)


{


struct xx_dev *dev=filp->private_data;


...


//Generate asynchronous read signal


if(dev->async_queue)


kill_fasync(&dev->async_queue,SIGIO,POLL_IN);


...


}


Finally, when closing the file, that is, in the release function, the file should be deleted from the list of asynchronous notifications.


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


{


//Delete the file from the asynchronous notification list


xxx_fasync(-1,filp,0);


...


return 0;


}


Keywords:Linux Reference address:Asynchronous Notification and Asynchronous I/O in Linux Device Drivers

Previous article:ARM Linux character device driver
Next article:14. s3c2440 bare metal - interrupt controller

Recommended ReadingLatest update time:2024-11-16 09:37

Ubuntu 12.04 embedded cross-compilation environment arm-linux-gcc construction process diagram
Before installation First, let me briefly introduce that building a cross-compilation environment means installing and configuring a cross-compilation tool chain. In this environment, the operating system and application programs required by the embedded Linux system are compiled and then uploaded to the target
[Microcontroller]
Ubuntu 12.04 embedded cross-compilation environment arm-linux-gcc construction process diagram
ADLINK joins the Open Radio Access Network (O-RAN) Alliance
Accelerating network interoperability to help enterprises move towards 5G Leveraging 5G open radio access network expertise to accelerate commercialization of 5G RAN solutions Summary:   • ADLINK joins the O-RAN Alliance as a Contributor to promote 5G RAN technology innovation and integrate software and hardwa
[Network Communication]
ADLINK joins the Open Radio Access Network (O-RAN) Alliance
Intel Gaudi2C AI accelerator card appears in Linux driver, sources say it is a special version for China
 According to news on December 20, in July this year, Intel launched a Gaudi2 processor for the Chinese market, which is mainly used to accelerate AI training and inference. According to Phoronix, there is also a new version of the accelerator card coming, and Intel has added support for Gaudi2C in its Linux driver.
[Embedded]
LINUX 3.0.8 supports RT3070 USB Wifi (S3C6410)
Run make xconfig in the LINUX 3.0.8 directory, and select Ralink rt27xx/rt28xx/rt30xx (USB) support as shown below. This adds the driver that supports RT3070 USB Wifi. Save and exit xconfig, then make to get the new kernel zImage. Update the kernel and connect the USB Wifi. You will see usb 1-1.3: ne
[Microcontroller]
The Linux Foundation AI & Data Foundation launches enterprise AI open platform project, Intel and partners work together to promote AI innovation and development
The Linux Foundation AI & Data Foundation launches enterprise AI open platform project, Intel and partners work together to promote AI innovation and development Abstract: Intel plans to work with the developer community to promote the development of generative AI systems. On April 17,
[Network Communication]
The Linux Foundation AI & Data Foundation launches enterprise AI open platform project, Intel and partners work together to promote AI innovation and development
【TE Connectivity】Stacked QSFP 112G High-Speed ​​I/O Products Support 400 Gbps
In order to meet the design requirements of next-generation computing units in fields such as data centers, telecommunications and artificial intelligence technology, TE Connectivity (hereinafter referred to as "TE") can provide a comprehensive, flexible and high-performance combination of internal and external conn
[Embedded]
【TE Connectivity】Stacked QSFP 112G High-Speed ​​I/O Products Support 400 Gbps
Linux kernel transplantation based on tiny4412 (supports device tree) (1)
Platform introduction Development board: tiny4412ADK + S700 + 4GB Flash Kernel version to be transplanted: Linux-4.4.0 (supports device tree) u-boot version: U-Boot 2010.12 that comes with Friendly Arm (some changes have been made to support uImage startup) busybox version: busybox 1.25 Cross-compilation tool chain: a
[Microcontroller]
ARM Linux Interrupt Analysis
Introduction: Linux has prepared the address of each interrupt vector when it is initialized! That is to say, the framework for adding an interrupt service program has been given. When an interrupt occurs, it will go to a certain address to find instructions. Therefore, when we make a driver, we only need to use reque
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号