007デバイス・ドライバ

まず、ブロック・デバイス・ドライバの導入(レッスン18 /第一)

キャラクタデバイスドライバを要約したものです。

図1に示すように、文字デバイスドライバを導入


アプリケーションが開いて呼び出すと、drv_open機能ドライバが呼び出されます。

2、最も簡単なドライバ文言

あなたが自分自身を設定するだけでなく、カーネルの配布を可能にすることができます。1.メジャー番号を決定します。
2.等「オープン、書き込み、読み出し」機能でドライブの構成、次いで構造における「file_operation」に。
3. register_chrdev文字登録装置、アレイの次のターゲットのプライマリデバイス番号のコアのデバイス構造に「file_operation」文字の構成。「register_chrdev(メジャー番号、マスタ・デバイスの名前、file_operation構造)。」
4.エントリ機能:カーネルモジュールをロードし、この「register_chrdev」関数を呼び出し、自動的にこのエントリポイントを呼び出します。
エクスポート機能:コール「unregister_chrdev」

3、我々は、例えば、ドライバのキードライバーの多くを書きました

1.クエリ:ドライバピン直接状態を返す読み出し機能を提供し、アプリケーションは、前後の2本のピン状態が変更されたかどうか、読み取りを継続します。CPU占有率が高くなります。
2.割り込み(ウェイクアップ):読み取り機能を使用する場合、読み取り機能のドライバを入力するためのアプリケーション。睡眠上のデータがない場合はドライバプログラムでは、割り込みが発生した場合、ユーザ空間にデータをコピーcopy_to_userそして、目覚めされます。
3.ポーリングメカニズム:タイムアップであるか、または割り込みが戻りが発生した場合だけ、アラームクロックを設定し
、上記非同期通知ドライバは、アプリケーションに信号を送る読み取るためのアプリケーションの3種類である:4.非同期通知。
上記4例欠点は、このドライブが唯一のあなたが使用する方法を知っていることです。一般的に記述する必要がありますドライバは、カーネルコード、独自のコードへの統合を理解しています。キーが入力サブシステムであるために、それは、LCDフレームバッファのためです。

ブロックデバイスドライバ

1、ハードディスク:



シリンダ:0滑走路:のような、環の滑走路と同じ
セクタ:面積の小さな部分に連続トラック、トラックはいくつかのセクタに分割することができます。
実際には、ディスクの読み取りおよび書き込みが非常に速い、遅い読者は、装置の機械的構造の上方に配置されています。
今上の異なるセクターの頭を読み書き仮定

上記の実行は次のとおりです。「R0は」 - >「W 」 - >「R1」、 操作を2回ジャンプします。
最適化: - >「R1「R0」 」 - >「W」、 この操作は一度だけジャンプする必要がありますように。
解決策:最初のキューではなく、実行、最適化された実行(再注文)後に。ハードディスク上の全体的な読み取りを削減し、効率を書くジャンプを防止することができます。

2、フラッシュ


仮定は、セクタ0とセクタ1書き込み
フラッシュが最初に消去してから書き込みます。

  1. バッファ全体を読むには。
  2. セクタ0のバッファを変更します。
  3. 全体のフラッシュを消去します。
  4. 修飾されたバッファは、ピースにプログラム。
    解決策:最初のキューで行われていない、後の最適化(連結)を行います。

    したがって、ブロックデバイスが読み込まれ、キャラクタデバイスのような関数を書くことができないことを条件とします。しかし、キューに最初の読み出しが行われていない、最適化を実行した後。

第二に、ブロックデバイスドライバフレームワーク(レッスン18 / II)


読み、通常のファイルを書き込む「1.TXT」を読み、書き、どのセクタを読み書きするためにペアリングブロックデバイスを変換されます。読み取りと書き込みのファイルから読み込む変換ペアリング部門は、中間体は、「ファイルシステム」を含むことになります
通常のファイルを読み書きするアプリケーションでは、操作は最終的にハードウェアを動作させるために「ブロックデバイスドライバ」、ハードウェアに変換されます。
どのように我々は「ll_rw_block」(低レベル下)を見ることができることを知っています「Linuxカーネルのソースコードのシナリオ分析を。」

今から「ll_rw_block」機能は、分析を開始します


「FS」があるディレクトリの下に、 -カーネルソースディレクトリにある「FS」ディレクトリの下に、この機能をファイル、ファイルシステムの多種多様なこの「FS」ディレクトリ(純粋なソフトウェアの概念組織形式のファイル)があります多くの一般的なドキュメント、「ll_rw_blokc」この機能(buffer.cとは)「FS」ディレクトリの下にユニバーサルファイルです。
パラメータ1:リードを示すまたは書き込み;パラメータ2:3及びNRパラメータ「buffer_head」構造アレイエントリ、パラメータ3:アレイ「buffer_head」構造へのデータ転送三つの要素(ソース、宛先、長さ)。


(submit_bh)関数を入力

バイオを構築し、バイオを提出し

---------------------------------------- -------------

(submit_bio)関数を入力


