<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM的嵌入式Linux移植體驗之設(shè)備驅(qū)動

          ARM的嵌入式Linux移植體驗之設(shè)備驅(qū)動

          作者: 時間:2012-11-13 來源:網(wǎng)絡(luò) 收藏

          static struct block_device_operations mtd_fops =
          {
           owner: THIS_MODULE,
           open: mtdblock_open,
           release: mtdblock_release,
           ioctl: mtdblock_ioctl
          };

          static void mtd_notify_add(struct mtd_info* mtd)
          {
           …
          }

          static void mtd_notify_remove(struct mtd_info* mtd)
          {
           if (!mtd || mtd->type == MTD_ABSENT)
            return;

           devfs_unregister(devfs_rw_handle[mtd->index]);
          }

          int __init init_mtdblock(void)
          {
           int i;

           spin_lock_init(mtdblks_lock);
           /* this lock is used just in kernels >= 2.5.x */
           spin_lock_init(mtdblock_lock);

           #ifdef CONFIG_DEVFS_FS
           if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, mtd_fops))
           {
            printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",
          MTD_BLOCK_MAJOR);
            return -EAGAIN;
           }

           devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
           register_mtd_user(notifier);
           #else
            if (register_blkdev(MAJOR_NR,DEVICE_NAME,mtd_fops)) {
             printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",
          MTD_BLOCK_MAJOR);
            return -EAGAIN;
           }
           #endif

          /* We fill it in at open() time. */
          for (i=0; i MAX_MTD_DEVICES; i++) {
           mtd_sizes[i] = 0;
           mtd_blksizes[i] = BLOCK_SIZE;
          }
          init_waitqueue_head(thr_wq);
          /* Allow the block size to default to BLOCK_SIZE. */
          blksize_size[MAJOR_NR] = mtd_blksizes;
          blk_size[MAJOR_NR] = mtd_sizes;

          BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), mtdblock_request, mtdblock_lock);

          kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
          return 0;
          }

          static void __exit cleanup_mtdblock(void)
          {
           leaving = 1;
           wake_up(thr_wq);
           down(thread_sem);
           #ifdef CONFIG_DEVFS_FS
            unregister_mtd_user(notifier);
            devfs_unregister(devfs_dir_handle);
            devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
           #else
            unregister_blkdev(MAJOR_NR,DEVICE_NAME);
           #endif
           blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
           blksize_size[MAJOR_NR] = NULL;
           blk_size[MAJOR_NR] = NULL;
          }

          module_init(init_mtdblock);
          module_exit(cleanup_mtdblock);

            從上述源代碼中我們發(fā)現(xiàn),塊設(shè)備也以與字符設(shè)備register_chrdev、unregister_ chrdev 函數(shù)類似的方法進行設(shè)備的注冊與釋放:

          int register_blkdev(unsigned int major, const char *name, struct block_device_operations *bdops);
          int unregister_blkdev(unsigned int major, const char *name);

            但是,register_chrdev使用一個向 file_operations 結(jié)構(gòu)的指針,而register_blkdev 則使用 block_device_operations 結(jié)構(gòu)的指針,其中定義的open、release 和 ioctl 方法和字符設(shè)備的對應(yīng)方法相同,但未定義 read 或者 write 操作。這是因為,所有涉及到塊設(shè)備的 I/O 通常由系統(tǒng)進行緩沖處理。

            塊驅(qū)動程序最終必須提供完成實際塊 I/O 操作的機制,在 Linux 當中,用于這些 I/O 操作的方法稱為"request(請求)"。在塊設(shè)備的注冊過程中,需要初始化request隊列,這一動作通過blk_init_queue來完成,blk_init_queue函數(shù)建立隊列,并將該驅(qū)動程序的 request 函數(shù)關(guān)聯(lián)到隊列。在模塊的清除階段,應(yīng)調(diào)用 blk_cleanup_queue 函數(shù)。

            本例中相關(guān)的代碼為:

          BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), mtdblock_request, mtdblock_lock);
          blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));

            每個設(shè)備有一個默認使用的請求隊列,必要時,可使用 BLK_DEFAULT_QUEUE(major) 宏得到該默認隊列。這個宏在 blk_dev_struct 結(jié)構(gòu)形成的全局數(shù)組(該數(shù)組名為 blk_dev)中搜索得到對應(yīng)的默認隊列。blk_dev 數(shù)組由內(nèi)核維護,并可通過主設(shè)備號索引。blk_dev_struct 接口定義如下:

          struct blk_dev_struct {
           /*
           * queue_proc has to be atomic
           */
           request_queue_t request_queue;
           queue_proc *queue;
           void *data;
          };

            request_queue 成員包含了初始化之后的 I/O 請求隊列,data 成員可由驅(qū)動程序使用,以便保存一些私有數(shù)據(jù)。

            request_queue定義為:

          struct request_queue
          {
           /*
           * the queue request freelist, one for reads and one for writes
           */
           struct request_list rq[2];

           /*
           * Together with queue_head for cacheline sharing
           */
           struct list_head queue_head;
           elevator_t elevator;

           request_fn_proc * request_fn;
           merge_request_fn * back_merge_fn;
           merge_request_fn * front_merge_fn;
           merge_requests_fn * merge_requests_fn;
           make_request_fn * make_request_fn;
           plug_device_fn * plug_device_fn;
           /*
           * The queue owner gets to use this for whatever they like.
           * ll_rw_blk doesn't touch it.
           */
           void * queuedata;

           /*
           * This is used to remove the plug when tq_disk runs.
           */
           struct tq_struct plug_tq;

           /*
           * Boolean that indicates whether this queue is plugged or not.
           */
           char plugged;

           /*
           * Boolean that indicates whether current_request is active or
           * not.
           */
           char head_active;

           /*
           * Is meant to protect the queue in the future instead of
           * io_request_lock
           */
           spinlock_t queue_lock;

           /*
           * Tasks wait here for free request
           */
           wait_queue_head_t wait_for_request;
          };

            下圖表征了blk_dev、blk_dev_struct和request_queue的關(guān)系:

            下圖則表征了塊設(shè)備的注冊和釋放過程:

            5.小結(jié)

            本章講述了Linux設(shè)備驅(qū)動程序的入口函數(shù)及驅(qū)動程序中的內(nèi)存申請、中斷等,并分別以實例講述了字符設(shè)備及塊設(shè)備的驅(qū)動開發(fā)方法。

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

          linux相關(guān)文章:linux教程



          上一頁 1 2 3 下一頁

          關(guān)鍵詞: ARM 嵌入式 Linux移植

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();