S5PV210(TQ210)學(xué)習(xí)筆記——按鍵驅(qū)動(dòng)程序
測(cè)試程序代碼:
本文引用地址:http://www.ex-cimer.com/article/201611/322807.htm- #include
- #include
- intmain(){
- intfd=open("/dev/buttons",O_RDWR);
- if(fd<0){
- printf("openerror");;
- return0;
- }
- unsignedcharkey;
- while(1){
- read(fd,&key,1);
- printf("Thekey=%x",key);
- }
- close(fd);
- }
相比輪詢方式的按鍵驅(qū)動(dòng)程序,中斷方式編寫的按鍵驅(qū)動(dòng)程序可以很大程度上節(jié)省CPU資源,因此,推薦使用中斷方式。
二 支持POLL機(jī)制
上面這種方式實(shí)現(xiàn)的按鍵驅(qū)動(dòng)程序有個(gè)弊端,如果我們不按鍵,應(yīng)用程序?qū)?huì)永遠(yuǎn)阻塞在這里,幸運(yùn)的是,linux內(nèi)核提供了poll機(jī)制,可以設(shè)置超時(shí)等待時(shí)間,如果在這個(gè)時(shí)間內(nèi)讀取到鍵值則正常返回,反之則超時(shí)退出。使內(nèi)核支持poll非常簡(jiǎn)單,為file_operations的poll成員提供poll處理函數(shù)即可。
使內(nèi)核支持poll還需要以下幾步:
添加poll頭文件
- #include
編寫poll處理函數(shù):
- staticunsignedbuttons_poll(structfile*file,poll_table*wait){
- unsignedintmask=0;
- poll_wait(file,&button_waitq,wait);
- if(pressed)
- mask|=POLLIN|POLLRDNORM;
- returnmask;
- }
- .poll=buttons_poll,
- #include
- #include
- #include
- #include
- #include
- intmain(intargc,char**argv){
- intfd;
- unsignedcharkey_val;
- intret;
- structpollfdfds[1];
- fd=open("/dev/buttons",O_RDWR);
- if(fd<0){
- printf("cantopen!");
- }
- fds[0].fd=fd;
- fds[0].events=POLLIN;
- while(1){
- ret=poll(fds,1,5000);
- if(ret==0){
- printf("timeout");
- }
- else{
- read(fd,&key_val,1);
- printf("key_val=0x%x",key_val);
- }
- }
- return0;
- }
這樣,應(yīng)用程序可以限制時(shí)間,如果在一定時(shí)間內(nèi)讀取不到鍵值就可以做特殊處理,這種思想在網(wǎng)絡(luò)通信中應(yīng)用廣泛。
三 支持異步機(jī)制
很多情況下,我們的程序在等待按鍵期間需要處理其它任務(wù)而不是在這里空等,這時(shí),就需要采用異步模式了。所謂異步模式,實(shí)際上是采用消息機(jī)制(以本文的按鍵程序?yàn)槔?,即?dāng)驅(qū)動(dòng)程序檢測(cè)到按鍵后發(fā)送消息給應(yīng)用程序,應(yīng)用程序接收到消息后再去讀取鍵值。與前面的兩種模式相比,最大的不同在于異步方式是驅(qū)動(dòng)告訴應(yīng)用程序來讀而不是應(yīng)用程序主動(dòng)去讀。添加異步支持更加簡(jiǎn)單,首先是為file_operations注冊(cè)fasync函數(shù),函數(shù)內(nèi)容如下:
- staticintbuttons_fasync(intfd,structfile*file,inton){
- returnfasync_helper(fd,file,on,&button_async);
- }
- staticssize_tbuttons_read(structfile*file,char__user*data,size_tcount,loff_t*loff){
- if(count!=1){
- printk(KERN_ERR"Thedrivercanonlygiveonekeyvalueonce!");
- return-ENOMEM;
- }
- wait_event_interruptible(button_waitq,pressed);
- pressed=0;
- if(copy_to_user(data,&key_val,1)){
- printk(KERN_ERR"Thedrivercannotcopythedatatouserarea!");
- return-ENOMEM;
- }
- return0;
- }
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- /*sixthdrvtest
- */
- intfd;
- voidmy_signal_fun(intsignum)
- {
- unsignedcharkey_val;
- read(fd,&key_val,1);
- printf("key_val:0x%x",key_val);
- }
- intmain(intargc,char**argv)
- {
- unsignedcharkey_val;
- intret;
- intOflags;
- signal(SIGIO,my_signal_fun);
- fd=open("/dev/buttons",O_RDWR|O_NONBLOCK);
- if(fd<0){
- printf("cantopen!");
- return-1;
- }
- fcntl(fd,F_SETOWN,getpid());
- Oflags=fcntl(fd,F_GETFL);
- fcntl(fd,F_SETFL,Oflags|FASYNC);
- intrest;
- while(1){
- printf("Hello");
- while(rest=sleep(50)){
- sleep(rest);
- }
- }
- return0;
- }
到這里,這個(gè)驅(qū)動(dòng)程序基本上就算可以了,當(dāng)然,還有對(duì)阻塞和非阻塞的支持,同步與互斥的支持,而阻塞與非阻塞無非是加上個(gè)邏輯判斷,同步與互斥根應(yīng)用程序的同步控制也差不多,無非就是信號(hào)量或者原子操作,這里就不多說了,如果有朋友需要這些內(nèi)容可以留言討論。
評(píng)論