在事件处理层()中结构体evdev_client定义了一个环形缓冲区(circular buffer),其原理是用数组的方式实现了一个先进先出的循环队列(circular queue),用以缓存内核驱动上报给用户层的input_event事件。
struct evdev_client {
unsigned int head;//头指针
unsigned int tail;//尾指针
unsigned int packet_head; /* [future] position of the first element of next packet *//包指针
spinlock_t buffer_lock; /* protects access to buffer, head and tail */
struct wake_lock wake_lock;
bool use_wake_lock;
char name[28];
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
int clkid;
bool revoked;
unsigned int bufsize;//循环队列大小
struct input_event buffer[];//循环队列数组
};
packet_head
内核驱动处理一次输入,可能上报一到多个input_event事件,为表示处理完成,会在上报这些input_event事件后再上报一次同步事件。头指针head以input_event事件为单位,记录缓冲区的入口偏移量,而包指针packet_head则以“数据包”(一到多个input_event事件)为单位,记录缓冲区的入口偏移量。
以上内容参照
http://blog.csdn.net/zifehng/article/details/70169512
另外,这里也有一个很好的例子。
http://blog.csdn.net/u013904227/article/details/51168398
这个buffer的作用是,上层OPEN了此节点,但是没有读取此节点的数据的时候,循环buffer会保存128个事件。
如下的代码是进入到事件传输,先入队列head++,如果head == tail 则为满。此时将会把tail往后面移动2个位置(input event,
input sync),填充sync事件。P_head =tail, 初始的状态。
正常情况下入队列,队列没有满,就把head++,最终受到sync信号,并把p_head指向head的位置。
static void __pass_event(struct evdev_client *client,
const struct input_event *event)
{
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
printk("====%s,head=%d,tail=%d,packet_head=%d,%s/n",__func__,client->head,client->tail,client->packet_head,client->name);
if (unlikely(client->head == client->tail)) {
/*
* This effectively "drops" all unconsumed events, leaving
* EV_SYN/SYN_DROPPED plus the newest event in the queue.
*/
client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail].time = event->time;
client->buffer[client->tail].type = EV_SYN;
client->buffer[client->tail].code = SYN_DROPPED;
client->buffer[client->tail].value = 0;
client->packet_head = client->tail;
if (client->use_wake_lock)
wake_unlock(&client->wake_lock);
}
if (event->type == EV_SYN && event->code == SYN_REPORT) {
printk("enter the SYN\n");
client->packet_head = client->head;
if (client->use_wake_lock)
wake_lock(&client->wake_lock);
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}
}
所以可以在读的操作和写的操作,在条件都为head=tail的情况下,分别为空和满。最终读取完数据初始状态是,
client->packet_head=8,client->tail=8,client->head=8。经过log分析应该是同一个数字。
static int evdev_fetch_next_event(struct evdev_client *client,
struct input_event *event)
{
int have_event;
spin_lock_irq(&client->buffer_lock);
have_event = client->packet_head != client->tail;
if (have_event) {
*event = client->buffer[client->tail++];
client->tail &= client->bufsize - 1;
if (client->use_wake_lock &&
client->packet_head == client->tail){
printk("=====client->packet_head=%d,client->tail=%d,client->head\n",client->packet_head,client->tail,client->head);
wake_unlock(&client->wake_lock);
}
}
spin_unlock_irq(&client->buffer_lock);
return have_event;
}