"I once had a sincere love in front of me, but I don't know how to cherish it. I once had a promise, but I felt very cherished. I must talk about it today .."
Let's talk about the asynchronous notification example mentioned in the previous section.CodeFirst, let's go to the Code:
Struct Globalbench o_dev { Struct Cdev; /* Cdev struct */ Unsigned Int Current_len; /* Valid FIFO Data Length */ Unsigned Char Mem [global1_o_size]; /* Global memory */ Struct Semaphore SEM;/* Semaphores used for concurrency control */ Wait_queue_head_t r_wait; /* The waiting queue header for blocking Reading */ Wait_queue_head_t w_wait; /* The waiting queue header for blocking write */ Struct Fasync_struct * async_queue; /* Asynchronous struct pointer for reading */ }; /* File release function */ Int Global1_o_release ( Struct Inode * inode, Struct File * filp ){ /* Delete the file from the asynchronous notification list */ Globalmem_fasync (-1, filp, 0 ); Return 0 ;}Static Int Global1_o_fasync ( Int FD, Struct File * filp, Int Mode ){ Struct Globalizer o_dev * Dev = filp-> private_data; Return Fasync_helper (FD, filp, mode, & Dev-> async_queue );} /* Globalfifo write operation */ Static Ssize_t global1_o_write ( Struct File * filp, Const Char _ User * Buf, size_t count, loff_t * PPOs ){ Struct Globalizer o_dev * Dev = filp-> private_data; // Obtain the device struct pointer Int RET; declare_waitqueue (wait, current ); // Define the waiting queue Down (& Dev-> SEM ); // Obtain the semaphore Add_wait_queue (& Dev-> w_wait, & wait ); // Enter the write wait queue Header /* Wait until the FIFO is not full */ If (Dev-> current_len = global1_o_size ){ If (Filp-> f_flags & o_nonblock) // If the access is not blocked {Ret =-eagain; Goto Out;} _ set_current_state (task_interruptible ); // Change the process status to sleep Up (& Dev-> SEM); schedule (); // Schedule other processes for execution If (Signal_pending (current )) // If it is because of a wake-up signal {Ret =-erestartsys; Goto Out2;} Down (& Dev-> SEM ); // Obtain the semaphore } /* Copy from user space to kernel space */ If (Count> global1_o_size-Dev-> current_len) Count = global1_o_size-Dev-> current_len;If (Copy_from_user (Dev-> mem + Dev-> current_len, Buf, count) {ret =-efault; Goto Out ;} Else {Dev-> current_len + = count; printk (kern_info" Written % d bytes (s), current_len: % d \ n ", Count, Dev-> current_len); wake_up_interruptible (& Dev-> r_wait ); // Wake up the read wait queue /* Generate asynchronous reading signal */ If (Dev-> async_queue) kill_fasync (& Dev-> async_queue, sigio, poll_in); ret = count;} Out: Up (& Dev-> SEM ); // Release the semaphore Out2: remove_wait_queue (& Dev-> w_wait, & wait );// Remove from the affiliated waiting queue Header Set_current_state (task_running ); Return RET;} The test is given below Program :
# Include... // Receives the asynchronous reading signal. Void Input_handler ( Int SIGNUM ){ Printf (" Receive a signal from globalfifo, signalnum: % d \ n ", SIGNUM );} Int Main (){ Int FD, oflags; FD = Open ("/Dev/globalfifo ", O_rdwr, s_irusr | s_iwusr ); If (FD! =-1 ){ // Start the signal Driving Mechanism Signal (Sigio, input_handler ); // Enable input_handler () to process sigio Signals Fcntl (FD, f_setown, getpid (); oflags = fcntl (FD, f_getfl); fcntl (FD, f_setfl, oflags | fasync ); While (1) {sleep (100 );}} Else { Printf (" Device open failure \ n ");}}After the driver is loaded and the device node is created, run the above program. When new data is written to/dev/globalfilfo through ECHO, input_handler will be called. Echo 0>/dev/globalereoreceive a signal from globalfifo, signalnum: 29 Echo 0>/dev/globalereoreceive a signal from globalfifo, signalnum: 29
Echo 0>/dev/globalereoreceive a signal from globalfifo, signalnum: 29
Through the actual example above, Mr. Wang understands that my promise has also been fulfilled. Next time we will start something more advanced ..