• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    Linux核心定制在嵌入式系統(tǒng)中應(yīng)用的探討

    2013-06-25 08:45:14陳剛
    關(guān)鍵詞:驅(qū)動(dòng)程序數(shù)據(jù)結(jié)構(gòu)內(nèi)核

    陳剛

    【中圖分類號(hào)】TP316 【文獻(xiàn)標(biāo)識(shí)碼】A 【文章編號(hào)】1672-5158(2013)03-0086-03

    隨著硬件的發(fā)展,只靠匯編語言已經(jīng)無法滿足嵌入式系統(tǒng)的開發(fā)要求了;同時(shí)種類繁多的開發(fā)平臺(tái)無論是硬件的還是軟件的平臺(tái)都讓人難以挑選;但是可以看到的是一些專用的軟件平臺(tái)必將被歷史淘汰;硬件上ARM在嵌入式系統(tǒng)一家獨(dú)大的局面也必將被打破。INTER也即將發(fā)布手機(jī)用CPU,AMD已經(jīng)推出移動(dòng)和嵌入式設(shè)備用的三個(gè)系列CPU;所以源代碼開放對(duì)各種硬件支持良好的LINUX是嵌入式系統(tǒng)開發(fā)的必選軟件平臺(tái);但是由于LINUX是針對(duì)臺(tái)式機(jī)筆記本的,所以在各式驅(qū)動(dòng)和內(nèi)存等的支持上的過多導(dǎo)致相對(duì)嵌入式系統(tǒng)來說過分龐大;所以在嵌入式系統(tǒng)的開發(fā)中,我們可以對(duì)LINUX內(nèi)核的驅(qū)動(dòng)模塊和內(nèi)存管理上進(jìn)行刪減和定制;(Android系統(tǒng)、虛擬操作系統(tǒng)VMware的最新版本等都是對(duì)LINUX內(nèi)核的驅(qū)動(dòng)和內(nèi)存管理進(jìn)行深層次定制修改的LINUX變種)本文主要討論在LINUX內(nèi)核中定制開發(fā)嵌入式系統(tǒng)的驅(qū)動(dòng)。

    對(duì)linux的devfs類型的驅(qū)動(dòng)程序的編寫可以從以下幾大內(nèi)容理解和入手:

    通過分析驅(qū)動(dòng)程序源代碼可以發(fā)現(xiàn)驅(qū)動(dòng)程序一般可分三部分:

    核心數(shù)據(jù)結(jié)構(gòu);核心數(shù)據(jù)和資源的初始化,注冊(cè)以及注消,釋放;底層設(shè)備操作函數(shù);

    A.核心數(shù)據(jù)結(jié)構(gòu)

    struct file_operations fops 設(shè)備驅(qū)動(dòng)程序接口struct file_operations { struct module *owner;

    loff_t (*llseek) (struct file *,loff_t,int);

    ssize_t (*read) (struct file *,char *,size_t,loff_t *);

    ssize_t (*write) (struct file *,const char *,size_t,loff_t *); int (*readdir) (struct file *,void *,filldir_t);

    unsigned int (*poll) (struct file *,struct poll_table_struct *);

    int (*ioctl) (struct inode *,struct file *,unsigned int,unsigned long);

    int (*mmap) (struct file *,struct vm_area_struct *);

    int (*open) (struct inode *,struct file *);

    int (*flush) (struct file *);

    int (*release) (struct inode *,struct file *);

    int (*fsync) (struct file *,struct dentry *,int datasync); int (*fasync) (int,struct file *,int);

    int (*lock) (struct file *,int,struct file_lock *);

    ssize_t (*readv) (struct file *,const struct iovec *,unsigned long,loff_t*);

    ssize_t (*writev) (struct file *,const struct iovec *,unsigned long,loff_t *);

    ssize_t (*sendpage) (struct file *,struct page *,int,size_t,loff_t *,int);

    unsigned long (*get_unmapped_area)(struct file *,unsigned long,unsigned long,unsigned long,unsigned long);

    };

    block_device_operations 塊設(shè)備驅(qū)動(dòng)程序接口{ int (*open) (struct inode *,struct file *); int (*release) (struct inode *,struct file *);

    int (*ioctl) (struct inode *,struct file *,unsigned,unsigned long);

    int (*check_media_change) (kdev_t);

    int (*revalidate) (kdev_t);

    struct module *owner;

    };塊設(shè)備的READ().WRITE()不在這里注冊(cè),而是在設(shè)備的讀寫請(qǐng)求隊(duì)列里注冊(cè),內(nèi)核在這里將調(diào)用通用的blk_read(),blk_write().向讀寫隊(duì)列

    發(fā)出讀寫請(qǐng)求.

    Linux 利用這些數(shù)據(jù)結(jié)構(gòu)向內(nèi)核注冊(cè)open(),release(),ioctl(),check_ media_change(),rvalidate()等函數(shù)的入口句柄.

    我們將要編寫的open(),release(),ioctl(),check_media_change(),Revali date()等函數(shù),將在驅(qū)動(dòng)初始化的時(shí)候,

    通過一個(gè)此結(jié)構(gòu)類型的變量向內(nèi)核提供函數(shù)的 入口.

    struct request_queue_t 設(shè)備請(qǐng)求隊(duì)列的數(shù)據(jù)結(jié)構(gòu)

    struct request_list {

    unsigned int count;

    unsigned int pending[2];

    struct list_head free;

    };

    struct request {

    struct list_head queue;

    int elevator_sequence;

    kdev_t rq_dev;

    int cmd; /* READ or WRITE */

    int errors;

    unsigned long start_time;

    unsigned long sector;

    unsigned long nr_sectors;

    unsigned long hard_sector,hard_nr_sectors;

    unsigned int nr_segments;

    unsigned int nr_hw_segments;

    unsigned long current_nr_sectors,hard_cur_sectors;

    void * special;

    char * buffer;

    struct completion * waiting;

    struct buffer_head * bh;

    struct buffer_head * bhtail;

    request_queue_t *q;

    };

    struct request_queue

    {

    /*

    * the queue request freelist,one for reads and one for writes*/

    struct request_list rq;

    /*

    * The total number of requests on each queue

    */

    int nr_requests;

    /*

    * Batching threshold for sleep/wakeup decisions

    */

    int batch_requests;

    /*

    * The total number of 512byte blocks on each queue

    */

    atomic_t nr_sectors;

    /*

    * Batching threshold for sleep/wakeup decisions

    */

    int batch_sectors;

    /*

    * The max number of 512byte blocks on each queue

    */

    int max_queue_sectors;

    /*

    * 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 doesnt 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.

    */

    int plugged:1;

    /*

    * Boolean that indicates whether current_request is active or

    * not.

    */

    int head_active:1;

    /*

    * Boolean that indicates you will use blk_started_sectors

    * and blk_finished_sectors in addition to blk_started_io

    * and blk_finished_io. It enables the throttling code to

    * help keep the sectors in flight to a reasonable value

    */

    int can_throttle:1;

    unsigned long bounce_pfn;

    /*

    * Is meant to protect the queue in the future instead of

    * io_request_lock

    */

    spinlock_t queue_lock;

    /*

    * Tasks wait here for free read and write requests

    */

    wait_queue_head_t wait_for_requests;

    struct request *last_request;

    };

    緩沖區(qū)和對(duì)緩沖區(qū)相應(yīng)的I/O操作在此任務(wù)隊(duì)列中相關(guān)聯(lián),等待內(nèi)核的調(diào)度.如果是字符設(shè)備就不需要此數(shù)據(jù)結(jié)構(gòu).而

    塊設(shè)備的read(),write()函數(shù)則在buffer_queue的initize和設(shè)備請(qǐng)求隊(duì)列進(jìn)行處理請(qǐng)求時(shí)候傳遞給request_fn().

    struct request_queue_t{}設(shè)備請(qǐng)求隊(duì)列的變量類型,驅(qū)動(dòng)程序在初始化的時(shí)候需要填寫request_fn().

    其他的數(shù)據(jù)結(jié)構(gòu)還有 I/O port,Irq,DMA 資源分配,符合POSIX標(biāo)準(zhǔn)的ioctl的cmd的構(gòu)造和定義,以及描述設(shè)備自身的

    相關(guān)數(shù)據(jù)結(jié)構(gòu)定義-如設(shè)備的控制寄存器的相關(guān)數(shù)據(jù)結(jié)構(gòu)定義,BIOS里的參數(shù)定義,設(shè)備類型定義等.

    B.初始化和注冊(cè)和注消,模塊方式驅(qū)動(dòng)程序的加載和卸載.

    設(shè)備驅(qū)動(dòng)程序在定義了數(shù)據(jù)結(jié)構(gòu)后,首先開始初始化:

    如I/O 端口的檢查和登記,內(nèi)核對(duì) I/O PORT的檢查和登記提供了兩個(gè) 函數(shù)check_region(int io_port,int off_set)

    和request_region(int io_port,int off_set,char *devname).I/O Port登記后,就可以用inb()和outb()進(jìn)行操作了 .

    還有DMA和Irq的初始化檢查和 登記,

    int request_irq(unsigned int irq,void(*handle)(int,void *,struct pt_regs*),unsigned int long flags,

    const char *device);

    irq: 是要申請(qǐng)的中斷。

    handle:中斷處理函數(shù)指針。

    flags:SA_INTERRUPT 請(qǐng)求一個(gè)快速中斷,0 正常中斷。

    device:設(shè)備名。

    如果登記成功,返回0,這時(shí)在/proc/interrupts文件中可以看你請(qǐng)求的中斷。

    DMA主要是在內(nèi)存中分配交換內(nèi)存空間.還有緩沖區(qū),設(shè)備請(qǐng)求隊(duì)列的初始化.

    還有設(shè)備控制寄存器的檢查和初始化,還有對(duì)設(shè)備自身相關(guān)的數(shù)據(jù)結(jié)構(gòu)的初始化,填寫一些設(shè)備特定的數(shù)據(jù)等.

    然后,開始注冊(cè)

    devfs_register()向VFS注冊(cè)統(tǒng)一的設(shè)備操作函數(shù).

    static struct file_operations XXX_fops = {

    owner: THIS_MODULE, XXX_fops所屬的設(shè)備模塊

    read: XXX_read, 讀設(shè)備操作

    write: XXX_write, 寫設(shè)備操作

    ioctl: XXX_ioctl, 控制設(shè)備操作

    mmap: XXX_mmap, 內(nèi)存重映射操作

    open: XXX_open, 打開設(shè)備操作

    release: XXX_release 釋放設(shè)備操作

    /* ... */

    };

    blk_init_queue()隊(duì)列初始化函數(shù).

    request_irq()中斷注冊(cè)函數(shù)

    相應(yīng)的注消函數(shù):

    devfs_unregister (devfs_handle_t de){};

    free_irq()釋放中斷,I/O資源,釋放緩沖區(qū),釋放設(shè)備,請(qǐng)求隊(duì)列,VFS節(jié)點(diǎn)等.

    模塊方式驅(qū)動(dòng)程序的加載和卸載.

    static int __init _init_module (void)

    {

    /* ... */

    }

    static void __exit _cleanup_module (void)

    {

    }

    /* 加載驅(qū)動(dòng)程序模塊入口 */

    module_init(_init_module);

    /* 卸載驅(qū)動(dòng)程序模塊入口 */

    module_exit(_cleanup_module);

    _intrrupt()

    設(shè)備發(fā)生中斷時(shí)的處理程序.

    {

    1.對(duì)共享中斷的處理;

    2.對(duì)spinlock以及其他的事務(wù)的處理;

    }

    C. 底層設(shè)備操作函數(shù)的編寫

    read().write(),open(),release(),check_media_change(),revalidate()等.

    open()和release()

    打開設(shè)備是通過調(diào)用file_operations結(jié)構(gòu)中的函數(shù)open( )來完成的,它是驅(qū)動(dòng)程序用來為今后的操作完成初始化準(zhǔn)備工作的。在大部分驅(qū)動(dòng)程序中,open( )通常需要完成下列工作:

    1. 檢查設(shè)備相關(guān)錯(cuò)誤,如設(shè)備尚未準(zhǔn)備好等。

    2. 如果是第一次打開,則初始化硬件設(shè)備。

    3. 識(shí)別次設(shè)備號(hào),如果有必要?jiǎng)t更新讀寫操作的當(dāng)前位置指針

    f_ops。

    4. 分配和填寫要放在file->private_data里的數(shù)據(jù)結(jié)構(gòu)。

    5. 使用計(jì)數(shù)增1。

    釋放設(shè)備是通過調(diào)用file_operations結(jié)構(gòu)中的函數(shù)release( )來完成的,這個(gè)設(shè)備方法有時(shí)也被稱為close( ),它的作用正好與open( )相反,通常要完成下列工作:

    1. 使用計(jì)數(shù)減1。

    2. 釋放在file->private_data中分配的內(nèi)存。

    3. 如果使用計(jì)算為0,則關(guān)閉設(shè)備。

    read()和 write()

    字符設(shè)備的讀寫操作相對(duì)比較簡(jiǎn)單,直接使用函數(shù)read( )和write( )就可以了。但如果是塊設(shè)備的話,則需要調(diào)用函數(shù)block_read( )和block_write( )來進(jìn)行數(shù)據(jù)讀寫,這兩個(gè)函數(shù)將向設(shè)備請(qǐng)求表中增加讀寫請(qǐng)求,以便Linux內(nèi)核可以對(duì)請(qǐng)求順序進(jìn)行優(yōu)化。由于是對(duì)內(nèi)存緩沖區(qū)而不是直接對(duì)設(shè)備進(jìn)行操作的,因此能很大程度上加快讀寫速度。如果內(nèi)存緩沖區(qū)中沒有所要讀入的數(shù)據(jù),或者需要執(zhí)行寫操作將數(shù)據(jù)寫入設(shè)備,那么就要執(zhí)行真正的數(shù)據(jù)傳輸,這是通過調(diào)用數(shù)據(jù)結(jié)構(gòu)blk_dev_struct中的函數(shù)request_fn( )來完成的。

    ioctl()--將cmd進(jìn)行解釋,并送到設(shè)備的控制寄存器.事實(shí)上,read()和write()也要通過ioctl()來完成操作的 .

    ioctl(){

    CASE CMD{

    SWITCH CASE1:{...};

    SWITCH CASE2:{...};

    SWITCH CASE N:{...};

    .

    .

    DEFAULT : {...};

    }

    END CASE

    總結(jié):

    我們可以看出一個(gè)linux的驅(qū)動(dòng)程序通常包含如下:

    初始化設(shè)備模塊、

    {I/O port,DMA.Irq,內(nèi)存 buffer,初始化并且填寫具體設(shè)備數(shù)據(jù)結(jié)構(gòu),注冊(cè) fops的具體函數(shù)等等 }

    中斷處理模塊、設(shè)備釋放模塊、設(shè)備卸載模塊

    設(shè)備打開模塊、數(shù)據(jù)讀寫和控制模塊、

    驅(qū)動(dòng)裝載模塊、驅(qū)動(dòng)釋放模塊.

    猜你喜歡
    驅(qū)動(dòng)程序數(shù)據(jù)結(jié)構(gòu)內(nèi)核
    萬物皆可IP的時(shí)代,我們當(dāng)夯實(shí)的IP內(nèi)核是什么?
    群眾路線是百年大黨成功之內(nèi)核性制度因素的外在表達(dá)
    強(qiáng)化『高新』內(nèi)核 打造農(nóng)業(yè)『硅谷』
    Linux內(nèi)核mmap保護(hù)機(jī)制研究
    “翻轉(zhuǎn)課堂”教學(xué)模式的探討——以《數(shù)據(jù)結(jié)構(gòu)》課程教學(xué)為例
    高職高專數(shù)據(jù)結(jié)構(gòu)教學(xué)改革探討
    TRIZ理論在“數(shù)據(jù)結(jié)構(gòu)”多媒體教學(xué)中的應(yīng)用
    《數(shù)據(jù)結(jié)構(gòu)》教學(xué)方法創(chuàng)新探討
    河南科技(2014年5期)2014-02-27 14:08:57
    驅(qū)動(dòng)程序更新與推薦
    驅(qū)動(dòng)程序更新與推薦
    蓝田县| 天台县| 慈溪市| 文安县| 调兵山市| 和田市| 柳州市| 新巴尔虎左旗| 陕西省| 金溪县| 杂多县| 门头沟区| 孟津县| 韶关市| 连平县| 延川县| 博兴县| 延津县| 苏尼特左旗| 临潭县| 内江市| 周至县| 天祝| 斗六市| 江油市| 娄底市| 福泉市| 谷城县| 达孜县| 庆元县| 永州市| 辽源市| 安远县| 澄江县| 崇文区| 灌云县| 汨罗市| 巴青县| 沾益县| 雅安市| 日照市|