1、註冊訊號處理函式
應用程式根據驅動程式所使用的訊號來設定訊號的處理函式,應用程式使用 signal 函式來
置訊號的處理函式。
sighandler_t signal(int signum, sighandler_t handler));
第乙個引數指定訊號的值, 第二個引數指定針對前面訊號值的處理函式, 若為 sig_ign, 表示忽略該信
號; 若為 sig_dfl, 表示採用系統預設方式處理訊號; 若為使用者自定義的函式, 則訊號**獲到後, 該函式
將被執行
2、將本應用程式的程序號告訴給核心
使用 fcntl(fd, f_setown, getpid())將本應用程式的程序號告訴給核心。
3、開啟非同步通知
使用如下兩行程式開啟非同步通知:
flags = fcntl(fd, f_getfl); /* 獲取當前的程序狀態 */
fcntl(fd, f_setfl, flags | fasync); /* 開啟當前程序非同步通知功能 */
重點就是通過 fcntl 函式設定程序狀態為 fasync,經過這一步,驅動程式中的 fasync 函
就會執行。
例項
void sigint_handler(int num)
int main(void)
1 、首先我們需要在驅動程式中定義乙個fasync_struct結構體指標變數,
2、如果要使用非同步通知,需要在裝置驅動中實現file_operations操作集中的fasync函式,此函式格式如下所示:
int (*fasync) (int fd, struct file *filp, int on)
fasync
函式裡面一般通過呼叫
fasync_helper
函式來初始化前面定義的
fasync_struct
結構體指標,
fasync_helper
函式原型如下:
fasync_helper函式的前三個引數就是fasync函式的那三個引數,第四個引數就是要初始化的fasync_struct結構體指標變數。當應用程式通過「fcntl(fd, f_setfl, flags | fasync)」改變fasync標記的時候,驅動程式file_operations操作集中的fasync函式就會執行。
static int ***_fasync(int fd, struct file *filp, int on)
static struct file_operations ***_ops = ;
3、在關閉驅動檔案的時候需要在file_operations操作集中的release函式中釋放fasync_struct,fasync_struct的釋放函式同樣為fasync_helper,release函式引數參考例項如下:
static int ***_release(struct inode *inode, struct file *filp)
4、驅動層如何通知應用層
kill_fasync函式
當裝置可以訪問的時候,驅動程式需要向應用程式發出訊號,相當於產生「中斷」。kill_fasync函式負責傳送指定的訊號,kill_fasync函式原型如下所示:
void kill_fasync(struct fasync_struct **fp, int sig, int band)
函式引數和返回值含義如下:
fp:要操作的fasync_struct。
sig:要傳送的訊號。
band:可讀時設定為poll_in,可寫時設定為poll_out。
返回值:無。
9.4.1.1 aio概念
9.4.1.1 aio系列api:
引數aiocb:結構體包含了傳輸的所有資訊,以及為aio操作準備的使用者空間快取區
返回值
int aio_read( struct aiocb *aiocbp );
引數aiocb:結構體包含了傳輸的所有資訊,以及為aio操作準備的使用者空間快取區
返回值
int aio_write( struct aiocb *aiocbp );
int aio_error( struct aiocb *aiocbp );
ssize_t aio_return( struct aiocb *aiocbp );
int aio_suspend( const struct aiocb *const cblist, int n, const struct timespec *timeout );
如果要取消對某個給定檔案描述符的所有請求,使用者需要提供這個檔案的描述符以及乙個對 aiocbp 的 null 引用
使用 aio_error()來驗證每個 aio 請求
int aio_cancel( int fd, struct aiocb *aiocbp );
list :是乙個 aiocb 引用的列表,最大元素的個數是由 nent 定義的
int lio_listio( int mode, struct aiocb *list, int nent, struct sigevent *sig );
io_setup( )
//initializes an asynchronous context for the current process
io_submit( )
//submits one or more asynchronous i/o operations
io_getevents( )
//gets the completion status of some outstanding asynchronous i/o operations
io_cancel( )
//cancels an outstanding i/o operation
io_destroy( )
//removes an asynchronous context for the current process
字元裝置:必須明確應支援aio(極少數是非同步i/o操作)
字元裝置驅動程式中file_operations 包含 3 個與 aio 相關的成員函式,
ssize_t (*aio_read) (struct kiocb *iocb, char *buffer, size_t count, loff_t offset);
ssize_t (*aio_write) (struct kiocb *iocb, const char *buffer, size_t count, loff_t offset);
int (*aio_fsync) (struct kiocb *iocb, int datasync);
linux中驅動非同步通知
驅動程式執行在核心空間中,應用程式執行在使用者空間中,兩者是不能直接通訊的。但在實際應用中,在裝置已經準備好的時候,我們希望通知使用者程式裝置已經ok,使用者程式可以讀取了,這樣應用程式就不需要一直查詢該裝置的狀態,從而節約了資源,這就是非同步通知。好,那下乙個問題就來了,這個過程如何實現呢?簡單,...
linux裝置驅動筆記
雖然並不做linux有關的東西,但是記錄下點點滴滴,以備不時之需 驅動程式的編譯 make 驅動程式按模組安裝 inmod ko 執行這個命令之前首先要獲得root許可權,否則會報錯,1 operation not permmitt 檢視模組安裝情況 lsmod 解除安裝相關模組 rmmod 安裝或...
linux驅動學習之非同步通知
非同步通知是裝置狀態改變後主動通知應用程式,這樣應用程式就不需要阻塞或查詢裝置了。應用通過訊號來處理核心的非同步通知,上次使用poll select來查詢裝置的可讀狀態,下面這個例子類似,不同的是當裝置有資料時主動通知應用去讀資料。應用的c 很簡單,主要設定對訊號的處理方式,核心有資料時會收到sig...