-------------------------------- ---------------------


----------------------------- ------------------------



機能がそれを設定した場合さて、これは何ですか?検索


それはどこにこの(blk_queue_make_request)関数が呼び出されますか?検索には、



何かをする何このデフォルトの関数(__make_request)を参照してくださいするには?






分析枠組み:

第三に、アナログメモリディスクとライトドライバブロックデバイスドライバ(レッスン18 /第三)

ブロックデバイスドライバを書くためにどのように?

1.オブジェクト指向の考え方は、「gendisk」構造を割り当てる:alloc_disk機能を使用する
2.セット「gendisk」構造。
2.1割り当て/キュー設定:使用blk_init_queue(読み取りと書き込みの提供)
2.2セット「gendisk」その他の情報を。提供属性:そのような能力
3.レジスタ「gendisk」の構造:機能使用add_disk

他の人々は、(ドライバー/ブロック/ xd.c)および(ドライバ/ブロック/ z2ram.c)を参照してくださいどのように見てみましょう。
「xd.c」エントリー機能を開始してから
1レジスタブロックデバイス


2.初期化キュー

3.キュー


4. add_disk

1番目、

デバイス・ドライバ・ブロックの書き込みに
割り当てられたディスク構造の

キューが設定/割り当てを


他の属性ディスクセット




の登録

処理要求
割当/キューセット「blk_init_queue」機能を、パラメータは、キュー内の要求を処理する機能である

出口機能

試験1番目:
1負荷駆動:

ドライバをロードした直後に「do_ramblock_request」キュー要求ハンドラと呼ばれるが、任意の処理をせずにいるためのrequesのため、ここに返されることはありません。

問題に対処するために返すことができない2番目、

(xd.c)を見て、実行する方法を見てとる

模倣どの

テスト2番目に:
ロード・ドライブを

何もしていないので、それがパーティションテーブルを認識しません
チェック機器を


3番目、改善メモリ、アナログディスク

1.ディスクをシミュレートするためにメモリを割り当て


構造の「要求」の三つの要素が定義され、データ伝送の三つの要素2.データ送信ブロックデバイスを

ブロック・デバイスの動作はバイト書き込みが最初に読み込まれた場合にも、セクタ単位で行われますセクタ、バイトであり、その後セクタ全体に焼き付けこのセクタを変更した後。

3.書き込みの方向

第3回のテスト:
なし試験液mkdosfsツール:
。ダウンロード元、解凍、コンパイル

mkdosfs 2. usr / sbinディレクトリのファイルシステムにコピーコンパイル


3.ボードNFSは次のディレクトリは/ usr / sbinにマウントボードからコピーする連結式の後。

テストの開始:
1.ドライバのロード

またはすべての割り当てられたメモリがアップクリアされるため、認識できないパーティションテーブルを要求。

2.フォーマット:mkdosfsは/ dev / ramblock

3.マウント:マウントは/ dev / ramblockを/ tmp / =====>をディレクトリにディスクTMP、操作を/ tmp /ディレクトリ操作が我々メモリと同等です仮想ディスク

4の読み取り・書き込みファイル:CD / tmpが、どのファイルまたはファイルのコピーを編集して


、ルートディレクトリに5.ジャンプをし、アンマウント

6.仮想ディスク全体のイメージを/ mnt / ramblockをカバーするために使用されるメモリを。ビン


お使いのPC上のfirst_fsディレクトリ7.チェックramblock.bin
「ループ-oは、」ループバックデバイスをマウントするブロックデバイスファイルとして通常のファイルとすることができ表します。

第四、印刷された書き込みキュー要求ハンドラ

メモリを搭載した「のmemcpy」の使用は、ハードウェアの操作を達成するために、複雑な操作のハードウェアを無視して、ディスクをシミュレートします。
読み込みの実行を参照するか、操作の書き込みにprint文を追加

テスト4日に:
1.負荷ドライバは

、負荷運転時に読み取るために
2.フォーマット

3.マウントし

......

4.コピーファイルを(CP /など/ inittabファイル/ tmp)に

すぐに書き込まれ、書き込みが、読んでいない見ることができます。読み取りおよび書き込み操作をブロックするデバイスの内部キューに、そしてすぐに実行されていないでしょう。

私はに書き込むにはしばらく待って

時には、Windows上で完成された「プログレスバー」で見つかったUのディスクにファイルをコピーすることができ、それはUディスクをアンロード、あなたはデバイスが使用中であると言うするように指示されたら、右下隅をクリックし、Uディスクライトが怒っ点滅しています。これは実際にはまだ書き込みを背景です。

次に、ファイルをコピー(CP /etc/init.d/rcSで/ tmp)に

見つかったか書いていない
シンク(同期)の実装は、すぐそこに書き込むことができ、同期はシステムコールです。

再びファイルをコピーし、「アンマウント」(アンマウント)を実行するとき、彼らはまた、すぐに書くことはできません、すぐに書き始めました。

第五、パーティション


