Linux driver development (xv): Asynchronous Notification

Brief introduction

Use front blocking and nonblocking way drive to read the key values are read application active, non-blocking manner for the required application by continuous polling poll function
provides notification of the Linux kernel asynchronous mechanism implement a driver proactive notification to the application, they can access the report, then the application and then read or write data from the driver, the software interrupt mode
"signal" interrupt on similar hardware, the software level is to break the simulation device may be issued when the write signal
blocking, non-blocking, asynchronous notification for different solutions proposed by different occasions, no better or worse, to select the appropriate
addition SIGKILL (9) and SIGSTOP (19) these two signals can not be ignored, other signals can be ignored
if the signal is to be used in the application, the signal processing function set signal must be used, the function to register using the following signal processing function

sighandler_t signal(int signum, sighandler_t handler)

signum reference signal, handler process function pointer
prototype handler: typedef void (* sighandler_t) ( int)

The signal processing in the drive

Focusing on a data structure with two functions

fasync_struct structure

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

fasync function

To use asynchronous notification, the need to achieve fops fasync function device driver

int (*fasync) (int fd, struct file *filp, int on)

typically by fasync_helper fasync function to initialize the structure fasync_struct

int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)

The first three parameters are the three parameters fasync the
fourth parameter is to initialize the pointer variable fasync_struct structure
when the application by the fcntl | fasync changed flag, the driver set fasync fops operation function (fd, F_SETEL, flags FASYNC) to performs
off the drive when the need to release fasync_struct culture in file_operations operations concentrated release function also calls fasync_helper release

kill_fasync function

When the device can access, drivers need to send a signal to the application that generated the equivalent of "break." Kill_fastync responsible for sending the signal specified function, kill_fastync following function prototype

void kill_fasync(struct fasync_struct **fp, int sig, int band)
  • fasync_struct to operate: fp
  • sig: a signal to be transmitted
  • band: set to readable POLL_IN, set POLL_OUT writable

Processing applications

1, up signal handler
2, will present the application to tell the kernel process ID
3, enables asynchronous notification

	flags = fcntl(fd,F_GETEL);//获取当前的进程状态
	fcntl(fd,F_SETEL,flags | FASYNC);//开启当前进程异步通知功能

The focus is through the fcntl function sets the process state to FASYNC, after this step, the driver function executes fasync

Experiment code and analysis

Experiment Code

Driver code

struct irqkey_dev
{
    dev_t devid;
	...
    struct fasync_struct *async_queue;
};

void timer_function(unsigned long arg)
{
    unsigned char value;
	...
    //一次完成的按键过程
    if(atomic_read(&dev->releasekey))
    {
        if(dev->async_queue)
            kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
    }
}
static int key_fasync(int fd, struct file *filp, int on)
{
    printk(KERN_EMERG "key_fasync enter!\n");
    struct irqkey_dev *dev = (struct irqkey_dev *)filp->private_data;

    return fasync_helper(fd, filp, on, &dev->async_queue);
}

static int key_release(struct inode *inode,struct file *filp)
{
    printk(KERN_EMERG "key_release enter!\n");
    return key_fasync(-1, filp, 0);
}

Application code

static void sigio_signal_func(int signum)
{
    int err = 0;
    unsigned int keyvalue = 0;

    err = read(fd, &keyvalue, sizeof(keyvalue));
    if(err < 0)
    {

    }
    else
    {
        printf("SIGIO signal! key value = %d\r\n",keyvalue);
    }
    
}
int main(int argc, char *argv[])
{
...
 /*open device*/
 fd = open(filename, O_RDWR);
 if(fd < 0)
 {
     printf("Can't open file %s\r\n", filename);
     return -1;
 }
 printf("Open file %s OK!\r\n", filename);
 
 signal(SIGIO, sigio_signal_func);

 fcntl(fd, F_SETOWN, getpid());
 flags = fcntl(fd, F_GETFD);
 fcntl(fd, F_SETFL, flags | FASYNC);

 while(1)
 {
     sleep(2);
 }
 }

Code Analysis

Driving part

In timer_function, when image stabilization is indeed the key after the key is pressed used kill_fasync () SIGIO release signal, the third parameter is represented by resource-readable POLL_IN
use fasync_helper function to initialize the drive fasync fasync functions, including memory allocation and setting properties
calls the device driver in the driver's release function fasync function (key_fasync ()) the file is deleted from the list of asynchronous notification
using the following statement

return key_fasync(-1, filp, 0);

Part of the application

Signal used to install the application of the SIGIO sigio_signal_func () as a function of the signal processing

signal(SIGIO, sigio_signal_func);

Use fcntl to set this process for the owner of the file, this step is not kernel does not know which process the signals sent

fcntl(fd, F_SETOWN, getpid());

Because asynchronous notification mechanism to enable the equipment needed to set up mechanisms FASYNC

flags = fcntl(fd, F_GETFD);
fcntl(fd, F_SETFL, flags | FASYNC);

to sum up

In order to process signals of a release device in the user space, it has to perform three tasks

  • By F_SETOWN IO control command to set the owner of the device file-based process, this signal can be sent from the device driver for this process is received
  • By F_SETOWN IO control command device file to support FASYNC, that is asynchronous notification mode
  • Function signal connections and signal processing functions by a signal ()

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

  • F_SETOWN support command, can be provided filp-> f_owner process ID corresponding control command in this process. But this work is completed by the kernel, device drivers without treatment
  • When support F_SETFL command, did not put FASYNC logo change, fasync driver () function will be performed. Thus, should the drive fasync advance () function
  • When the device resources available, call kill_fasync () function corresponding excitation signal

A block diagram of the whole mechanism is as follows
Here Insert Picture Description

Published 123 original articles · won praise 598 · views 340 000 +

Guess you like

Origin blog.csdn.net/a568713197/article/details/103145834