插播一條訊息:火箭官網剛剛公布,姚明徹底告別本賽季。看來退役也是遲早的事情了,其實上大學就一直關注火箭隊,一個主要原因是有姚明,誰讓咱是中國人呢,中國人都是很愛國的,當然個別間諜分子除外。因為姚明,喜歡上了麥迪……如今二人都淪落這般境地,想想讓人心寒。煙花易冷、人事易分啊。好了,不提這些傷心地事兒了。我們做點有勁的事兒,繼續研究我們的evdev 裝置美眉。
前面已經開啟她的心扉了。某位腦殘的兄弟問:“開啟之後幹嘛呢”,還能幹嘛呢?當然是讀了,好,下來我們分析操作集中的第二個函數:evdev_read()深入跟蹤下去:
static ssize_t evdev_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
1 struct evdev_client *client = file->private_data;
2 struct evdev *evdev = client->evdev;
3 struct input_event event;
4 int retval;
5 if (count < input_event_size())
6 return -EINVAL;
7 if (client->head == client->tail && evdev->exist &&
8 (file->f_flags & O_NONBLOCK))
9 return -EAGAIN;
10 retval = wait_event_interruptible(evdev->wait,
11 client->head != client->tail || !evdev->exist);
12 if (retval)
13 return retval;
14 if (!evdev->exist)
15 return -ENODEV;
16 while (retval + input_event_size() <= count &&
17 evdev_fetch_next_event(client, &event)) {
18 if (input_event_to_user(buffer + retval, &event))
return -EFAULT;
19 retval += input_event_size();
}
20 return retval;
}
相信在座的各位,現在分析這個函數也不會有什麼困難。
1行,把在evdev_open裡那個私人資料放到struct evdev_client *client中。
5-6行,如果要copy的位元組數少於一個event的大小,對不起,結束吧。不完整的event對我們來說沒什麼用,別浪費表情。
10-11兩行,wait_event_interruptible(evdev->wait,client->head != client->tail || !evdev->exist);
還記得她嗎?是的,她已經在這裡睡了好久,等待她的的如意郎君把她喚醒。後面的client->head != client->tail || !evdev->exist為條件,條件必須滿足,她才會醒來。
16-19行,每次從client的buffer中取出一個input event資料放到我們這裡的event中,然後把它傳到應用程式層的buffer中,retval記錄總共返回的位元組數。深入input_event_to_user(buffer + retval, &event):
int input_event_to_user(char __user *buffer,
const struct input_event *event)
{
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
return 0;
}
函數copy_to_user就是把一個核心空間buffer放到我們的使用者空間buffer,他的兄弟copy_from_user完成相反的動作。
好了,資料都已經到我們的使用者空間了,現在我們想幹嘛就可以幹嘛了……
至於函數集中的evdev_write、evdev_ioctl等函數我就不一一分析了,怎麼去往她心裏面寫東西,怎麼去操作她,這些東西聽起來是不是有點yellow,我就不好意思再和你一起探討了。這些東西哥們你要自己慢慢去摸索,俗話說的好:“自己動手,豐衣足食”。
到此,整個系列都已分析完了,發現自己理解和分析代碼是一回事,寫出來是另外一回事。還是那句話:兄弟們,我們要多實踐啊,無論是工作還是把妹,你不去實踐,光yy的話,效果還是是相差的很遠的。感謝大家的關注,有任何問題,私下找我討論。
插播一條訊息:火箭官網剛剛公布,姚明徹底告別本賽季。看來退役也是遲早的事情了,其實上大學就一直關注火箭隊,一個主要原因是有姚明,誰讓咱是中國人呢,中國人都是很愛國的,當然個別間諜分子除外。因為姚明,喜歡上了麥迪……如今二人都淪落這般境地,想想讓人心寒。煙花易冷、人事易分啊。好了,不提這些傷心地事兒了。我們做點有勁的事兒,繼續研究我們的evdev 裝置美眉。
前面已經開啟她的心扉了。某位腦殘的兄弟問:“開啟之後幹嘛呢”,還能幹嘛呢?當然是讀了,好,下來我們分析操作集中的第二個函數:evdev_read()深入跟蹤下去:
static ssize_t evdev_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
1 struct evdev_client *client = file->private_data;
2 struct evdev *evdev = client->evdev;
3 struct input_event event;
4 int retval;
5 if (count < input_event_size())
6 return -EINVAL;
7 if (client->head == client->tail && evdev->exist &&
8 (file->f_flags & O_NONBLOCK))
9 return -EAGAIN;
10 retval = wait_event_interruptible(evdev->wait,
11 client->head != client->tail || !evdev->exist);
12 if (retval)
13 return retval;
14 if (!evdev->exist)
15 return -ENODEV;
16 while (retval + input_event_size() <= count &&
17 evdev_fetch_next_event(client, &event)) {
18 if (input_event_to_user(buffer + retval, &event))
return -EFAULT;
19 retval += input_event_size();
}
20 return retval;
}
相信在座的各位,現在分析這個函數也不會有什麼困難。
1行,把在evdev_open裡那個私人資料放到struct evdev_client *client中。
5-6行,如果要copy的位元組數少於一個event的大小,對不起,結束吧。不完整的event對我們來說沒什麼用,別浪費表情。
10-11兩行,wait_event_interruptible(evdev->wait,client->head != client->tail || !evdev->exist);
還記得她嗎?是的,她已經在這裡睡了好久,等待她的的如意郎君把她喚醒。後面的client->head != client->tail || !evdev->exist為條件,條件必須滿足,她才會醒來。
16-19行,每次從client的buffer中取出一個input event資料放到我們這裡的event中,然後把它傳到應用程式層的buffer中,retval記錄總共返回的位元組數。深入input_event_to_user(buffer + retval, &event):
int input_event_to_user(char __user *buffer,
const struct input_event *event)
{
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
return 0;
}
函數copy_to_user就是把一個核心空間buffer放到我們的使用者空間buffer,他的兄弟copy_from_user完成相反的動作。
好了,資料都已經到我們的使用者空間了,現在我們想幹嘛就可以幹嘛了……
至於函數集中的evdev_write、evdev_ioctl等函數我就不一一分析了,怎麼去往她心裏面寫東西,怎麼去操作她,這些東西聽起來是不是有點yellow,我就不好意思再和你一起探討了。這些東西哥們你要自己慢慢去摸索,俗話說的好:“自己動手,豐衣足食”。
到此,整個系列都已分析完了,發現自己理解和分析代碼是一回事,寫出來是另外一回事。還是那句話:兄弟們,我們要多實踐啊,無論是工作還是把妹,你不去實踐,光yy的話,效果還是是相差的很遠的。感謝大家的關注,有任何問題,私下找我討論。