异步 IO
IO分類
IO類型
1、異步通知:一旦設備就緒,則主動通知應用程序。異步通知意味則設備通知自身可訪問,實現了異步I/O.由內核向應用程序發信號,類似中斷。
2、阻塞I/O意味著一直等待設備可訪問后再訪問。
3、非阻塞IO,設備不可訪問,則馬上返回。
4、輪詢I/O,使用poll()查詢設備是否可訪問。
Linux 中最為常見信號的含義及其默認操作,詳見Linux信號列表.pdf。
重點關注的信號:
- SIGIO 鍵盤輸入或者當文件可讀、寫
- SIGINT 終端中斷 ctrl+c
- SIGQUIT 終端退出 ctrl+\
信號實例一
#include <signal.h> #include <stdio.h>#include <stdlib.h> /*自定義信號處理函數*/ void my_func(int sign_no) {if(sign_no==SIGINT)printf("I have get SIGINT\n");else if(sign_no==SIGQUIT)printf("I have get SIGQUIT\n"); } int main() {printf("Waiting for signal SIGINT or SIGQUIT \n ");/*發出相應的信號,并跳轉到信號處理函數處*/signal(SIGINT, my_func);signal(SIGQUIT, my_func);while(1); }信號實例二
#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <unistd.h> #define MAX_LEN 100 /*接收到異步讀信號后的動作*/ void input_handler(int signum) { char data[MAX_LEN]; int len; len=read(STDIN_FILENO,data,MAX_LEN); data[len]=0; printf("input available:%s\n",data); }main() { int oflags; //啟動信號驅動機制 signal(SIGIO, input_handler); //讓input_handler()處理SIGIO信號 fcntl(STDIN_FILENO, F_SETOWN, getpid()); oflags = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);while(1); }異步IO的實現1
首先在結構體中添加異步結構體指針:
struct globalfifo_dev { struct cdev cdev; /*cdev結構體*/ unsigned int current_len; /*fifo有效數據長度*/ unsigned char mem[GLOBALFIFO_SIZE]; /*全局內存*/ struct semaphore sem; /*并發控制用的信號量*/ //wait_queue_head_t r_wait; /*阻塞讀用的等待隊列頭*/ //wait_queue_head_t w_wait; /*阻塞寫用的等待隊列頭*/ struct fasync_struct *async_queue; /* 異步結構體指針,用于讀 */ };實現驅動設備的fasync()函數
/* globalfifo fasync函數*/ static int globalfifo_fasync(int fd, struct file *filp, int mode) { struct globalfifo_dev *dev = filp->private_data; return fasync_helper(fd, filp, mode, &dev->async_queue); }在相應的資源可以獲得的地方添加釋放sigio信號,比如在中斷,讀函數,寫函數中,這里舉例寫函數中:
/*globalfifo寫操作*/ static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) {……writeok…../* 產生異步讀信號 */ if (dev->async_queue) kill_fasync(&dev->async_queue, SIGIO, POLL_IN);…… }在文件關閉時,在release方法將文件從異步通知隊列中刪除。
/*文件釋放函數*/ int globalfifo_release(struct inode *inode, struct file *filp) { /* 將文件從異步通知列表中刪除 */ globalfifo_fasync( - 1, filp, 0); return 0; }file_operations中添加fasync函數指針。
/*文件操作結構體*/ static const struct file_operations globalfifo_fops ={.owner = THIS_MODULE, .read = globalfifo_read, .write = globalfifo_write, //.ioctl = globalfifo_ioctl, .poll = globalfifo_poll, .open = globalfifo_open, .release = globalfifo_release, .fasync = globalfifo_fasync, };測試程序
void input_handler(int signum) {相應的處理,比如說程序中異步讀通知的話,這里就可以實現讀的操作 } main() {int fd, oflags;fd = open("dev/fifo, O_RDWR, S_IRUSR | S_IWUSR");signal(SIGIO,input_handler);//讓input_handler()處理SIGIO信號fcntl(fd, F_SETOWN, getpid());//第二個參數的定義是設置異步io所有權,所以這句話的意思是設置本進程為fd文件的所有者oflags = fcntl(fd, F_GETFL);//獲得文件狀態標志fcntl(fd, F_SETFL, oflags | FASYNC);//用戶程序必須對訪問的設備文件設置FASYNC標志。F_SETFL命令表示設置文件狀態標志位.while(1); }總結
- 上一篇: MySQL数据库常见的几个问题
- 下一篇: MSN无法登陆错误汇总