1. 程式人生 > >linux字元裝置驅動程式scull例項

linux字元裝置驅動程式scull例項

這個例子還是比較完整的講述了字元驅動開發的過程,尤其字元驅動程式的設計流程,包括測試在內。

【1.系統環境】

該驅動程式在UBUNTU10.04LTS編譯通過,系統核心為linux-2.6.32-24(可使用uname -r 命令來檢視當前核心的版本號)

由於安裝UBUNTU10.04LTS時,沒有安裝LINUX核心原始碼,因此需要在www.kernel.org下載LINUX原始碼,下載linux-2.6.32.22.tar.bz2(與系統執行的LINUX核心版本儘量保持一致),使用如下命令安裝核心:

1.解壓核心

cd /us/src

tar jxvf linux-2.6.32.22.tar.bz2


2.為系統的include建立連結檔案

cd /usr/include
rm -rf asm linux scsi
ln -s /usr/src/linux-2.6.32.22/include/asm-generic asm
ln -s /usr/src/linux-2.6.32.22/include/linux linux
ln -s /usr/src/linux-2.6.32.22/include/scsi scsi


LINUX核心原始碼安裝完畢

【2.驅動程式程式碼】

/******************************************************************************
*Name: memdev.c
*Desc: 字元裝置驅動程式的框架結構,該字元裝置並不是一個真實的物理裝置,
* 而是使用記憶體來模擬一個字元裝置
*Parameter:
*Return:
*Author: yoyoba(

[email protected])
*Date: 2010-9-26
*Modify: 2010-9-26
********************************************************************************/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.
h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#include "memdev.h"

static mem_major = MEMDEV_MAJOR;

module_param(mem_major,int, S_IRUGO);

struct mem_dev *mem_devp;/*裝置結構體指標*/

struct cdev cdev;

/*檔案開啟函式*/
int mem_open(struct inode*inode, struct file *filp)
{
    struct mem_dev *dev;
    
    /*獲取次裝置號*/
    int num = MINOR(inode->i_rdev);

    if (num>= MEMDEV_NR_DEVS)
            return -ENODEV;
    dev = &mem_devp[num];
    
    /*將裝置描述結構指標賦值給檔案私有資料指標*/
    filp->private_data= dev;
    
    return 0;
}

/*檔案釋放函式*/
int mem_release(struct inode*inode, struct file *filp)
{
  return 0;
}

/*讀函式*/
static ssize_t mem_read(structfile *filp,char __user *buf,size_t size, loff_t*ppos)
{
  unsigned long p= *ppos;
  unsigned intcount = size;
  int ret = 0;
  struct mem_dev *dev= filp->private_data;/*獲得裝置結構體指標*/

  /*判斷讀位置是否有效*/
  if (p >= MEMDEV_SIZE)
    return 0;
  if (count> MEMDEV_SIZE - p)
    count = MEMDEV_SIZE- p;

  /*讀資料到使用者空間*/
  if (copy_to_user(buf,(void*)(dev->data+ p),count))
  {
    ret = - EFAULT;
  }
  else
  {
    *ppos +=count;
    ret = count;
    
    printk(KERN_INFO "read %d bytes(s) from %d/n", count, p);
  }

  return ret;
}

/*寫函式*/
static ssize_t mem_write(structfile *filp,const char __user*buf, size_t size, loff_t *ppos)
{
  unsigned long p= *ppos;
  unsigned intcount = size;
  int ret = 0;
  struct mem_dev *dev= filp->private_data;/*獲得裝置結構體指標*/
  
  /*分析和獲取有效的寫長度*/
  if (p >= MEMDEV_SIZE)
    return 0;
  if (count> MEMDEV_SIZE - p)
    count = MEMDEV_SIZE- p;
    
  /*從使用者空間寫入資料*/
  if (copy_from_user(dev->data+ p, buf,count))
    ret = - EFAULT;
  else
  {
    *ppos +=count;
    ret = count;
    
    printk(KERN_INFO "written %d bytes(s) from %d/n", count, p);
  }

  return ret;
}

/* seek檔案定位函式 */
static loff_t mem_llseek(structfile *filp, loff_t offset,int whence)
{
    loff_t newpos;

    switch(whence){
      case 0:/* SEEK_SET */
        newpos = offset;
        break;

      case 1:/* SEEK_CUR */
        newpos = filp->f_pos+ offset;
        break;

      case 2:/* SEEK_END */
        newpos = MEMDEV_SIZE -1 + offset;
        break;

      default:/* can't happen */
        return -EINVAL;
    }
    if ((newpos<0)|| (newpos>MEMDEV_SIZE))
     return -EINVAL;
     
    filp->f_pos= newpos;
    return newpos;

}

