现在的位置: 首页 > 综合 > 正文

闲聊linux中的input设备(5) 她那含情脉脉的眼神

2013年03月12日 ⁄ 综合 ⁄ 共 2804字 ⁄ 字号 评论关闭

故事真正要进入高潮部分了。接下来我们来了解一下,我们前面那位美少女是在哪儿被嫁了出去的。

真正的执行者乃input_register_device()函数。

同样来自input core中,我们来看一下她的全貌:

int input_register_device(struct input_dev *dev)

{

       1 static atomic_t input_no = ATOMIC_INIT(0);

       2 struct input_handler *handler;

       3 const char *path;

       4 int error;

 

       5 __set_bit(EV_SYN, dev->evbit);

 

       /*

        * If delay and period are pre-set by the driver, then autorepeating

        * is handled by the driver itself and we don't do it in input.c.

        */

 

       6 init_timer(&dev->timer);

       7 if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {

       8     dev->timer.data = (long) dev;

       9     dev->timer.function = input_repeat_key;

       10    dev->rep[REP_DELAY] = 250;

       11    dev->rep[REP_PERIOD] = 33;

       12 }

 

       13 if (!dev->getkeycode)

       14    dev->getkeycode = input_default_getkeycode;

 

       15 if (!dev->setkeycode)

       16    dev->setkeycode = input_default_setkeycode;

 

       17 snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),

       18    "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);

 

       19 error = device_add(&dev->dev);

       20 if (error)

       21    return error;

 

       22 path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);

       23 printk(KERN_INFO "input: %s as %s/n",

       24    dev->name ? dev->name : "Unspecified device", path ? path : "N/A");

       25 kfree(path);

 

       26 error = mutex_lock_interruptible(&input_mutex);

       27 if (error) {

       28   device_del(&dev->dev);

       29    return error;

       }

 

       30 list_add_tail(&dev->node, &input_dev_list);

 

       31 list_for_each_entry(handler, &input_handler_list, node)

       32    input_attach_handler(dev, handler);

 

       33 input_wakeup_procfs_readers();

 

       34 mutex_unlock(&input_mutex);

 

       35 return 0;

}

这里我在给代码表明代码行数时,为了方便,只标出了那些有代码的行,对于空行,就略了。

1-4行,初始化一些基本变量,以备后文使用。这里我们重点了解一下static atomic_t input_no = ATOMIC_INIT(0); 这里atomic_t表明一个原子变量。记住对于原子变量,不能被并发的访问,比如有两个线程,都是想让nput_no1操作,如果input_no初值为0,当两线程串行访问,当然可以得到我们想要的值2,可以如果是并发呢,两个线程同时访问它,得到的初值都为0并同时为她加1,我们最后看到的值就只增加了一次,即为1。原子变量很好的解决了此类问题。每次只能让一个线程获得它,进行操作,释放,然后第二个线程访问,然后释放,是不是让你想到了自旋锁机制,聪明,他就是一个简化版的自旋锁,不过操作的对象是一个变量,而非一段临界区代码。

5行,设置EV_SYN,让所有的设备都支持它。

6-18行是跟按键有关的,与我们这里无关。暂且不论。

19 error = device_add(&dev->dev);4小结中的device_initialize(&dev->dev);夫唱妇和,共同让我们的input设备中的内嵌dev结构在系统中注册,并在sysfs文件系统中形成相应的文件层次结构。

20-25行,打印此设备在文件系统中的路径。

2634两行代码就是为了防止其中间的临界区代码被并发访问。还记得他在哪儿初始化的吗?正是在我们第4节的input_allocate_device函数中,原句如下:mutex_init(&dev->mutex);为什么要使用互斥体呢,这个问题留到后面分析中间的临界区代码再来讨论。这里mutex_lock_interruptible()用mutex_lock取代,前者表示该可被信号打断,后者则显然不行。

27-29行代码,如果该进程没有获取到互斥量,说明此时已有另外一个程序占有了她。哥们你天生没那命,你前面的所有工作,什么买花,什么请客看电影,都白忙活了,死心吧,放弃一切(device_del(&dev->dev);),回老家,然后慢慢的躺在家里边睡边等,等待前面那位哥们,等待他放手的那一天……

30-33行,很幸运,她还是独身,也等着你的出现,所以情同意和,两小无猜,继续牵手往下走…30行,把该设备添加到input_dev_list中,31 遍历系统中所有已注册的handler链表即input_handler_list,从中找到和自己的Mr.Right..ok,一切顺利函数返回,成功把该input设备嫁出去,任务完成,打道回府。网名叫“西门吹牛”的兄弟要说了,好像漏了点什么?哦,对!前面说到,为什么要使用互斥量了,来防止并发访问这段代码呢?如果此时你还来问我这个问题,我就要骂你,你丫到底有没有在看我文档?

抱歉!评论已关闭.