国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Linux|Centos|Ubuntu|系統(tǒng)進(jìn)程|Fedora|注冊(cè)表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Linux - Linux 塊設(shè)備驅(qū)動(dòng)代碼編寫

Linux 塊設(shè)備驅(qū)動(dòng)代碼編寫

2022-03-07 16:51feixiaoxing Linux

這篇文章主要介紹了Linux 塊設(shè)備驅(qū)動(dòng)代碼編寫,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

按照ldd的說法,linux的設(shè)備驅(qū)動(dòng)包括了char,block,net三種設(shè)備。char設(shè)備是比較簡(jiǎn)單的,只要分配了major、minor號(hào),就可以進(jìn)行讀寫處理了。相對(duì)而言,block和net要稍微復(fù)雜些。net設(shè)備姑且按下不談,我們?cè)谝院蟮牟┪闹袝?huì)有涉及。今天,我們可以看看一個(gè)簡(jiǎn)單的block是怎么設(shè)計(jì)的。

為了將block和fs分開,kernel的設(shè)計(jì)者定義了request queue這一種形式。換一句話說,所有fs對(duì)block設(shè)備的請(qǐng)求,最終都會(huì)轉(zhuǎn)變?yōu)閞equest的形式。所以,對(duì)于block設(shè)備驅(qū)動(dòng)開發(fā)的朋友來說,處理好了request queue就掌握了block設(shè)備的一半。當(dāng)然,block設(shè)備很多,hd、floppy、ram都可以這么來定義,有興趣的朋友可以在drivers/block尋找相關(guān)的代碼來閱讀。興趣沒有那么強(qiáng)的同學(xué),可以看看我們這篇博文,基本上也能學(xué)個(gè)大概。有個(gè)基本的概念,再加上一個(gè)簡(jiǎn)單淺顯的范例,對(duì)于一般的朋友來說,已經(jīng)足夠了。

閑話不多說,我們看看一個(gè)ramdisk代碼驅(qū)動(dòng)是怎么寫的,代碼來自《深入linux 設(shè)備驅(qū)動(dòng)程序內(nèi)核機(jī)制》,

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
 
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
 
#define RAMHD_NAME "ramhd"
#define RAMHD_MAX_DEVICE 2
#define RAMHD_MAX_PARTITIONS 4
 
#define RAMHD_SECTOR_SIZE 512
#define RAMHD_SECTORS 16
#define RAMHD_HEADS 4
#define RAMHD_CYLINDERS 256
 
#define RAMHD_SECTOR_TOTAL (RAMHD_SECTORS * RAMHD_HEADS *RAMHD_CYLINDERS)
#define RAMHD_SIZE (RAMHD_SECTOR_SIZE * RAMHD_SECTOR_TOTAL) //8mb
 
typedef struct {
  unsigned char* data;
  struct request_queue* queue;
  struct gendisk* gd;
}RAMHD_DEV;
 
static char* sdisk[RAMHD_MAX_DEVICE] = {NULL};
static RAMHD_DEV* rdev[RAMHD_MAX_DEVICE] = {NULL};
 
static dev_t ramhd_major;
 
static int ramhd_space_init(void)
{
  int i;
  int err = 0;
  for(i = 0; i < RAMHD_MAX_DEVICE; i++){
    sdisk[i] = vmalloc(RAMHD_SIZE);
    if(!sdisk[i]){
      err = -ENOMEM;
      return err;
    }
     
    memset(sdisk[i], 0, RAMHD_SIZE);
  }
   
  return err;
}
 
static void ramhd_space_clean(void)
{
  int i;
  for(i = 0; i < RAMHD_MAX_DEVICE; i++){
    vfree(sdisk[i]);
  }
}
 
static int ramhd_open(struct block_device* bdev, fmode_t mode)
{
  return 0;
}
 
static int ramhd_release(struct gendisk*gd, fmode_t mode)
{
  return 0;
}
 
static int ramhd_ioctl(struct block_device* bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
  int err;
  struct hd_geometry geo;
   
  switch(cmd)
  {
    case HDIO_GETGEO:
      err = !access_ok(VERIFY_WRITE, arg, sizeof(geo));
      if(err)
        return -EFAULT;
         
      geo.cylinders = RAMHD_CYLINDERS;
      geo.heads = RAMHD_HEADS;
      geo.sectors = RAMHD_SECTORS;
      geo.start = get_start_sect(bdev);
       
      if(copy_to_user((void*)arg, &geo, sizeof(geo)))
        return -EFAULT;
       
      return 0;
  }
   
  return -ENOTTY;
}
 
static struct block_device_operations ramhd_fops = {
  .owner = THIS_MODULE,
  .open = ramhd_open,
  .release = ramhd_release,
  .ioctl = ramhd_ioctl,
};
 
static int ramhd_make_request(struct request_queue* q, struct bio* bio)
{
  char* pRHdata;
  char* pBuffer;
  struct bio_vec* bvec;
  int i;
  int err = 0;
   
  struct block_device* bdev = bio->bi_bdev;
  RAMHD_DEV* pdev = bdev->bd_disk->private_data;
   
  if(((bio->bi_sector * RAMHD_SECTOR_SIZE) + bio->bi_size) > RAMHD_SIZE){
    err = -EIO;
    return err;
  }
   
  pRHdata = pdev->data + (bio->bi_sector * RAMHD_SECTOR_SIZE);
  bio_for_each_segment(bvec, bio, i){
    pBuffer = kmap(bvec->bv_page) + bvec->bv_offset;
    switch(bio_data_dir(bio)){
      case READ:
        memcpy(pBuffer, pRHdata, bvec->bv_len);
        flush_dcache_page(bvec->bv_page);
        break;
         
      case WRITE:
        flush_dcache_page(bvec->bv_page);
        memcpy(pRHdata, pBuffer, bvec->bv_len);
        break;
         
      default:
        kunmap(bvec->bv_page);
        goto out;
    }
     
    kunmap(bvec->bv_page);
    pRHdata += bvec->bv_len;
  }
   
out:
  bio_endio(bio, err);
  return 0;
}
 
