Android系统--输入系统(一)必备的Linux知识_inotify和epoll
Android系統--輸入系統(一)必備的Linux知識_inotify和epoll
引入
1. 筆記本電腦插入外接鍵盤,兩個鍵盤都可以使用
a. 鍵盤即插即用--如何檢測鍵盤的接入和拔出
hotplug機制:內核發現鍵盤接入或撥出之后啟動hotplug進程,進程發出信號告訴輸入系統,輸入系統處理
inotify機制:輸入系統使用inotify檢測/dev/input的節點變化
b. 可用使用多鍵盤--如何知道哪個鍵盤被按下
- epoll機制:可以檢測多個事件
c. 如何使用inotify和epoll機制:
(1) inotify使用(用于檢測目錄或者文件的變化)
初始化得到文件句柄--fd=inotify_init();
檢測對象--inotify_add_watch(fd,目錄/文件,創建/刪除);
對象變化--read();返回一個或者多個結構體:struct inotify_event
范例代碼:
inotify.c
*Author : LKQ*Date : 2017-2-23*Desc : use inotify watch dir change*參考: frameworks\native\services\inputflinger\EventHub.cpp*//*Usage: inotify <dir> */#include <unistd.h>#include <stdio.h>#include <sys/inotify.h>#include <string.h>#include <errno.h>int read_process_inotify_fd(int fd){int res;char event_buf[512];int event_size;int event_pos = 0;struct inotify_event *event;/* read */ res = read(fd, event_buf, sizeof(event_buf)); //return a struct if(res < (int)sizeof(*event)) {if(errno == EINTR)return 0;printf("could not get event, %s\n", strerror(errno));return -1;} //procee : read a and more inotify_event//deal with each struct while(res >= (int)sizeof(*event)) {event = (struct inotify_event *)(event_buf + event_pos);//printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");if(event->len) {if(event->mask & IN_CREATE) {printf("create file: %s\n", event->name);} else {printf("delete file: %s\n", event->name);}}event_size = sizeof(*event) + event->len;res -= event_size;event_pos += event_size;}return 0;}int main(int argc,char **argv){int mINotifyFd;int result;if(argc != 2){printf("Usage : %s <dir> \n",argv[1]);}/*1. inotify init*/mINotifyFd = inotify_init(); /*2. add watch*/result = inotify_add_watch(mINotifyFd, argv[1], IN_DELETE | IN_CREATE); /*3. read*/while (1){read_process_inotify_fd(mINotifyFd);}return 0;}使用過程:
gcc -o inotify inotify.c
mkdir tmp
./inotify tmp &
echo > tmp/1
echo > tmp/2
rm tmp/1 tmp/2
(2) epoll使用(用于檢測多個文件:1. 有無數據可供讀取;2. 有無空間寫入)
初始化得到文件句柄--fd=epoll_create();
對于每一個文件執行epoll_ctl(fd,EPOLL_CRTL_ADD,...);表示監測該文件的行為
epoll_wait();等待某個文件可用epoll_ctl(fd,EPOLL_CRTL_DEL,...);
范例代碼:
epoll.c
/**Author : LKQ*Date : 2017-2-23*Desc :how to use epoll*參考: frameworks\native\services\inputflinger\EventHub.cpp*//* usage: epoll <file1> [file2] [file3] ... */#include <stdio.h>#include <sys/epoll.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#if 0typedef union epoll_data {void *ptr;int fd;uint32_t u32;uint64_t u64;} epoll_data_t;#endif#define DATA_MAX_LEN 512int add_to_epoll(int fd, int epollFd){int result;struct epoll_event eventItem;memset(&eventItem, 0, sizeof(eventItem));eventItem.events = EPOLLIN;eventItem.data.fd = fd;result = epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &eventItem);return result;}void rm_from_epoll(int fd, int epollFd){epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, NULL);}int main(int argc,char **argv){int mEpollFd;int i;char buf[DATA_MAX_LEN];// Maximum number of signalled FDs to handle at a time.static const int EPOLL_MAX_EVENTS = 16;// The array of pending epoll events and the index of the next event to be handled.struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];if (argc < 2){printf("Usage: %s <file1> [file2] [file3] ...\n", argv[0]);return -1;}/*1. epoll create*/mEpollFd = epoll_create(8); /*2. for each file:* open it* add it to epoll: epoll_ctl(...EPOLL_CTL_ADD...)*/for(i=1;i<argc;i++){//int tmpFd = open(argv[i], O_RDONLY|O_NONBLOCK);int tmpFd = open(argv[i],O_RDWR);add_to_epoll(tmpFd,mEpollFd);}/*3. epoll_wait */while (1){int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, -1);for (i = 0; i < pollResult; i++){printf("Reason: 0x%x\n", mPendingEventItems[i].events);int len = read(mPendingEventItems[i].data.fd, buf, DATA_MAX_LEN);buf[len] = '\0';printf("get data: %s\n", buf);}}/*remove epoll*/for(i=1;i<argc;i++){rm_from_epoll(mPendingEventItems[i].data.fd,mEpollFd);}return 0;}操作方法:
gcc -o epoll epoll.c
mkdir tmp
mkfifo tmp/1 tmp/2 tmp/3
./epoll tmp/1 tmp/2 tmp/3 &
echo aaa > tmp/1
echo bbb > tmp/2
echo ccc > tmp/3
補充:
當fifo文件以 O_RDONLY|O_NONBLOCK 方式打開,會出現不斷返回epoll_wait,導致崩潰。
原因:使用fifo是, 我們的epoll程序是reader;echo aa > tmp/1 是writer
a. 如果reader以 O_RDONLY|O_NONBLOCK打開FIFO文件,writer寫入數據時, epoll_wait會立刻返回;
當writer關閉FIFO之后, reader再次調用epoll_wait, 它也會立刻返回(原因是EPPLLHUP, 描述符被掛斷)
b. 如果reader以 O_RDWR打開FIFO文件當writer寫入數據時, epoll_wait會立刻返回;
當writer關閉FIFO之后, reader再次調用epoll_wait, 它并不會立刻返回, 而是繼續等待有數據
轉載于:https://www.cnblogs.com/lkq1220/p/6434184.html
總結
以上是生活随笔為你收集整理的Android系统--输入系统(一)必备的Linux知识_inotify和epoll的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AntData.ORM框架 之 读写分离
- 下一篇: 生活中的实验 —— 磁铁的使用