输入子系统linux编程知识

思考:

1、键盘的即插即用,怎么监测键盘的接入和拔出?

可以通过hotplug机制和inotify机制实现:1、hotplug机制:内核发现键盘接入和拔出后启动hotplug进程发送消息告诉输入系统。hotplug进程复杂,android系统不使用hotplug。2、inotify:输入系统使用inotify监测目录/dev/input变化。作用: 监控一个目录下文件的增加、删除事件。

inotify测试程序:参考android源码: frameworks\native\services\inputflinger\EventHub.cpp

struct inotify_event {

__s32   wd; /* watch descriptor */

__u32   mask;   /* watch mask 表明add /remove 事件  IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE*/

__u32   cookie; /* cookie to synchronize two events */

__u32   len;    /* length (including nulls) of namename长度 */

char    name[0];    /* stub for possible name 指针,指向 add/remove 的文件名字*/

};
#include <unistd.h>
#include <stdio.h>
#include <sys/inotify.h>
#include <string.h>
#include <errno.h>


/*
 *参考: frameworks\native\services\inputflinger\EventHub.cpp
 */

/*Usage: inotify <dir> */

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));

    if(res < (int)sizeof(*event)) {
        if(errno == EINTR)
            return 0;
        printf("could not get event, %s\n", strerror(errno));
        return -1;
    }

    /* process
     * 读到的数据是1个或多个inotify_event
     * 它们的长度不一样
     * 逐个处理
     */

    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[0]);
        return -1;
    }

    /* inotify_init */

    mINotifyFd = inotify_init();

    /* add watch */
    result = inotify_add_watch(mINotifyFd, argv[1], IN_DELETE | IN_CREATE);

    /* read */
    while (1)
    {
        read_process_inotify_fd(mINotifyFd);
    }

    return 0;
}

gcc -o inotify inotify.c
mkdir tmp
./inotify tmp /&
cd tmp/
echo >1 创建文件 并且写入
echo >2
rm 1 2

2、多键盘的使用,怎么知道哪个键盘被按下?
通过使用epoll机制实现,作用:检测一个或多个文件的可读可写属性的变化。
epoll测试程序:参考android源码: frameworks\native\services\inputflinger\EventHub.cpp

数据结构:
 // 感兴趣的事件和被触发的事件  
struct epoll_event {  
    __uint32_t events; /* Epoll 事件 :  EPOLLIN、EPOLLOUT等感兴趣的事件 */  
    epoll_data_t data; /* ☆下面的联合体结构:一般用作保存事件的fd或者其他,根据需求赋值  */  
};  



(1)events
    events可以是以下几个宏的集合:
    EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
    EPOLLOUT:表示对应的文件描述符可以写;
    EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
    EPOLLERR:表示对应的文件描述符发生错误;
    EPOLLHUP:表示对应的文件描述符被挂断;
    EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
    EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里


(2)data 
    //保存触发事件的某个文件描述符相关的数据(与具体使用方式有关,加入检测前赋值!!)  

    typedef union epoll_data {  
        void *ptr;  
        int fd;      // 保存文件描述符
        __uint32_t u32;  
        __uint64_t u64;  
    } epoll_data_t; 
#include <sys/epoll.h>
#include <stdio.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 500

/* usage: epoll <file1> [file2] [file3] ... */

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;
    }

    /* epoll_create */
    mEpollFd = epoll_create(8);

    /* 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);
    }

    /* 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);
            //sleep(3);
        }

    }

    return 0;
}

gcc -o inotify inotify.c
mkdir tmp
./inotify tmp /&
cd tmp/
echo >1 创建文件 并且写入
echo >2
rm 1 2

epoll测试程序

gcc -o epoll epoll.c
cd  tmp/
ls
mkfifo 1
mkfifo 2

./epoll tmp/1 tmp/2 &
echo aaa >> tmp/1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值