static int alloc_ramdev(void)
{
  int i;
  for(i = 0; i < RAMHD_MAX_DEVICE; i++){
    rdev[i] = kzalloc(sizeof(RAMHD_DEV), GFP_KERNEL);
    if(!rdev[i]){
      return -ENOMEM;
    }
  }
   
  return 0;
}
 
static void clean_ramdev(void)
{
  int i;
   
  for(i = 0; i < RAMHD_MAX_DEVICE; i++){
    if(rdev[i])
      kfree(rdev[i]);
  }
}
 
static int __init ramhd_init(void)
{
  int i;
   
  ramhd_space_init();
  alloc_ramdev();
   
  ramhd_major = register_blkdev(0, RAMHD_NAME);
   
  for(i = 0; i < RAMHD_MAX_DEVICE; i++){
    rdev[i]->data = sdisk[i];
    rdev[i]->queue = blk_alloc_queue(GFP_KERNEL);
    blk_queue_make_request(rdev[i]->queue, ramhd_make_request);
     
    rdev[i]->gd = alloc_disk(RAMHD_MAX_PARTITIONS);
    rdev[i]->gd->major = ramhd_major;
    rdev[i]->gd->first_minor = i * RAMHD_MAX_PARTITIONS;
    rdev[i]->gd->fops = &ramhd_fops;
    rdev[i]->gd->queue = rdev[i]->queue;
    rdev[i]->gd->private_data = rdev[i];
    sprintf(rdev[i]->gd->disk_name, "ramhd%c", 'a' +i);
    rdev[i]->gd->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
    set_capacity(rdev[i]->gd, RAMHD_SECTOR_TOTAL);
    add_disk(rdev[i]->gd);
  }
   
  return 0;
}
 
static void __exit ramhd_exit(void)
{
  int i;
  for(i = 0; i < RAMHD_MAX_DEVICE; i++){
    del_gendisk(rdev[i]->gd);
    put_disk(rdev[i]->gd);
    blk_cleanup_queue(rdev[i]->queue);
  }
   
  clean_ramdev();
  ramhd_space_clean();
  unregister_blkdev(ramhd_major, RAMHD_NAME);
}
 
module_init(ramhd_init);
module_exit(ramhd_exit);
 
MODULE_AUTHOR("dennis__chen@ AMDLinuxFGL");
MODULE_DESCRIPTION("The ramdisk implementation with request function");
MODULE_LICENSE("GPL");

為了大家方便,順便也把Makefile放出來,看過前面blog的朋友都知道,這其實(shí)很簡(jiǎn)單,

?
1
2
3
4
5
6
7
8
9
10
11
12
ifneq ($(KERNELRELEASE),)
obj-m := ramdisk.o
 
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
  $(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
  rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.*
endif

這段代碼究竟有沒有用呢?可以按照下面的步驟來做,

    a)make 一下,生成ramdisk.ko;

    b)編譯好了之后,就可以安裝驅(qū)動(dòng)了,在linux下是這么做的,sudo insmod ramdisk.ko;

    c)安裝好了,利用ls /dev/ramhd*, 就會(huì)發(fā)現(xiàn)在/dev下新增兩個(gè)結(jié)點(diǎn),即/dev/ramhda和/dev/ramhdb;

    d)不妨選擇其中一個(gè)節(jié)點(diǎn)進(jìn)行分區(qū)處理, sudo fdisk /dev/ramhda,簡(jiǎn)單處理的話就建立一個(gè)分區(qū), 生成/dev/ramhda1;

    e)創(chuàng)建文件系統(tǒng),sudo mkfs.ext3 /dev/ramhda1;

    f)有了上面的文件系統(tǒng),就可以進(jìn)行mount處理,不妨sudo mount /dev/ramhda1 /mnt;

    g)上面都弄好了,大家就可以copy、delete文件試試了,是不是很簡(jiǎn)單。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/feixiaoxing/article/details/11701797

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久久久一区二区三区 | 青青草原亚洲 | 五月婷婷激情 | 精品国产一区二区三区日日嗨 | 久久色av| 亚洲午夜免费视频 | 欧美精品日韩 | 亚洲区欧美区 | 午夜视频在线 | 日产精品一区二区三区在线观看 | 99re在线观看| 中文字幕91在线 | 91视频网 | 日韩精品在线观看中文字幕 | 91黄视频 | 91色爱| 99青草| 国产免费拔擦拔擦8x高清在线人 | a级免费黄色片 | 国产精品久久久久久久久久久久久久 | 九色精品| 视频一二区 | 久久久成人精品 | 视频一区二区三区在线观看 | 日韩不卡一区二区三区 | 狠狠av| 久久久www | 久久久五月天 | 精品视频一区二区 | 国产精品视频久久久 | 在线视频一区二区三区 | 亚洲高清久久 | 中文字幕一区三级久久日本 | 国产精品网站在线看 | 国产精品v一区二区三区 | 午夜精品福利在线观看 | 午夜视频一区 | 日本黄色大片 | 国产黄色小视频 | 日本黄色录像 | 精品国产欧美一区二区三区成人 |