Wei Dongshan uboot_kernel_root file system study notes 5.10-lesson 005_character device driver_section 010_character device driver asynchronous notification

Application: Actively read the hardware status ①Query
method: very resource-consuming ②Interrupt
method: the read function always sleeps and never returns
③poll: specify the sleep time

The driver triggers the application, and the application reads the
asynchronous notification signal. Once the device is ready, it actively informs the application to access it. In this way, applications that use non-blocking IO do not need to poll whether the device is accessible, and achieve the purpose of reducing CPU consumption. Similar to the concept of "interrupt" on hardware, the more accurate term is "signal-driven asynchronous IO". Signal: It is the simulation of the interrupt mechanism at the software level.
In principle, the process receives a signal (software layer) <==> (hardware layer) the processor receives an interrupt.

Kill command: The kill command in Linux is used to terminate the operation of a specified process (terminate a process), and is a common command for process management under Linux. Usually, you can use the Ctrl+C key to terminate a foreground process. However, for a background process, you must use the kill command to terminate. We need to use tools such as ps/pidof/pstree/top to get the process PID, and then use the kill command to Kill the process. The kill command terminates the corresponding process by sending a specified signal to the process. By default, the TERM signal number 15 is used. The TERM signal will terminate all processes that cannot catch the signal. For those processes that can capture the signal, use the kill signal number 9 to forcefully "kill" the process.
kill -USER1 (a signal) PID (specified process number)
eg:
1. View the process number
Insert picture description here
2. kill -USER1 833

  1. Goal: When a button is pressed, the driver notifies the application
  2. Register signal processing function? application
  3. Who signaled? Driver signaling
  4. To whom? Application, the application needs to tell the driver its PID number
  5. How to send it? The driver calls the kill_fasynfunction to send

Look at the implementation code below

In order to make the device support asynchronous notification mechanism, the following 3 tasks are involved in the driver:

  1. Support F_SETOWN command, can set filp->f_owner as 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 be processed.
  2. Supports the processing of F_SETFL commands. When the FASYNC flag changes, the fasync() function in the driver will be
    executed. 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

A driver

  1. Define the structure:static struct fasync_struct *button_async;
  2. Interrupt handling function:
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
    
    
	...
	kill_fasync (&button_async, SIGIO, POLL_IN);//发送的信号类型:SIGIO
	...
}

Who will initialize the button_asyncstructure?

  1. fifth_drv_fasyncFunction initialization button_asyncstructure
static struct file_operations sencod_drv_fops = {
    
    
    .owner   =  THIS_MODULE,   
    .open    =  fifth_drv_open,     
	.read	 =	fifth_drv_read,	   
	.release =  fifth_drv_close,
	.poll    =  fifth_drv_poll,
	.fasync	 =  fifth_drv_fasync,			//
};

static int fifth_drv_fasync (int fd, struct file *filp, int on)
{
    
    
	printk("driver: fifth_drv_fasync\n");
	return fasync_helper (fd, filp, on, &button_async);//这里初始化button_async结构体
}
  1. fifth_drv_fasyncWhen is the function called? It .fasyncwill be called when the app program calls the driver .
//把自己的进程号pid告诉驱动程序;
//支持 F_SETOWN 命令,能在这个控制命令处理中设置 filp->f_owner 为对应进程 ID。不过此项工作已由内核完成,设备驱动无须处理。
 app > fcntl(fd,F_SETOWN,pid) 
 //读出F_GETFL
 //支持 F_SETFL 命令的处理,每当 FASYNC 标志改变时,驱动程序中的 fasync()函数将得以执行。驱动中应该实现 fasync()函数。
 app > Oflags = fcntl(fd,F_GETFL)
 app > fcnl(fd,F_SETFL,oflags | FASYNC)

Two applications

  1. Declare signal response function and response signal type
//信号响应函数:my_signal_fun
//相应信号类型:SIGIO
signal(SIGIO, my_signal_fun);
  1. Signal response function definition
//从fd中读取按键值到key_val
void my_signal_fun(int signum)
{
    
    
	unsigned char key_val;
	read(fd, &key_val, 1);
	printf("key_val: 0x%x\n", key_val);
}

When the interrupt service function of the driver finds a signal, it sends the signal directly to the app program, and the app program jumps to the signal processing function my_signal_fun.

//发给谁?
//把自己的进程号pid告诉驱动程序;
//getpid()函数表示获取的进程号
fcntl(fd, F_SETOWN, getpid());

//改变FASYNC标记,最终会调用到驱动的fasync > fasync_helper:初始化/释放fasync_struct
//驱动程序中的 fasync()函数将得以执行
Oflags = fcntl(fd, F_GETFL); 
fcntl(fd, F_SETFL, Oflags | FASYNC);//设置文件描述符标志

Three simple analysis of fasync_helper function

Call: fasync_helper (fd, filp, on, &button_async)
Function: Declare the prototype of the structure button_asyncinitialization
function:

int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
int fd= fd;
struct file * filp = filp;
int on = on;
struct fasync_struct **fapp = &button_async

Function definition:

int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
{
    
    
	...
	//1. 参数on控制,如果为on分配一个结构体new
	if (on) {
    
    
		new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
		if (!new)
			return -ENOMEM;
	}
	write_lock_irq(&fasync_lock);
	for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
    
    
		if (fa->fa_file == filp) {
    
    
			if(on) {
    
    
				fa->fa_fd = fd;
				kmem_cache_free(fasync_cache, new);
			} else {
    
    
				*fp = fa->fa_next;
				kmem_cache_free(fasync_cache, fa);
				result = 1;
			}
			goto out;
		}
	}
	//与1.对应,刚刚分配的结构体new进行初始化后,赋给fapp即&button_async
	if (on) {
    
    
		new->magic = FASYNC_MAGIC;
		new->fa_file = filp;
		new->fa_fd = fd;
		new->fa_next = *fapp;
		*fapp = new;
		result = 1;
	}
out:
	write_unlock_irq(&fasync_lock);
	return result;
}

Guess you like

Origin blog.csdn.net/xiaoaojianghu09/article/details/104334782