/*檔案操作結構體*/
static conststruct file_operations mem_fops =
{
  .owner = THIS_MODULE,
  .llseek = mem_llseek,
  .read = mem_read,
  .write = mem_write,
  .open = mem_open,
  .release = mem_release,
};

/*裝置驅動模組載入函式*/
static int memdev_init(void)
{
  int result;
  int i;

  dev_t devno = MKDEV(mem_major, 0);

  /* 靜態申請裝置號*/
  if (mem_major)
    result = register_chrdev_region(devno, 2,"memdev");
  else /* 動態分配裝置號 */
  {
    result = alloc_chrdev_region(&devno, 0, 2,"memdev");
    mem_major = MAJOR(devno);
  }
  
  if (result< 0)
    return result;

  /*初始化cdev結構*/
  cdev_init(&cdev,&mem_fops);
  cdev.owner = THIS_MODULE;
  cdev.ops =&mem_fops;
  
  /* 註冊字元裝置 */
  cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
   
  /* 為裝置描述結構分配記憶體*/
  mem_devp = kmalloc(MEMDEV_NR_DEVS* sizeof(struct mem_dev), GFP_KERNEL);
  if (!mem_devp)/*申請失敗*/
  {
    result = - ENOMEM;
    goto fail_malloc;
  }
  memset(mem_devp, 0,sizeof(struct mem_dev));
  
  /*為裝置分配記憶體*/
  for (i=0; i< MEMDEV_NR_DEVS; i++)
  {
        mem_devp[i].size= MEMDEV_SIZE;
        mem_devp[i].data= kmalloc(MEMDEV_SIZE, GFP_KERNEL);
        memset(mem_devp[i].data, 0, MEMDEV_SIZE);
  }
    
  return 0;

  fail_malloc:
  unregister_chrdev_region(devno, 1);
  
  return result;
}

/*模組解除安裝函式*/
static void memdev_exit(void)
{
  cdev_del(&cdev);/*登出裝置*/
  kfree(mem_devp);/*釋放裝置結構體記憶體*/
  unregister_chrdev_region(MKDEV(mem_major, 0), 2);/*釋放裝置號*/
}

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("GPL");

module_init(memdev_init);
module_exit(memdev_exit);


/************************
*memdev.h
************************/

#ifndef _MEMDEV_H_
#define _MEMDEV_H_

#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 260/*預設的mem的主裝置號*/
#endif

#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 2/*裝置數*/
#endif

#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 4096
#endif

/*mem裝置描述結構體*/
struct mem_dev
{
  char *data;
  unsigned long size;
};

#endif /* _MEMDEV_H_ */


【3.編譯驅動程式模組】

Makefile檔案的內容如下:

ifneq ($(KERNELRELEASE),)

obj-m:=memdev.o

else

KERNELDIR:=/lib/modules/$(shell uname -r)/build

PWD:=$(shell pwd)

default:

 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

 rm -rf *.o *.mod.c *.mod.o *.ko

endif


切換到root下,執行make時,如果UBUNTU是使用虛擬機器安裝的,那麼執行make時,不要在ubuntu和windows的共享目錄下,否則會出錯。

[email protected]:~# make
make -C /lib/modules/2.6.32-24-generic/build M=/root modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-24-generic'
  CC

­ /root/memdev.o
/root/memdev.c:15: warning: type defaults to ‘int’ in declaration of ‘mem_major’
/root/memdev.c: In function ‘mem_read’:
/root/memdev.c:71: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long unsigned int’
/root/memdev.c: In function ‘mem_write’:
/root/memdev.c:99: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long unsigned int’
  Building modules, stage 2.
  MODPOST 1 modules
  CC /root/memdev.mod.o
  LD

­ /root/memdev.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-24-generic'


ls檢視當前目錄的內容

[email protected]:~# ls
Makefile memdev.h memdev.mod.c memdev.o Module.symvers
memdev.c memdev.ko memdev.mod.o modules.order


這裡的memdev.ko就是生成的驅動程式模組。

通過insmod命令把該模組插入到核心

[email protected]:~# insmod memdev.ko


檢視插入的memdev.ko驅動

[email protected]:~# cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
260 memdev
  6 lp
  7 vcs
 10 misc
 13 input
 14 sound
 21 sg
 29 fb
 99 ppdev
108 ppp
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
226 drm
251 hidraw
252 usbmon
253 bsg
254 rtc

Block devices:
  1 ramdisk
259 blkext
  7 loop
  8 sd
  9 md
 11 sr
 65 sd
 66 sd
 67 sd
 68 sd
 69 sd
 70 sd
 71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
