1. 程式人生 > >在linux下裝置檔案讀寫例項

在linux下裝置檔案讀寫例項

一般在linux下裝置分為字元裝置和塊裝置。
字元裝置是指裝置傳送和接收資料以字元的形式進行;而塊裝置則以整個資料緩衝區的形式進行。
在linux下對任何的操作可以看成是對裝置的操作。簡單而言之,可以是看成對裝置檔案的讀寫操作。
那麼,怎樣對linux 的裝置檔案進行讀寫呢?我們通過一段小程式來模擬linux下對字元裝置檔案的讀寫操作。
程式如下(本程式基於linux2.6核心):

1.定義自己的裝置檔案驅動
// my_driver.c
MODULE_LICENSE("GPL");
// 定義自己的操作型別
struct file_operations my_driver_fops =
 {
     read:
         my_driver_read,
     write:
         my_driver_write,
 };

static int my_ver = 0;
static struct semaphore sem; 
static wait_queue_head_t outq;
static int flag = 0;

// 初始化檔案裝置
static int __init my_driver_init(void)
{
 int ret;
 ret = register_chrdev(MAJOR_NUM, "my_driver", &my_driver_fops);
 if (ret) {
  printk("my_driver register failure/n");
 } else {
  printk("my_driver register success/n");
  init_MUTEX(&sem);
  init_waitqueue_head(&outq);
 }

 return ret;
}

// 退出裝置操作
static void __exit my_driver_exit(void)
{
 int ret;
 ret = unregister_chrdev(MAJOR_NUM, "my_driver");

 if (ret)
  printk("my_driver unregister failure/n");
 else
  printk("my_driver unregister success/n");
}

// 讀取裝置檔案
static ssize_t my_driver_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
 if (wait_event_interruptible(outq, flag != 0))
  return - ERESTARTSYS;

 if(down_interruptible(&sem))
  return - ERESTARTSYS;

 flag = 0;
 if (copy_to_user(buf, &my_ver, sizeof(int))) {
  up(&sem);
  return - EFAULT;
 }

 up(&sem);
 return sizeof(int);
}

// 寫裝置檔案
static ssize_t my_driver_write(struct file *filp, const char *buf, size_t len,loff_t *off)
{
 if (down_interruptible(&sem))
  return - ERESTARTSYS;

 if (copy_from_user(&my_ver, buf, sizeof(int))) {
  up(&sem);
  return - EFAULT;
 }

 up(&sem);
 flag = 1;
 wake_up_interruptible(&outq);
 return sizeof(int);
}

// 自定義模組的載入與解除安裝
module_init(my_driver_init);
module_exit(my_driver_exit);

在這個驅動裡my_driver_read、my_driver_write這兩個函式分別實現核心空間與使用者空間的資料交換,module_init(my_driver_init)、module_exit(my_driver_exit)用於模組的載入與解除安裝。

2.測試程式,為了驗證我們的驅動是否正確我們編寫了以下測試程式。
// my_read.c
int main(void)
{
 int fd, num;
 fd = open("/dev/my_driver",O_RDWR,S_IRUSR | S_IWUSR);
 
 if(fd != -1) {
  while(1) {
   read(fd,&num,sizeof(int));
   printf("the my_driver is %d/n",num);
   if(0 == num) {
    close(fd);
    break;
   }
  }
 } else{
   printf("device open failure/n");
 }

 return 0;
}
讀取裝置檔案資料。讀取裝置檔案了my_var的內容。

// my_write.c
int main(void)
{
 int fd, num;
 fd = open("/dev/my_driver",O_RDWR,S_IRUSR | S_IWUSR);
 
 if(fd != -1) {
  while(1) {
   printf("please input the my_driver!/n");
   scanf("%d",&num);
   write(fd,&num,sizeof(int));
   if(0 == num){
    close(fd);
    break;
   }
  }
 } else {
      printf("open my_driver failure/n");
 }

 return 0;
}
寫裝置檔案,將資料寫到檔案的my_ver裡。

以上就完成了自定義裝置檔案的讀寫操作,在這裡我們針對裝置檔案定義了相應的驅動程式,在裡面我們實現了
資料在裝置檔案和使用者之間的傳遞功能,是不是很簡單?
編譯程式生成my_driver.ko, insmod my_driver.ko, 執行my_write,my_read,看試試可以讀寫檔案。
呵呵,自己動手試試吧!

完整程式下載