您的位置:首页 > 运维架构 > Linux

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

2012-06-29 22:57 411 查看
故事真正要进入高潮部分了。接下来我们来了解一下,我们前面那位美少女是在哪儿被嫁了出去的。
真正的执行者乃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_no加1操作,如果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行,打印此设备在文件系统中的路径。
26、34两行代码就是为了防止其中间的临界区代码被并发访问。还记得他在哪儿初始化的吗?正是在我们第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设备嫁出去,任务完成,打道回府。网名叫“西门吹牛”的兄弟要说了,好像漏了点什么?哦,对!前面说到,为什么要使用互斥量了,来防止并发访问这段代码呢?如果此时你还来问我这个问题,我就要骂你,你丫到底有没有在看我文档?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: