分享

如何在内核中保留G以上的大内存在驱动中使用

 mediatv 2012-10-19
我的内核版本为 3.4.3 以下测试成功:
1, 找到 linux-3.4.3/init/main.c
2,  在 ————init start_kernel函数中加入如下红色代码:
      {
       setup_command_line(command_line);
        setup_nr_cpu_ids();
        setup_per_cpu_areas();
        smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */

        build_all_zonelists(NULL);
        page_alloc_init();

        printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
        parse_early_param();
        parse_args("Booting kernel", static_command_line, __start___param,
                   __stop___param - __start___param,
                   -1, -1, &unknown_bootoption);

        jump_label_init();

        /*
         * These use large bootmem allocations and must precede
         * kmem_cache_init()
         */
        setup_log_buf(0);
        pidhash_init();
        vfs_caches_init_early();
        sort_main_extable();
        trap_init();

        disk_mem = alloc_bootmem(1000000000);
        mm_init();
     }

3,输出符号:
      unsigned char *disk_mem = NULL;
      EXPORT_SYMBOL(disk_mem);


4, 在驱动中使用:

#include <linux/blkdev.h>
#include <linux/types.h>
#include <linux/module.h>

//unsigned char array_data[16*1024*1024];
unsigned char *array_data;
extern unsigned char *disk_mem;
struct gendisk *my_gendisk;
int major_num = -1;

struct request_queue *my_request_queue = NULL;
static DEFINE_SPINLOCK (lock);


struct block_device_operations my_operations=
{
        .owner                = THIS_MODULE,
};

static void sbd_transfer(sector_t sector,unsigned long nsect, char *buffer, int write)
{
        unsigned long offset = sector<<9;
        unsigned long nbytes = nsect<<9;

        if ((offset + nbytes) > 976560 * 1024) {
                printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
                return;
        }
        if (write)
                memcpy(array_data + offset, buffer, nbytes);
        else
                memcpy(buffer, array_data + offset, nbytes);
}

static void
my_process_on_request_queue(struct request_queue *q)
{

        struct request *req;

        req = blk_fetch_request(q);
        while (req != NULL)
        {
                if (req == NULL || (req->cmd_type != REQ_TYPE_FS))
                {
                        printk (KERN_NOTICE "Skip non-CMD request\n");
                        __blk_end_request_all(req, -EIO);
                        continue;
                }
                sbd_transfer(blk_rq_pos(req), blk_rq_cur_sectors(req),req->buffer, rq_data_dir(req));
                if ( ! __blk_end_request_cur(req, 0) ) {
                        req = blk_fetch_request(q);
                }
        }
}


static int __init
my_init(void)
{

        /* array_data = vmalloc(200 * 1024 * 1024); */
        array_data = disk_mem;
        if (NULL == array_data)
        {
            return -ENOMEM;
        }

        my_gendisk = alloc_disk (1);/*linux/genhd.h*/
        if (NULL == my_gendisk)
        {
                printk(KERN_NOTICE"alloc gendisk failure\n");
                return -ENOMEM;
        }
        major_num = register_blkdev (0,"blocksimple");/*linux/fs.h*/
        if (major_num<=0)
        {
                printk(KERN_WARNING"no major number\n");
                goto major_alloc_error;

        }

        //spin_lock_init (&lock);

        my_request_queue = blk_init_queue (my_process_on_request_queue,&lock);

        if (NULL == my_request_queue)
        {
                printk("request queue error");
                goto requeue_alloc_error;

        }
        strcpy(my_gendisk->disk_name ,"BlockSimple");
        my_gendisk->major = major_num;
        my_gendisk->first_minor = 0;
        my_gendisk->queue = my_request_queue;
        my_gendisk->fops = &my_operations;
        //set_capacity (my_gendisk,16*1024*2);
        set_capacity (my_gendisk,976560 * 2);


        add_disk (my_gendisk);
        return 0;




requeue_alloc_error:
        unregister_blkdev(major_num, "blocksimple");
major_alloc_error:
        del_gendisk(my_gendisk);
        return -ENOMEM;

}


static void __exit
my_exit(void)
{
        blk_cleanup_queue (my_request_queue);

        unregister_blkdev(major_num, "blocksimple");
     
        del_gendisk(my_gendisk);
        put_disk (my_gendisk);
}


module_init (my_init);
module_exit (my_exit);
                                                                                                                                                                                 127,1         90%
 




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多