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

本文详细介绍了inotify和epoll两种Linux机制的工作原理及其应用场景。inotify用于监测文件系统的变动,如文件的创建与删除等;epoll则用于高效地处理多个文件描述符的读写事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 0

typedef union epoll_data {

   void        *ptr;

   int          fd;

   uint32_t     u32;

   uint64_t     u64;

} epoll_data_t;

#endif

#define DATA_MAX_LEN 512

int 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值