블록 장치 기반 > > Linux 장치 드라이버
글 목록
[0x 110] 블록 장치 속성 정보
[0x 120] 요청 대기 열
[0x 122] 역할
[0x 122] 내용
[0x 200] 관련 데이터 구조
[0x 210] 장치 번호 링크 구조 [struct blk major name]
#include
static struct blk_major_name {
struct blk_major_name *next; //
int major; //
char name[16]; //
} *major_names[BLKDEV_MAJOR_HASH_SIZE];
[0x 220] 블록 설비 관리
[0x 221] 블록 장치 조작 리 셋 함수 집합
#include
struct block_device_operations {
int (*open) (struct block_device *, fmode_t);
int (*release) (struct gendisk *, fmode_t);
int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
int (*direct_access) (struct block_device *, sector_t,void **, unsigned long *);
unsigned int (*check_events) (struct gendisk *disk,unsigned int clearing);
int (*media_changed) (struct gendisk *);
void (*unlock_native_capacity) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
/* this callback is with swap_lock and sometimes page table lock held */
void (*swap_slot_free_notify) (struct block_device *, unsigned long);
struct module *owner;
};
[0x222] 분 구 속성 정보 구조
#include
struct gendisk {
/*【 】 disk_devt()*/
int major;
/*【 】 */
int first_minor;
/*【 】 =1, ;US=16, 15 , disk_max_parts() */
int minors;
/* , /proc/partions sysfs */
char disk_name[DISK_NAME_LEN];
char *(*devnode)(struct gendisk *gd, umode_t *mode);
unsigned int events; /* supported events */
unsigned int async_events; /* async events, subset of all */
struct disk_part_tbl __rcu *part_tbl;
struct hd_struct part0;
/* */
const struct block_device_operations *fops;
/* I/O */
struct request_queue *queue;
/* */
void *private_data;
/* GENHD_FL_* */
int flags;
struct device *driverfs_dev; // FIXME: remove
/*sysfs */
struct kobject *slave_dir;
struct timer_rand_state *random;
atomic_t sync_io; /* RAID */
struct disk_events *ev;
#ifdef CONFIG_BLK_DEV_INTEGRITY
struct blk_integrity *integrity;
#endif
int node_id;
};
[0x 230] 블록 장치 요청 구조
[0x 231] 요청 항목 구조 [struct request]
struct request {
struct list_head queuelist; /* request */
struct call_single_data csd;
struct request_queue *q; /* */
unsigned int cmd_flags;
enum rq_cmd_type_bits cmd_type;
unsigned long atomic_flags;
int cpu;
struct bio *bio; /* */
struct bio *biotail;
struct hlist_node hash; /* hash */
union {
struct rb_node rb_node; /* sort/lookup */
void *completion_data;
};
union {
struct {
struct io_cq *icq;
void *priv[2];
} elv;
struct {
unsigned int seq;
struct list_head list;
rq_end_io_fn *saved_end_io;
} flush;
};
struct gendisk *rq_disk;
struct hd_struct *part;
unsigned long start_time;
#ifdef CONFIG_BLK_CGROUP
unsigned long long start_time_ns;
unsigned long long io_start_time_ns; /* when passed to hardware */
#endif
unsigned short nr_phys_segments; /* */
#if defined(CONFIG_BLK_DEV_INTEGRITY)
unsigned short nr_integrity_segments;
#endif
unsigned short ioprio;
int ref_count;
void *special; /* opaque pointer available for LLD use */
char *buffer; /* kaddr of the current segment if available */
int tag;
int errors;
unsigned char __cmd[BLK_MAX_CDB];
unsigned char *cmd;
unsigned short cmd_len;
unsigned int extra_len; /* length of alignment and padding */
unsigned int sense_len;
unsigned int resid_len; /* residual count */
void *sense;
unsigned long deadline;
struct list_head timeout_list;
unsigned int timeout;
int retries;
rq_end_io_fn *end_io;
void *end_io_data;
struct request *next_rq;
};
[0x 232] 물리 적 페이지 구조 분할 요청 [struct bio]
struct bio {
sector_t bi_sector; /* 512K */
struct bio *bi_next; /* IO */
struct block_device *bi_bdev;
unsigned long bi_flags; /* */
unsigned long bi_rw; /* , */
unsigned short bi_vcnt; /* how many bio_vec's */
unsigned short bi_idx; /* current index into bvl_vec */
unsigned int bi_phys_segments; /* */
unsigned int bi_size; /* */
/* , bi_seg_front_size~bi_seg_back_size*/
unsigned int bi_seg_front_size;
unsigned int bi_seg_back_size;
unsigned int bi_max_vecs; /* max bvl_vecs we can hold */
atomic_t bi_cnt; /* pin count */
struct bio_vec
{
struct page *bv_page;
unsigned int bv_len;
unsigned int bv_offset;
} *bi_io_vec; /* bio : IO , bv_offset bv_len */
struct bio_vec bi_inline_vecs[0];
bio_end_io_t *bi_end_io;
void *bi_private;
#if defined(CONFIG_BLK_DEV_INTEGRITY)
struct bio_integrity_payload *bi_integrity; /* data integrity */
#endif
bio_destructor_t *bi_destructor; /* destructor */
};
[0x 300] 특성 및 인터페이스
[0x 310] 블록 장치 초기 화
[0x 311] 등록 블록 장치 드라이버 [struct blk major name]
#include
/*implement kernel-dir/block/genhd.c */
static inline int major_to_index(unsigned major)
{
return major % BLKDEV_MAJOR_HASH_SIZE;
}
/* */
int register_blkdev(unsigned int major, const char *name)
{
struct blk_major_name **n, *p;
int index, ret = 0;
mutex_lock(&block_class_lock);
/* major 0, */
if (major == 0) {
for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) {
if (major_names[index] == NULL)
break;
}
/*index 0, , */
if (index == 0) {
printk("register_blkdev: failed to get major for %s
",name);
ret = -EBUSY;
goto out;
}
/* */
major = index;
ret = major;
}
/* , */
p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL);
if (p == NULL) {
ret = -ENOMEM;
goto out;
}
/* , */
p->major = major;
strlcpy(p->name, name, sizeof(p->name));
p->next = NULL;
/* , , , 。 */
index = major_to_index(major);
/* , , , */
for (n = &major_names[index]; *n; n = &(*n)->next) {
if ((*n)->major == major)
break;
}
/* */
if (!*n)
*n = p;
else
ret = -EBUSY;
if (ret < 0) {
printk("register_blkdev: cannot get major %d for %s
",major, name);
kfree(p);
}
out:
mutex_unlock(&block_class_lock);
return ret;
}
args 1: 할당 해 야 할 주 장치 번호, 예 를 들 어 0 은 자동 으로 분 배 됩 니 다. 예 를 들 어 N0 은 정적 으로 args 2 를 분배 합 니 다. 디 스 플레이 와 / proc / dev / 의 장치 이름 retval: 성공 major, 실패 errno;
[0x312] 블록 장치 드라이버 로그아웃
#include
/*implement kernel-dir/block/genhd.c */
void unregister_blkdev(unsigned int major, const char *name)
{
struct blk_major_name **n;
/* */
struct blk_major_name *p = NULL;
/* index*/
int index = major_to_index(major);
mutex_lock(&block_class_lock);
/* major */
for (n = &major_names[index]; *n; n = &(*n)->next)
if ((*n)->major == major)
break;
/* */
if (!*n || strcmp((*n)->name, name)) {
WARN_ON(1);
} else { /* */
p = *n;
*n = p->next;
}
mutex_unlock(&block_class_lock);
/* */
kfree(p);
}
args 1: 로그아웃 해 야 할 주 장치 번호;args 2: 로그아웃 해 야 할 장치 이름;[/ proc / dev / 에 표 시 된 장치 이름] retval: 성공 major, 실패 errno;
[0x 313] 블록 장치 추가 준비 작업
struc sbull_dev
{
int size; /* */
u8 *data;
short users;
spinlock_t lock; /* */
short media_change; /* */
struct request_queue *queue; /* IO */
struct gendisk *gd; /* */
struct timer_list timer; /* */
};
/*1. */
struc sbull_dev * blk_dev =(struc sbull_dev *) kzalloc(sizeof(struc sbull_dev),GFP_KERNEL);
/*2. */
spin_lock_init(spinlock_t *lock);
/*3. , node_id =-1*/
struct request_queue *blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
[0x314] 디스크 속성 저장 공간 할당 [struct gendisk]
/*implement kernel-3.4.39/block/genhd.c*/
/* */
struct gendisk *alloc_disk(int minors) { return alloc_disk_node(minors, -1); }
/* kmalloc , ,sysfs */
struct gendisk *alloc_disk_node(int minors, int node_id)
/* */
void del_gendisk(struct gendisk *disk)
[0x315] 커 널 목록 에 블록 장 치 를 추가 합 니 다.
void add_disk(struct gendisk *disk)
{
struct backing_dev_info *bdi;
dev_t devt;
int retval;
WARN_ON(disk->minors && !(disk->major || disk->first_minor));
/* 0, flag GENHD_FL_EXT_DEVT,alloc_disk() */
WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));
disk->flags |= GENHD_FL_UP;
/* */
retval = blk_alloc_devt(&disk->part0, &devt);
if (retval) {
WARN_ON(1);
return;
}
disk_to_dev(disk)->devt = devt;
disk->major = MAJOR(devt);
disk->first_minor = MINOR(devt);
disk_alloc_events(disk);
/* BDI */
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, disk_devt(disk));
/* */
blk_register_region(disk_devt(disk), disk->minors, NULL,exact_match, exact_lock, disk);
/* */
register_disk(disk);
/* , */
blk_register_queue(disk);
WARN_ON_ONCE(!blk_get_queue(disk->queue));
/* sysfs*/
retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,"bdi");
WARN_ON(retval);
disk_add_events(disk);
}
[0x 320] 요청 대기 열 [struct request queue]
[0x 321] 대기 열 구조 초기 화
#include
/*implement kernel-dir/block/blk-core.c*/
typedef void (request_fn_proc) (struct request_queue *q);
struct request_queue *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
{
return blk_init_queue_node(rfn, lock, -1);
}
EXPORT_SYMBOL(blk_init_queue);
/* */
struct request_queue *blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
{
struct request_queue *uninit_q, *q;
uninit_q = blk_alloc_queue_node(GFP_KERNEL, node_id);
if (!uninit_q)
return NULL;
q = blk_init_allocated_queue(uninit_q, rfn, lock);
if (!q)
blk_cleanup_queue(uninit_q);
return q;
}
Func: 요청 대기 열 구조 공간 을 분배 하고 요청 대기 열 args 1: 요청 대기 열 처리 함수 포인터 비우 기;args 2: 블록 설비 가 유지 하 는 자 회전 자물쇠 구 조 는 이것 이 원자 조작 임 을 나타 낸다.args 3: 작 동 하 는 노드 ID 는 보통 - 1 이 모든 노드 로 설정 합 니 다.retval: 요청 대기 열 구 조 를 성공 적 으로 되 돌려 주 었 습 니 다. NULL 을 되 돌려 주 는 데 실 패 했 습 니 다.
[0x 322] 대기 열 관리 인터페이스
/* */
void blk_start_request(struct request *req)
/* , */
struct request *blk_peek_request(struct request_queue *q)
/* */
void blk_dequeue_request(struct request *rq)
/* */
int blk_noretry_request(struct request *rq)
/* */
void blk_requeue_request(struct request_queue *q, struct request *rq)
/* */
void blk_stop_request(struct request *req)
[0x 330] 대기 열 메모리 맵 오프셋 요청
[0x 331] bio 벡터 파라미터 방문
#define bio_page(bio) bio_iovec((bio))->bv_page
#define bio_offset(bio) bio_iovec((bio))->bv_offset
#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx)
#define bio_sectors(bio) ((bio)->bi_size >> 9)
[0x 332] 가상 주소 맵
/* bio , */
static inline void *bio_data(struct bio *bio)
{
if (bio->bi_vcnt)
return page_address(bio_page(bio)) + bio_offset(bio);
return NULL;
}
static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,unsigned long *flags)
{
return bvec_kmap_irq(bio_iovec_idx(bio, idx), flags);
}
#ifdef CONFIG_HIGHMEM
static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
{
unsigned long addr;
/*
* might not be a highmem page, but the preempt/irq count
* balancing is a lot nicer this way
*/
local_irq_save(*flags);
addr = (unsigned long) kmap_atomic(bvec->bv_page);
BUG_ON(addr & ~PAGE_MASK);
return (char *) addr + bvec->bv_offset;
}
static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
{
unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
kunmap_atomic((void *) ptr);
local_irq_restore(*flags);
}
#else
static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
{
return page_address(bvec->bv_page) + bvec->bv_offset;
}
static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
{
*flags = 0;
}
#endif
#define __bio_kunmap_irq(buf, flags) bvec_kunmap_irq(buf, flags)
/*bio */
#define bio_kmap_irq(bio, flags) __bio_kmap_irq((bio), (bio)->bi_idx, (flags))
#define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags)
어떤 부분 은 알 아 볼 수 없고 정리 해 야 합 니 다. 메모리 관리 와 연결 되 어 있 는 것 같 습 니 다!나중에 자신 에 게 닭 피 주 사 를 맞 고 메모리 관리 부분 을 정리 한 다음 에 그 부분 이 끝나 면 다시 업데이트 하 세 요!힘 든 QAQ 를 두 드 리 는 시간 이 얼마 남지 않 았 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로그'메타프로그램 루비 버전 2'3장 읽기동적 방법 Object#send 호출 방법은 약간 메모와 Object#send obj.send(:my_method, 3) Object#send를 사용하면 어떤 방법으로든 호출할 수 있습니다. privete 방법을 호...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.