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