我們先看下input的註冊過程:
input_register_device(input_dev):
int input_register_device(struct input_dev *dev)
if (!dev->getkeycode)//如果沒設定,則設定成預設的
dev->getkeycode = input_default_getkeycode;
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
dev_set_name(&dev->dev, "input%ld",
(unsigned long) atomic_inc_return(&input_no) - 1);//按順序地去定義input序號
error = device_add(&dev->dev);//將input dev新增到sys系統中,包括建立一些input的屬性檔案
if (error)
return error;
path = kobject_get_path(&dev->dev.kobj, gfp_kernel);//這裡路徑是上面device_add產生的
printk(kern_info "input: %s as %s\n",
dev->name ? dev->name : "unspecified device", path ? path : "n/a");
kfree(path);
error = mutex_lock_interruptible(&input_mutex);
if (error)
list_add_tail(&dev->node, &input_dev_list);//新增到input裝置列表裡面
list_for_each_entry(handler, &input_handler_list, node)//對input handler列表中的每個handler都進行匹配,這裡input_handler_list怎麼來的呢?我們在 input_register_handler找到它的形成過程
input_attach_handler(dev, handler);//匹配dev和handler
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
return 0;
}我們看下input_attach_handler(dev, handler):
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
input_match_device(handler->id_table, dev):
static const struct input_device_id *input_match_device(const struct input_device_id *id,
struct input_dev *dev)
return null;
}該函式會對handler中的每個id都進行查詢,先根據id->flags設定去比較,然後比較具體的位,match_bit定義如下:
#define match_bit(bit, max) \
for (i = 0; i < bits_to_longs(max); i++) \
if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
break; \
if (i != bits_to_longs(max)) \
continue;
可以看出來是id->bit[i]與dev->bit[i]比較。
從整體上看,匹配的過程還算比較簡單。分析中有幾個新的地方input_handler_list和handler->connect。
其實這些都是input子系統最頂層做的工作,最頂層可以有evdev,joydev,mousedev等,當然使用者完全可以構建乙個自己的dev。我們就挑選evdev做分析吧,也是最常用的一種。
static const struct input_device_id evdev_ids = , /* matches all devices */
, /* terminating zero entry */
};module_device_table(input, evdev_ids);
static struct input_handler evdev_handler = ;
static int __init evdev_init(void)
evdev初始化是註冊了handler:
int input_register_handler(struct input_handler *handler)
input_table[handler->minor >> 5] = handler;//放到input_table
}list_add_tail(&handler->node, &input_handler_list);//新增到handler列表中,這樣就形成了input_handler_list
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);//這邊也進行匹配了,所以無論是handler還是dev註冊都會呼叫匹配函式
input_wakeup_procfs_readers();
out:
mutex_unlock(&input_mutex);
return retval;
}我們下面分析一下evdev_connect:
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
evdev = kzalloc(sizeof(struct evdev), gfp_kernel);
if (!evdev)
return -enomem;
init_list_head(&evdev->client_list);
spin_lock_init(&evdev->client_lock);
mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);
dev_set_name(&evdev->dev, "event%d", minor);//evdev的名字,即event*
evdev->exist = 1;
evdev->minor = minor;
evdev->handle.dev = input_get_device(dev);//將dev賦值給handle
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;//將handler賦值給handle
evdev->handle.private = evdev;
//可以看出handle將dev和handler聯絡到一塊了
evdev->dev.devt = mkdev(input_major, evdev_minor_base + minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;
device_initialize(&evdev->dev);
error = input_register_handle(&evdev->handle);//註冊handle,其實就是將handle再跟dev和handler分別聯絡起來,這樣三者就真正地互相聯絡到一塊了
if (error)
goto err_free_evdev;
error = evdev_install_chrdev(evdev);//把evdev新增到evdev_table中
if (error)
goto err_unregister_handle;
error = device_add(&evdev->dev);//將evdev新增到/sys/中
if (error)
goto err_cleanup_evdev;
return 0;
err_cleanup_evdev:
evdev_cleanup(evdev);
err_unregister_handle:
input_unregister_handle(&evdev->handle);
err_free_evdev:
put_device(&evdev->dev);
return error;
}我們先解釋input_register_handle(&evdev->handle):
int input_register_handle(struct input_handle *handle)
將handle分別新增到dev和handler的h_list中,這樣三者真正地聯絡起來了,可以互相訪問。
我們可以看到evdev才是真正使用者可以操作的裝置,evdev中的handle把handler和dev聯絡到了一塊,同時將evdev新增到了sys中。
Linux 我對Vmstat的理解
首先,在公司的伺服器上,有時候會出現top命令中cpu的記憶體和負載很高的情況,我們要如何檢視具體的原因,這個時候,就要用到vmstat命令,來進行仔細分析,系統中記憶體,程序,cpu,硬碟讀寫,swap分割槽等的運 況 root web110 vmstat 2 5procs memory swap...
我對SNS我理解
模仿也要做得比真的還好,比如qq,它的業務包括客戶端都是模仿別人的,但能做得像它那樣,的確不容易。sns在國內肯定能火的,不過現在的sns 只是太跟風了,沒有了自己的特點,很多的sns 很難看出它到底還是不是sns,或者它到底去哪個方向?自己都沒有弄清楚。所以sns在國內是很有機遇的。其實在當前經濟...
Python之我對閉包理解1
閉包 針對函式而言,是在在函式中提出的概念 條件 1.外部函式中定義了內部函式 即有函式巢狀 2.外部函式有返回值 3.外部函式返回的值是 內部函式名 即函式入口位址 為方便記憶不搞混淆,我們這裡可以說返回的是函式名 4.內部函式呼叫 引用 了外部函式的變數 不引用不叫嚴格的閉包 格式 def 外部...