[Linux] 2. vSSD Driver, RAM 디스크 기반 vSSD와 Driver

임채진·2024년 12월 9일

Linux System Programming

목록 보기
2/2

Loopback Device를 이용한 가상 SSD 생성이 완료되었으므로, 이제 Linux 커널의 블록 디바이스 프레임워크를 활용해 vSSD Driver를 개발합니다. 이 드라이버는 RAM 디스크를 활용하여 데이터를 저장하여, Loopback Device의 역할을 대신합니다.

touch devicedriver.c Makefile app.c

2.1 코드 구조

1) devicedriver.c: vSSD Driver 모듈 코드
2) app.c: vSSD Driver를 테스트하는 사용자 애플리케이션
3) Makefile: 빌드 파일

2.2 vSSD Driver 코드

다음은 vSSD Driver의 주요 코드입니다.
RAM 디스크를 생성하고, 블록 디바이스 연산을 구현합니다.


#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/blk-mq.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>

#define VSSD_NAME "vssd"
#define RAMDISK_SIZE (1024 * 1024) // 1GB

static struct gendisk *my_disk;
static struct request_queue *my_queue;
static struct blk_mq_tag_set *tag_set;
static int major_num;
static char *ramdisk;

static blk_status_t my_request(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) {
    struct request *req = bd->rq;
    blk_mq_start_request(req);
    pr_info("Handling request: cmd_flags=%x\n", req->cmd_flags);
    blk_mq_end_request(req, BLK_STS_OK);
    return BLK_STS_OK;
}

static struct blk_mq_ops mq_ops = {
    .queue_rq = my_request,
};

static struct block_device_operations my_block_ops = {
    .owner = THIS_MODULE,
};

static int __init my_block_init(void) {
    ramdisk = vmalloc(RAMDISK_SIZE);
    if (!ramdisk) {
        pr_err("Failed to allocate ramdisk\n");
        return -ENOMEM;
    }
    memset(ramdisk, 0, RAMDISK_SIZE);

    major_num = register_blkdev(0, VSSD_NAME);
    if (major_num < 0) {
        pr_err("register_blkdev failed\n");
        vfree(ramdisk);
        return major_num;
    }

    tag_set = kzalloc(sizeof(*tag_set), GFP_KERNEL);
    if (!tag_set) {
        unregister_blkdev(major_num, VSSD_NAME);
        vfree(ramdisk);
        return -ENOMEM;
    }
    tag_set->ops = &mq_ops;
    tag_set->nr_hw_queues = 1;
    tag_set->queue_depth = 128;

    if (blk_mq_alloc_tag_set(tag_set)) {
        kfree(tag_set);
        unregister_blkdev(major_num, VSSD_NAME);
        vfree(ramdisk);
        return -ENOMEM;
    }

    my_queue = blk_mq_init_queue(tag_set);
    if (IS_ERR(my_queue)) {
        blk_mq_free_tag_set(tag_set);
        unregister_blkdev(major_num, VSSD_NAME);
        vfree(ramdisk);
        return PTR_ERR(my_queue);
    }

    my_disk = blk_mq_alloc_disk(tag_set, NULL);
    if (!my_disk) {
        blk_cleanup_queue(my_queue);
        blk_mq_free_tag_set(tag_set);
        unregister_blkdev(major_num, VSSD_NAME);
        vfree(ramdisk);
        return -ENOMEM;
    }
    my_disk->major = major_num;
    my_disk->first_minor = 0;
    my_disk->fops = &my_block_ops;
    my_disk->queue = my_queue;
    snprintf(my_disk->disk_name, 32, VSSD_NAME);
    set_capacity(my_disk, RAMDISK_SIZE / 512);

    add_disk(my_disk);
    pr_info("Module loaded: /dev/%s\n", VSSD_NAME);
    return 0;
}

static void __exit my_block_exit(void) {
    del_gendisk(my_disk);
    put_disk(my_disk);
    blk_cleanup_queue(my_queue);
    blk_mq_free_tag_set(tag_set);
    unregister_blkdev(major_num, VSSD_NAME);
    vfree(ramdisk);
    pr_info("Module unloaded\n");
}

module_init(my_block_init);
module_exit(my_block_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("임채진");
MODULE_DESCRIPTION("Virtual SSD Block Device");

2.3 사용자 애플리케이션 코드

다음은 vSSD Driver를 테스트하는 app.c 코드입니다.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define DEVICE_PATH "/dev/vssd"

int main() {
    int fd;
    char write_buf[] = "Hello, vSSD!";
    char read_buf[512];

    fd = open(DEVICE_PATH, O_RDWR);
    if (fd < 0) {
        perror("Failed to open device");
        return EXIT_FAILURE;
    }

    write(fd, write_buf, strlen(write_buf));
    lseek(fd, 0, SEEK_SET);
    read(fd, read_buf, sizeof(read_buf));

    printf("Read from device: %s\n", read_buf);
    close(fd);

    return EXIT_SUCCESS;
}

2.4

(1) vSSD Driver 로드

Loopback Device를 대신하는 RAM 디스크 기반 드라이버를 로드합니다.

	$ sudo insmod devicedriver.ko

(2) 디바이스 파일 생성

주의: <major_number>는 드라이버 로드 후 dmesg에서 확인할 수 있습니다.

  $ sudo mknod /dev/vssd b <major_number> 0
  $ sudo chmod 666 /dev/vssd

(3) RAM 디스크 동작 테스트

첫 번째 실습과 동일한 방식으로 파일 시스템 생성 및 테스트를 진행합니다.

# ext4 파일 시스템 생성
$ sudo mkfs.ext4 /dev/vssd

# 가상 SSD 마운트
$ sudo mount /dev/vssd /mnt/virtual_ssd

# 테스트
$ echo "Hello, vSSD!" > /mnt/virtual_ssd/testfile
$ cat /mnt/virtual_ssd/testfile

결론

1.	첫 번째 실습: Loopback Device를 활용해 가상 SSD 환경을 설정하고 테스트합니다.
2.	두 번째 실습: vSSD Driver를 구현하여 RAM 디스크를 활용한 블록 디바이스 드라이버를 개발합니다.

이 두 실습을 통해 Linux 블록 디바이스의 기본 구조를 이해하고, Loopback Device와 커널 드라이버의 차이점을 배울 수 있습니다.

0개의 댓글