我對linux理解之input一

2021-06-08 14:31:31 字數 4706 閱讀 3829

我們先看下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 外部...