あなたは「シリンダー」番号を知りませんでしたプロンプトが表示されます。今では多くのディスクには(ヘッド、シリンダー)このような構造を持っていないが、これらの「FDISK」古いツールとの互換性のために、あなたは彼らが「頭」の数、数持っていることをふりをする必要がある「シリンダーを。」この情報は、幾何学的属性の「block_device_operation」構造「.getgeo」機能から取得されます。

検索「.getgeoは、」どのように他の人々を使用している見るために

他人の文言に従ってください

シリンダーヘッド容量= * 512 *部門の
ヘッドは:どのように多くの顔を示しています。2つの顔があることを想定しています。
シリンダー:どのように多くのリングを示しています。32個のリングがあることを想定しています。
セクター:セクタ数でループを示します。
セクタは512バイトです。

テスト第5回:
1.リロードドライバ

デバイス2.チェック

マイナー番号が「0」はディスク全体を表し、1Mメモリ
3.パーティションは

1Mのスペースを分割する

「n」は新しいパーティションを追加するために

、いくつかのパーティションの最初を設定し、設定パーティションサイズは、

パーティションテーブルに表示

新しいパーティションは、パーティションを追加するには、以下のうちに作成されて表示するには、この時間は

本当にパーティションテーブルを書きます「W」の入力を、このディスクは、最初のセクターのパーティションテーブルと呼ばれる

視聴デバイス

できます各フォーマットは、別々に実装してもよいです

第五パーティション分割プログラム

/*
 * 参考:drivers\block\xd.c
 *        drivers\block\z2ram.c
 */
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>

#define RAMBLOCK_SIZE (1204*1024)    //应该是1024*1024,只是内存大小不同

static int major;
static struct gendisk* ramblock_disk;
static request_queue_t* ramblock_queue;
static DEFINE_SPINLOCK(ramblock_lock);
static unsigned char* ramblock_buffer;

static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
    /* 容量 =   磁头 * 柱面 * 扇区 * 512 */
    geo->heads = 2;
    geo->sectors = 32;
    geo->cylinders = RAMBLOCK_SIZE/2/32/512;
    return 0;
}

static struct block_device_operations ramblock_fops = {
    .owner    = THIS_MODULE,
    .getgeo = ramblock_getgeo,
};

static void do_ramblock_request (request_queue_t * q)
{
    struct request *req;
    //static unsigned int w_cnt = 0, r_cnt = 0;
    while ((req = elv_next_request(q)) != NULL) {
        /* 要开始提交的第几个扇区 */
        unsigned long offset = req->sector * 512;
        /* 长度 */
        unsigned long len  = req->current_nr_sectors * 512;

        if (rq_data_dir(req) == READ)
        {//memcpy(dest,src,len)
            memcpy(req->buffer, ramblock_buffer + offset, len);
            //printk("read %d\n", ++r_cnt);
        }
        else
        {
            memcpy(ramblock_buffer + offset, req->buffer, len);
            //printk("write %d\n", ++w_cnt);
        }
        end_request(req, 1);    /* wrap up, 0 = fail, 1 = success */
        }
}

static int ram_block_init(void)
{
    /* 1. 分配一个disk结构 */
    /* 分配的次设备号个数,16表示组多能创建15个分区,其中次设备号为0表示整个磁盘。 */
    /* 如果不想分区,写为1就可以了 */
    ramblock_disk = alloc_disk(16);
    /* 2. 设置 */
    /* 2.1 分配/设置队列 */
    ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
    ramblock_disk->queue = ramblock_queue;
    /* 2.2 设置其它属性:比如容量 */
    major = register_blkdev(0, "ramblock");
    ramblock_disk->major = major;
    ramblock_disk->first_minor = 0;
    sprintf(ramblock_disk->disk_name, "ramblock");
    ramblock_disk->fops = &ramblock_fops;

    set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);
    /* 4.硬件相关操作 */
    ramblock_buffer = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
    /* 3.注册 */
    add_disk(ramblock_disk);
    return 0;
}

static void ram_block_exit(void)
{
    put_disk(ramblock_disk);
    blk_cleanup_queue(ramblock_queue);
    unregister_blkdev(major, "ramblock");
    del_gendisk(ramblock_disk);
    kfree(ramblock_buffer);
}

module_init(ram_block_init);
module_exit(ram_block_exit);

MODULE_LICENSE("GPL");

個人的な要約:

    格式化、读写文件等都是由"文件系统"这一层将文件的读写转换成对扇区的读写。调用"ll_rw_block"会把读写放到你的队列中去。会调用你的"队列请求函数"来处理。只要写好"队列请求函数"即可。
    一旦使用读写文件等操作就会被文件系统拆分成对不同扇区的一个一个读写请求然后加入队列,在队列会调用电梯调度算法,最终就会调用"do_request"函数,在函数里面从队列里取出一个请求以实现对硬件的读写操作。

<wiz_tmp_tagのID = "ウィズ・テーブル・レンジ・ボーダー" のcontentEditable = "false" のスタイル= "表示:なし;">

おすすめ

転載: www.cnblogs.com/luosir520/p/11457409.html