日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Android系统--输入系统(一)必备的Linux知识_inotify和epoll

發布時間:2025/4/14 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

struct inotify_event {__s32 wd;__u32 mask; //發生的變化狀態__u32 cookie;__u32 len; //name的長度char name[0]; //發生變化的文件}
范例代碼:

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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。