252 device-mapper
253 pktcdvd
254 mdp


可以看到memdev驅動程式被正確的插入到核心當中,主裝置號為260,該裝置號為memdev.h中定義的#define MEMDEV_MAJOR 260。

如果這裡定義的主裝置號與系統正在使用的主裝置號衝突,比如主裝置號定義如下:#define MEMDEV_MAJOR 254,那麼在執行insmod命令時,就會出現如下的錯誤:

[email protected]:~# insmod memdev.ko
insmod: error inserting 'memdev.ko': -1 Device or resource busy


檢視當前裝置使用的主裝置號

[email protected]:~# cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  6 lp
  7 vcs
 10 misc
 13 input
 14 sound
 21 sg
 29 fb
 99 ppdev
108 ppp
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
226 drm
251 hidraw
252 usbmon
253 bsg
254 rtc

Block devices:
  1 ramdisk
259 blkext
  7 loop
  8 sd
  9 md
 11 sr
 65 sd
 66 sd
 67 sd
 68 sd
 69 sd
 70 sd
 71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
252 device-mapper
253 pktcdvd
254 mdp


發現字元裝置的254主裝置號為rtc所使用,因此會出現上述錯誤,解決方法只需要在memdev.h中修改主裝置號的定義即可。

【4.編寫應用程式,測試該驅動程式】

首先應該在/dev/目錄下建立與該驅動程式相對應的檔案節點,使用如下命令建立:

[email protected]:/dev# mknod memdev c 260 0


使用ls檢視建立好的驅動程式節點檔案

[email protected]:/dev# ls -al memdev
crw-r--r-- 1 root root 260, 0 2010-09-26 17:28 memdev


編寫如下應用程式,來對驅動程式進行測試。

/******************************************************************************
*Name: memdevapp.c
*Desc: memdev字元裝置驅動程式的測試程式。先往memedev裝置寫入內容,然後再
* 從該裝置中把內容讀出來。
*Parameter:
*Return:
*Author: yoyoba([email protected])
*Date: 2010-9-26
*Modify: 2010-9-26
********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/fcntl.h>

int main()
{
 int fd;
 char buf[]="this is a example for character devices driver by yoyoba!";//寫入memdev裝置的內容

 char buf_read[4096];//memdev裝置的內容讀入到該buf中

 
 if((fd=open("/dev/memdev",O_RDWR))==-1)//開啟memdev裝置

  printf("open memdev WRONG!/n");
 else
  printf("open memdev SUCCESS!/n");
  
 printf("buf is %s/n",buf);

 write(fd,buf,sizeof(buf));//把buf中的內容寫入memdev裝置

 
 lseek(fd,0,SEEK_SET);//把檔案指標重新定位到檔案開始的位置

 
 read(fd,buf_read,sizeof(buf));//把memdev裝置中的內容讀入到buf_read中

 
 printf("buf_read is %s/n",buf_read);
 
 return 0;
}


編譯並執行該程式

[email protected]:/mnt/xlshare# gcc -o mem memdevapp.c

[email protected]:/mnt/xlshare# ./mem
open memdev SUCCESS!
buf is this is a example for character devices driver by yoyoba!
buf_read is this is a example for character devices driver by yoyoba!


表明驅動程式工作正常。。。

【5.LINUX是如何make驅動程式模組的】

Linux核心是一種單體核心,但是通過動態載入模組的方式,使它的開發非常靈活 方便。那麼,它是如何編譯核心的呢?我們可以通過分析它的Makefile入手。以下是 一個簡單的hello核心模組的Makefile.
ifneq ($(KERNELRELEASE),)
obj-m:=hello.o
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
        $(MAKE) -C $(KERNELDIR)  M=$(PWD) modules
clean:
        rm -rf *.o *.mod.c *.mod.o *.ko
endif
當我們寫完一個hello模組,只要使用以上的makefile。然後make一下就行。 假設我們把hello模組的原始碼放在/home/study/prog/mod/hello/下。 當我們在這個目錄執行make時,make是怎麼執行的呢? LDD3第二章第四節“編譯和裝載”中只是簡略地說到該Makefile被執行了兩次, 但是具體過程是如何的呢?
首先,由於make 後面沒有目標,所以make會在Makefile中的第一個不是以.開頭 的目標作為預設的目標執行。於是default成為make的目標。make會執行 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules shell是make內部的函式,假設當前核心版本是2.6.13-study,所以$(shell uname -r)的結果是 2.6.13-study 這裡,實際執行的是
make -C /lib/modules/2.6.13-study/build M=/home/study/prog/mod/hello/ modules
/lib/modules/2.6.13-study/build是一個指向核心原始碼/usr/src/linux的符號連結。 可見,make執行了兩次。第一次執行時是讀hello模組的原始碼所在目錄/home/s tudy/prog/mod/hello/下的Makefile。第二次執行時是執行/usr/src/linux/下的Makefile時.
但是還是有不少令人困惑的問題: 1.這個KERNELRELEASE也很令人困惑,它是什麼呢?在/home/study/prog/mod/he llo/Makefile中是沒有定義這個變數的,所以起作用的是else…endif這一段。不 過,如果把hello模組移動到核心原始碼中。例如放到/usr/src/linux/driver/中, KERNELRELEASE就有定義了。 在/usr/src/linux/Makefile中有 162 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION) 這時候,hello模組也不再是單獨用make編譯,而是在核心中用make modules進行 編譯。 用這種方式,該Makefile在單獨編譯和作為核心一部分編譯時都能正常工作。
2.這個obj-m := hello.o什麼時候會執行到呢? 在執行:
make -C /lib/modules/2.6.13-study/build M=/home/study/prog/mod/hello/ modules
時,make 去/usr/src/linux/Makefile中尋找目標modules: 862 .PHONY: modules 863 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) 864 @echo ' Building modules, stage 2.'; 865 $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
可以看出,分兩個stage: 1.編譯出hello.o檔案。 2.生成hello.mod.o hello.ko 在這過程中,會呼叫 make -f scripts/Makefile.build obj=/home/study/prog/mod/hello 而在 scripts/Makefile.build會包含很多檔案: 011 -include .config 012 013 include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile) 其中就有/home/study/prog/mod/hello/Makefile 這時 KERNELRELEASE已經存在。 所以執行的是: obj-m:=hello.o
關於make modules的更詳細的過程可以在scripts/Makefile.modpost檔案的註釋 中找到。如果想檢視make的整個執行過程,可以執行make -n。

相關推薦

linux字元裝置驅動程式scull例項

這個例子還是比較完整的講述了字元驅動開發的過程,尤其字元驅動程式的設計流程,包括測試在內。 【1.系統環境】 該驅動程式在UBUNTU10.04LTS編譯通過,系統核心為linux-2.6.32-24(可使用uname -r 命令來檢視當前核心的版本號) 由於安裝UBUNTU10.04LTS時,沒有安裝LI

從零開始寫linux字元裝置驅動程式(一)(基於友善之臂tiny4412開發板)

從這篇博文開始,我將開始手把手教會大家寫linux裝置驅動程式這是開篇,如何來寫第一個字元裝置驅動程式。首先,寫一個最簡單的字元裝置驅動程式需要什麼?或者說我們需要了解什麼?1、每一個字元裝置至少需要有一個裝置號2、裝置號 = 主裝置號 + 次裝置號3、同一類裝置的主裝置號一

Linux字元裝置驅動程式的一個簡單示例

一.原始碼: // memdev.c #define MEMDEV_MAJOR 254 /*預設的mem的主裝置號*/ #define MEMDEV_NR_DEVS 2 /*裝置數*/ #define MEMDEV_SIZE 4096 /*mem裝置描述結構體

韋東山嵌入式Linux學習筆記之——第12課第8節 字元裝置驅動程式之定時器防抖動

注:本文部分內容摘自《魚樹學員筆記》。 當按鍵按得比較快的時候,這裡出現了兩次中斷值,也即產生了抖動。 這裡產生了“抖動”,按鍵是機械開關,按下鬆開時裡面的金屬彈片可能抖動了好幾次。這種抖動產生了多次“脈衝”導致多次中斷。 方法: 使用定時器來防抖動。

字元裝置驅動程式的三種寫法

驅動工程師如何去寫驅動程式? 要看原理圖。確定如何去操作硬體。 對於點亮led燈來說,確定引腳,檢視晶片手冊,確定如何去操作引腳,要設定哪些暫存器,如何設定這些暫存器才可以讓這個引腳輸出高電平或者低電平。 寫驅動程式 驅動程式起封裝作用,如何封裝。應用程式要操作硬體需要o

字元裝置驅動程式之非同步通知

非同步通知:      驅動程式的所謂非同步通知,指的是應用程式不是主動對驅動程式進行操作,而是驅動程式查詢到有事件發生或者有資料發生變化的時候通知應用程式。角色發生了變化,應用程式由主動改為被動執行。 比如按鍵驅動: 1、要不斷進行查詢引腳狀

Linux字元裝置驅動模型--字元裝置的註冊

當我們編寫字元裝置驅動程式的時候,在進行字元裝置物件cdev的分配、初始化,裝置號的註冊這些初始化階段之後,就可以將它加入到系統中,這樣才能使用這個字元裝置。將一個字元裝置加入到系統中呼叫的函式時cdev_add,核心原始碼如下: int cdev_add(struct cdev *

Linux 字元裝置驅動結構(二)—— 自動建立裝置節點

      上一篇我們介紹到建立裝置檔案的方法,利用cat /proc/devices檢視申請到的裝置名,裝置號。 第一種是使用mknod手工建立:mknod filename type major minor 第二種是自動建立裝置節點:利用u

Linux 字元裝置驅動結構(一)—— cdev 結構體、裝置號相關知識解析

一、字元裝置基礎知識 1、裝置驅動分類       linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。使用驅動程式: 字元裝置:是指只能一個位元組一個位元組讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後資料。

Linux字元裝置驅動註冊三種方法以及核心分析

       Linux驅動是使用者訪問底層硬體的橋樑,驅動有可以簡單分成三類:字元裝置、塊裝置、網路裝置。其中最多的是字元裝置,其中字元裝置的註冊方法主要有三種:雜項設備註冊、早期字元設備註冊、標準字元設備註冊。以及詳細介紹各類方法註冊。 開發環境: PC:WMwork

淺析字元裝置驅動程式__register_chrdev_region

在 2.4 的核心我們使用 register_chrdev(0, “hello”, &hello_fops) 來進行字元裝置裝置節點的分配,這種方式每一個主裝置號只能存放一種裝置,它們使用相同的 file_operation 結構體,也就是說核心最多支

linux字元裝置驅動模型

一.雜項裝置驅動模型 雜項的主裝置號固定為10,只有255個次裝置號。可以直接生成驅動核心。 1.需要確定每個模型都會用到的檔案操作方法集合指標 2.確定核心的結構體 static struct miscdevice abc 確定三個引數,第一個為次裝置號,第二個是次裝

Linux字元裝置驅動

一、字元裝置基礎 字元裝置:是指只能一個位元組一個位元組進行讀寫操作的裝置,不能隨機讀取裝置中的某一資料、讀取資料要按照先後資料。字元裝置是面向流的裝置,常見的字元裝置有滑鼠、鍵盤、串列埠、控制檯和LED等。 一般每個字元裝置或者塊裝置都會在/dev目錄(可以是任意目錄,這樣是為了統一)下對應一個裝置檔案

linux裝置驅動程式示例(適用於高版本核心3.16.0

1. 字元裝置與塊裝置的 I/O 操作主要有如下不同點:    (1)塊裝置只能以塊為單位接受輸入和返回輸出,而字元裝置則以位元組為單位。大多數裝置是字元裝置,因為它們不需要緩衝而且不以固定塊大小進行操作。    (2)塊裝置對於 I/O 請求有對應的緩衝區,因此它們可以選擇

1--linux字元裝置驅動

1. 編寫一個簡單的字元裝置框架 *****hello.c***** #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <

Linux 字元裝置驅動結構(三)—— file、inode結構體及chardevs陣列等相關知識解析

       先看下面這張圖,這是Linux 中虛擬檔案系統、一般的裝置檔案與裝置驅動程式值間的函式呼叫關係;         上面這張圖展現了一個應用程式呼叫字元裝置驅動的過程, 在裝置驅動程式的設計中,一般而言,會關心 file 和 inode 這兩個結構體  

字元裝置驅動程式——定時器按鍵消抖

實現方式 需要設定的結構體 struct timer_list { struct list_head entry; unsigned long expires; void (*function)(unsigned long); unsigned long data; struct tvec_

字元裝置驅動程式——按鍵中斷之互斥阻塞操作

一、互斥操作 在程式設計中,引入了物件互斥鎖的概念,來保證共享資料操作的完整性。每個物件都對應於一個可稱為" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個執行緒訪問該物件。 實現方式 原子操作 原子操作指的是在執行過程中不會被別的程式碼路徑所中斷的操作。 常用

字元裝置驅動程式——按鍵中斷之非同步通知

一、驅動程式的實現 1、定義static struct fasync_struct *newdrv_async; 2、加入 static struct file_operations new_drv_fops = { .fasync =new_drv_fasync, }; static

字元裝置驅動程式——按鍵中斷poll機制

編譯環境 ubunt 16.04 arm-linux-gcc 4.3.2 linux-3.4.2 zj2440 poll的作用是把當前的檔案指標掛到等待佇列。 對於一個按鍵事件: 1、查詢方法:在while(1)中不斷迴圈呼叫read(fd, &key_val, 1)查詢,不