設置Linux保留物理內存並使用 (1)

在Linux系統中可以通過memblock來設置系統保留物理內存,防止這些內存被內存管理系統分配出去。

 

作者: 彭東林

郵箱: pengdonglin137@163.com

 

平臺

硬件平臺: TQ2440

Linux版本:Linux 3.14.45

 

說明

1. 在tq2440上,物理內存的起始地址是0x30000000,一共有64MB的內存,所以物理內存地址範圍是: 0x30000000 -> 0x33ffffff

2. 可以在uboot傳給kernel的參數bootargs中添加一個"memblock=debug",這樣在Linux啓動的時候,會將設置memblock的信息打印出來

 

參考博文

Linux内核---41.arm 内存初始化

http://bbs.chinaunix.net/thread-4143403-1-1.html

 

代碼調用

在Linux啓動的時候會調用machine相關的代碼定製部分系統保留內存,函數調用如下:

start_kernel

    ----> setup_arch

            ----> arm_memblock_init

                     ----> mdesc->reserve()

所以我們可以修改machine相關的代碼,添加reserve函數的實現。

 

方法一

修改mach-tq2440.c如下:

 1 diff --git a/arch/arm/mach-s3c24xx/mach-tq2440.c b/arch/arm/mach-s3c24xx/mach-tq2440.c
 2 index f9679fb..da75db2 100644
 3 --- a/arch/arm/mach-s3c24xx/mach-tq2440.c
 4 +++ b/arch/arm/mach-s3c24xx/mach-tq2440.c
 5 @@ -23,6 +23,7 @@
 6  #include <linux/platform_device.h>
 7  #include <linux/io.h>
 8  #include <linux/dm9000.h>
 9 +#include <linux/memblock.h>
10  
11  #include <asm/mach/arch.h>
12  #include <asm/mach/map.h>
13 @@ -503,11 +504,28 @@ static void __init tq2440_machine_init(void)
14         s3c_pm_init();
15  }
16  
17 +static void __init tq2440_reserve(void) {
18 +    u32 paddr,size;
19 +
20 +    printk("%s enter.\n", __func__);
21 +
22 +    paddr = 0x32000000;
23 +    size = 0x200000;
24 +
25 +    if (memblock_reserve(paddr, size) < 0) {
26 +        pr_err("failed to reserve DRAM - no memory\n");
27 +               return;
28 +    }
29 +
30 +    printk("reserve : reserve %dM mem\n", size>>20);
31 +}
32 +
33  MACHINE_START(TQ2440, "TQ2440")
34         /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
35         .atag_offset    = 0x100,
36  
37         .init_irq       = s3c2440_init_irq,
38 +    .reserve    = tq2440_reserve,
39         .map_io         = tq2440_map_io,
40         .init_machine   = tq2440_machine_init,
41         .init_time      = samsung_timer_init,

 上面我們在0x32000000開始的地方保留了2MB的物理內存,然後調用memblock_reserve告訴系統。這個在系統的啓動信息中可以看到:

 1 [    0.000000] Machine: TQ2440
 2 [    0.000000] memblock_reserve: [0x00000030008200-0x0000003057fc03] flags 0x0 arm_memblock_init+0x4c/0x1bc
 3 [    0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init+0x158/0x1bc
 4 [    0.000000] tq2440_reserve enter.
 5 [    0.000000] memblock_reserve: [0x00000032000000-0x000000321fffff] flags 0x0 tq2440_reserve+0x1c/0x50
 6 [    0.000000] reserve : reserve 2M mem
 7 [    0.000000] MEMBLOCK configuration:
 8 [    0.000000]  memory size = 0x4000000 reserved size = 0x77ba04
 9 [    0.000000]  memory.cnt  = 0x1
10 [    0.000000]  memory[0x0]    [0x00000030000000-0x00000033ffffff], 0x4000000 bytes flags: 0x0
11 [    0.000000]  reserved.cnt  = 0x3
12 [    0.000000]  reserved[0x0]    [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0
13 [    0.000000]  reserved[0x1]    [0x00000030008200-0x0000003057fc03], 0x577a04 bytes flags: 0x0
14 [    0.000000]  reserved[0x2]    [0x00000032000000-0x000000321fffff], 0x200000 bytes flags: 0x0

  上面的第5行和第14行就是我們自己設置的保留內存範圍信息。在Linux啓動後,在debugfs中也可以看到memblock的信息:

[root@TQ2440 /]# cat /sys/kernel/debug/memblock/memory 0: 0x30000000..0x33ffffff
[root@TQ2440 /]# cat /sys/kernel/debug/memblock/reserved 0: 0x30004000..0x30007fff1: 0x30008200..0x3057fc032: 0x32000000..0x321fffff3: 0x33f60000..0x33ffbfff4: 0x33ffc540..0x33ffc96b5: 0x33ffc980..0x33ffc9f76: 0x33ffca00..0x33ffca037: 0x33ffca20..0x33ffca238: 0x33ffca40..0x33ffca439: 0x33ffca60..0x33ffca6310: 0x33ffca80..0x33ffcad211: 0x33ffcae0..0x33ffcb3212: 0x33ffcb40..0x33ffcb9213: 0x33ffcba0..0x33ffcbbb14: 0x33ffcbc0..0x33ffcdc715: 0x33ffcdd0..0x33ffffff

  其中memory節點中存放的是可用的物理內存地址範圍,reserved表示已經分配出去的物理地址,第2行記錄的就是我們設置的。

既然添加了保留物理內存,那麼如何使用呢?下面我寫了一個簡單的內核模塊,使用我們添加的保留物理內存,下面是內核模塊的代碼:

 1 #include <linux/module.h>
 2 
 3 #define RESERVE_PHY  0x32000000
 4 #define RESERVE_SIZE 0x200000
 5 
 6 static char str[] = "pengdonglin137@163.com\n";
 7 
 8 static __init int reserve_demo_init(void)
 9 {
10     memcpy(phys_to_virt(RESERVE_PHY), str, sizeof(str));
11 
12     printk("%s: virt: %p\n", __func__, phys_to_virt(RESERVE_PHY));
13 
14     return 0;
15 }
16 
17 static __exit void reserve_demo_exit(void)
18 {
19     printk("%s: %s\n", __func__, (char *)phys_to_virt(RESERVE_PHY));
20 }
21 
22 module_init(reserve_demo_init);
23 module_exit(reserve_demo_exit);
24 MODULE_LICENSE("GPL");

  可以看到,我們直接調用函數phys_to_virt將物理地址轉換成虛擬地址,然後直接向這個虛擬地址中寫入數據,在模塊卸載時再將內容打印出出來。

1 [root@TQ2440 /]# insmod nfs/demo.ko 
2 [ 1417.153362] reserve_demo_init: virt: c2000000
3 [root@TQ2440 /]# 
4 [root@TQ2440 /]# rmmod demo
5 [ 1420.986938] reserve_demo_exit: pengdonglin137@163.com
6 [ 1420.986938] 

 可以看到,第2行中得到物理地址0x32000000對應的虛擬地址是0xC2000000。在模塊卸載時打印出了我們之前寫入的內容。

這種方法使用與物理內存在Normal區域的情況。

 

方法二

修改mach-tq2440.c

 1 diff --git a/arch/arm/mach-s3c24xx/mach-tq2440.c b/arch/arm/mach-s3c24xx/mach-tq2440.c
 2 index f9679fb..345a868 100644
 3 --- a/arch/arm/mach-s3c24xx/mach-tq2440.c
 4 +++ b/arch/arm/mach-s3c24xx/mach-tq2440.c
 5 @@ -23,6 +23,7 @@
 6  #include <linux/platform_device.h>
 7  #include <linux/io.h>
 8  #include <linux/dm9000.h>
 9 +#include <linux/memblock.h>
10  
11  #include <asm/mach/arch.h>
12  #include <asm/mach/map.h>
13 @@ -503,11 +504,31 @@ static void __init tq2440_machine_init(void)
14         s3c_pm_init();
15  }
16  
17 +static void __init tq2440_reserve(void) {
18 +    u32 paddr,size;
19 +
20 +    printk("%s enter.\n", __func__);
21 +
22 +    paddr = 0x32000000;
23 +    size = 0x200000;
24 +
25 +    if (memblock_reserve(paddr, size) < 0) {
26 +        pr_err("failed to reserve DRAM - no memory\n");
27 +               return;
28 +    }
29 +
30 +    memblock_free(paddr, size);
31 +    memblock_remove(paddr, size);
32 +
33 +    printk("reserve : reserve %dM mem\n", size>>20);
34 +}
35 +
36  MACHINE_START(TQ2440, "TQ2440")
37         /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
38         .atag_offset    = 0x100,
39  
40         .init_irq       = s3c2440_init_irq,
41 +    .reserve    = tq2440_reserve,
42         .map_io         = tq2440_map_io,
43         .init_machine   = tq2440_machine_init,
44         .init_time      = samsung_timer_init,

 用新kernel啓動,在啓動信息中可以看到:

 1 [    0.000000] Machine: TQ2440
 2 [    0.000000] memblock_reserve: [0x00000030008200-0x0000003057fc03] flags 0x0 arm_memblock_init+0x4c/0x1bc
 3 [    0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init+0x158/0x1bc
 4 [    0.000000] tq2440_reserve enter.
 5 [    0.000000] memblock_reserve: [0x00000032000000-0x000000321fffff] flags 0x0 tq2440_reserve+0x1c/0x68
 6 [    0.000000]    memblock_free: [0x00000032000000-0x000000321fffff] tq2440_reserve+0x3c/0x68
 7 [    0.000000] reserve : reserve 2M mem
 8 [    0.000000] MEMBLOCK configuration:
 9 [    0.000000]  memory size = 0x3e00000 reserved size = 0x57ba04
10 [    0.000000]  memory.cnt  = 0x2
11 [    0.000000]  memory[0x0]    [0x00000030000000-0x00000031ffffff], 0x2000000 bytes flags: 0x0
12 [    0.000000]  memory[0x1]    [0x00000032200000-0x00000033ffffff], 0x1e00000 bytes flags: 0x0
13 [    0.000000]  reserved.cnt  = 0x2
14 [    0.000000]  reserved[0x0]    [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0
15 [    0.000000]  reserved[0x1]    [0x00000030008200-0x0000003057fc03], 0x577a04 bytes flags: 0x0

 在kernel啓動後,在memory和reserved節點中:

[root@TQ2440 /]# cat /sys/kernel/debug/memblock/memory 0: 0x30000000..0x31ffffff1: 0x32200000..0x33ffffff

 可以看到,此時系統中有兩塊物理內存,但是這兩塊物理內存的地址之間不連續,中間有一個大小爲2MB的“洞”。此時在reserved節點看不到這部分內存。

[root@TQ2440 /]# cat /sys/kernel/debug/memblock/reserved 0: 0x30004000..0x30007fff1: 0x30008200..0x3057fc032: 0x33f60000..0x33ffbfff3: 0x33ffc520..0x33ffc94b4: 0x33ffc960..0x33ffc9d75: 0x33ffc9e0..0x33ffc9e36: 0x33ffca00..0x33ffca037: 0x33ffca20..0x33ffca238: 0x33ffca40..0x33ffca439: 0x33ffca60..0x33ffcab210: 0x33ffcac0..0x33ffcb1211: 0x33ffcb20..0x33ffcb7212: 0x33ffcb80..0x33ffcb9b13: 0x33ffcba0..0x33ffcbbb14: 0x33ffcbc0..0x33ffcdc715: 0x33ffcdd0..0x33ffffff

此時在使用這部分保留內存時就不能直接使用了,需要申請,然後映射後才能使用,如下:

 1 #include <linux/module.h>
 2 #include <linux/ioport.h>
 3 #include <linux/io.h>
 4 
 5 #define RESERVE_PHY  0x32000000
 6 #define RESERVE_SIZE 0x200000
 7 
 8 static char str[] = "pengdonglin137@163.com\n";
 9 static void __iomem *addr;
10 
11 static __init int reserve_demo_init(void)
12 {
13 
14     if (!request_mem_region(RESERVE_PHY, RESERVE_SIZE, "my reserve"))
15         return  -EBUSY;
16 
17     addr = ioremap_nocache(RESERVE_PHY, RESERVE_SIZE);
18     memcpy(addr, str, sizeof(str));
19 
20     printk("%s: virt: %p\n", __func__, addr);
21 
22     return 0;
23 }
24 
25 static __exit void reserve_demo_exit(void)
26 {
27     printk("%s: %s\n", __func__, (char *)addr);
28 
29     iounmap(addr);
30     release_mem_region(RESERVE_PHY, RESERVE_SIZE);
31 }
32 
33 module_init(reserve_demo_init);
34 module_exit(reserve_demo_exit);
35 MODULE_LICENSE("GPL");

 然後加載這個模塊,此時會向addr中寫入字符串,在卸載時再打印出來。log如下:

1 [root@TQ2440 /]# insmod nfs/demo.ko 
2 [   43.853848] reserve_demo_init: virt: c5000000
3 [root@TQ2440 /]# 
4 [root@TQ2440 /]# rmmod demo
5 [   49.247204] reserve_demo_exit: pengdonglin137@163.com
6 [   49.247204] 
7 [root@TQ2440 /]# 

 

方法三

在uboot可以通過在bootargs中設置mem參數,告訴kernel可用的物理內存。

修改uboot傳給kernel的bootargs,如下:

setenv bootargs "memblock=debug noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200n8 mem=32M"

 此時啓動Linux,啓動信息中可以看到:

[    0.000000] memblock_reserve: [0x00000030008200-0x00000030589c83] flags 0x0 arm_memblock_init+0x5c/0x1d8
[    0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init+0x8c/0x1d8
[    0.000000] MEMBLOCK configuration:
[    0.000000]  memory size = 0x2000000 reserved size = 0x585a84
[    0.000000]  memory.cnt  = 0x1
[    0.000000]  memory[0x0]    [0x00000030000000-0x00000031ffffff], 0x2000000 bytes flags: 0x0
[    0.000000]  reserved.cnt  = 0x2
[    0.000000]  reserved[0x0]    [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0
[    0.000000]  reserved[0x1]    [0x00000030008200-0x00000030589c83], 0x581a84 bytes flags: 0x0
... ...
[    0.000000] Memory: 26752K/32768K available (3912K kernel code, 214K rwdata, 1176K rodata, 155K init, 176K bss, 6016K reserved)

 可以看到,此時Linux只知道有32MB的物理內存,而實際上板子上有64MB的物理內存。

可以看到memory和reserved節點的內容如下:

 1 [root@TQ2440 /]# cat /d/memblock/memory 
 2    0: 0x30000000..0x31ffffff
 3 [root@TQ2440 /]# 
 4 [root@TQ2440 /]# cat /d/memblock/reserved 
 5    0: 0x30004000..0x30007fff
 6    1: 0x30008200..0x30589c83
 7    2: 0x31fa6000..0x31ffbfff
 8    3: 0x31ffc840..0x31ffca6b
 9    4: 0x31ffca80..0x31ffcaf7
10    5: 0x31ffcb00..0x31ffcb03
11    6: 0x31ffcb20..0x31ffcb23
12    7: 0x31ffcb40..0x31ffcb43
13    8: 0x31ffcb60..0x31ffcb63
14    9: 0x31ffcb80..0x31ffcbda
15   10: 0x31ffcbe0..0x31ffcc3a
16   11: 0x31ffcc40..0x31ffcc9a
17   12: 0x31ffcca0..0x31ffccbb
18   13: 0x31ffccc0..0x31ffcdc3
19   14: 0x31ffcdd0..0x31ffffff

 使用剩餘的物理內存,同樣需要先申請,再映射,然後再使用:

 1 #include <linux/module.h>
 2 #include <linux/ioport.h>
 3 #include <linux/io.h>
 4 
 5 #define RESERVE_PHY  0x32000000
 6 #define RESERVE_SIZE 0x200000
 7 
 8 static char str[] = "pengdonglin137@163.com\n";
 9 static void __iomem *addr;
10 
11 static __init int reserve_demo_init(void)
12 {
13 
14     if (!request_mem_region(RESERVE_PHY, RESERVE_SIZE, "my reserve"))
15         return  -EBUSY;
16 
17     addr = ioremap_nocache(RESERVE_PHY, RESERVE_SIZE);
18     memcpy(addr, str, sizeof(str));
19 
20     printk("%s: virt: %p\n", __func__, addr);
21 
22     return 0;
23 }
24 
25 static __exit void reserve_demo_exit(void)
26 {
27     printk("%s: %s\n", __func__, (char *)addr);
28 
29     iounmap(addr);
30     release_mem_region(RESERVE_PHY, RESERVE_SIZE);
31 }
32 
33 module_init(reserve_demo_init);
34 module_exit(reserve_demo_exit);
35 MODULE_LICENSE("GPL");

 加載模塊,然後卸載,可以看到log:

1 root@TQ2440 /]# insmod /nfs/demo.ko 
2 [  266.998897] reserve_demo_init: virt: c3000000
3 [root@TQ2440 /]# 
4 [root@TQ2440 /]# rmmod demo
5 [  271.735731] reserve_demo_exit: pengdonglin137@163.com
6 [  271.735731] 

 

转载于:https://www.cnblogs.com/pengdonglin137/p/5837115.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动端

http://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html 移动端手淘使用方案 移动端px自动转换rem插件 CSSREM Flexible 转载于:https://www.cnblogs.com/yuruiweb/p/6723580.html

OutOfMemoryError:Java堆空间–分析和解决方法

java.lang.OutOfMemoryError&#xff1a;Java堆问题是在支持或开发复杂的Java EE应用程序时可能会遇到的最复杂的问题之一。 这篇简短的文章将为您提供此JVM HotSpot OutOfMemoryError错误消息的描述&#xff0c;以及在解决该问题之前应如何解决此问题。 有关如何确定要处理的O…

函数伪代码_Excel常用函数

欢迎大家在此收看任我行office教程系列&#xff0c;这一期我来为大家讲什么内容呢&#xff0c;那就是几个office的几个常用函数了&#xff0c;如果您不会这些函数和函数嵌套那么您的Excel电子表格也就别玩了哈&#xff0c;那么他们分别是什么函数呢。咱们现在隆重有请这几位函数…

阻止Ajax多次提交

1、Ajax的abort() xhr $.ajax({})if (xhr){xhr.abort(); } 2、通过在Ajax的beforeSend()方法以及complete()方法添加删除类&#xff0c;对类进行判断&#xff0c;对于两者来回切换的时候&#xff0c;对类的设置不好进行操作上的时候&#xff0c;可以通过使用一个input框&#…

POJ3675 Telescope 圆和多边形的交

POJ3675 用三角剖分可以轻松搞定&#xff0c;数据也小 随便AC。 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<vector> usi…

windows搭建python开发环境方法_04 Windows下搭建 Python 开发环境 - Python 入门教程

前面两个小节中我们已经学习了在 MacOS 和 Ubuntu 中安装 Python 的开发环境。当然&#xff0c;作为用户基数最多的 Windows 操作系统&#xff0c;我们当然不会忘记&#xff0c;这节课我们就来学习下如何在 Windows 下搭建 Python 的开发环境。1. 下载 Python1.1 Python 2 与 P…

消除view旋转后边缘有锯齿的情况

view的layer中有个属性叫 allowsEdgeAntialiasing&#xff1b; 在形变后有边缘有锯齿的话 可以 view.layer.allowsEdgeAntialiasing YES; 消除锯齿 如果直接在*-Info.plist配置 Renders with edge antialiasing YES 会导致UIAlertView显示有问题。转载于:https://www.cnblogs…

Google AppEngine:任务队列API

任务队列 com.google.appengine.api.taskqueue 使用任务队列&#xff0c;用户可以发起一个请求&#xff0c;以使应用程序执行此请求之外的工作。 它们是进行后台工作的强大工具。 此外&#xff0c;您可以将工作组织成小的离散单元&#xff08;任务&#xff09;。 然后&#xf…

打印5列五颗星_55组“数学顺口溜” 大九九乘法口诀表!孩子想学好数学必须背熟...

小学数学需要记住的知识点还是比较多的&#xff0c;看到这些知识点&#xff0c;很多孩子都觉得枯燥&#xff0c;不愿意用心去记。今天&#xff0c;我们给孩子们汇总了55组“数学顺口溜”和大九九乘法口诀&#xff0c;让孩子们在轻松有趣的氛围中学到知识&#xff01;55组“顺口…

C++学习48 对ASCII文件的读写操作

如果文件的每一个字节中均以ASCII代码形式存放数据,即一个字节存放一个字符,这个文件就是ASCII文件(或称字符文件)。程序可以从ASCII文件中读入若干个字符,也可以向它输出一些字符。 对ASCII文件的读写操作可以用以下两种方法&#xff1a;1) 用流插入运算符“<<”和流提取…

文献综述写作之“结构内容”

综述&#xff1a; 又称文献综述&#xff0c;英文名为review。它是利用已发表的文献资料为原始素材撰写的&#xff0c;通过对已发表材料的组织、综合和评价&#xff0c;以及对当前研究进展的考察来澄清问题。在某种意义上&#xff0c;综述论文具有一定的指导性&#xff0c;包括以…

NetBeans 7.2 beta:更快,更有用

NetBeans 7.2的beta版本引起了极大的兴奋。 在本文中&#xff0c;我将简要介绍一下此版本令人兴奋的原因&#xff08;包括更好的性能&#xff0c;提供更多的提示以及集成FindBugs&#xff09;。 NetBeans 7.2 beta在典型的下载捆绑软件中可用&#xff0c;从较小的Java SE&#…

地铁闸门会夹伤人吗_家长们注意啦!又有孩子被地铁闸机夹翻

原标题&#xff1a;家长们注意啦&#xff01;又有孩子被地铁闸机夹翻现代快报讯(通讯员狄公宣记者顾元森)家长带着孩子通过地铁站闸机&#xff0c;这件事情看似简单&#xff0c;却隐藏着风险。近日&#xff0c;南京地铁又发生了一起儿童被闸机夹翻的事&#xff0c;所幸孩子并无…

WPF DevExpress 设置雷达图Radar样式

DevExpress中定义的ChartControl很不错&#xff0c;很多项目直接使用这种控件。 本节讲述雷达图的样式设置 <Grid><Grid.Resources><DataTemplate x:Key"LabelItemDataTemplate" DataType"dxc:SeriesLabelItem"><Border CornerRadius…

mxnet系列教程之1-第一个例子

第一个例子当然是mnist的例子 假设已经成功安装了mxnet 例子的代码如下&#xff1a; cd mxnet/example/image-classification python train_mnist.py这样就会运行下去 train_mnist.py的代码为 """ Train mnist, see more explanation at http://mxnet.io/tutori…

Apache Shiro第3部分–密码学

除了保护网页和管理访问权限外&#xff0c; Apache Shiro还执行基本的加密任务。 该框架能够&#xff1a; 加密和解密数据&#xff0c; 哈希数据&#xff0c; 生成随机数。 Shiro没有实现任何加密算法。 所有计算都委托给Java密码学扩展&#xff08;JCE&#xff09;API。 使…

mysql数据存在就更新_Mysql:如果数据存在则更新,不存在则插入

mysql语法支持如果数据存在则更新&#xff0c;不存在则插入&#xff0c;首先判断数据存在还是不存在的那个字段要设置成unique索引&#xff0c;例如表tb_addrbook如下&#xff1a;索引&#xff1a;语句1:不存在插入INSERT INTO tb_addrbook(num,name,mobile) VALUE(1001,小李,1…

Memcached, Redis, MongoDB区别

mongodb和memcached不是一个范畴内的东西。mongodb是文档型的非关系型数据库&#xff0c;其优势在于查询功能比较强大&#xff0c;能存储海量数据。mongodb和memcached不存在谁替换谁的问题。和memcached更为接近的是redis。它们都是内存型数据库&#xff0c;数据保存在内存中&…

洛谷P1757 通天之分组背包 [2017年4月计划 动态规划06]

P1757 通天之分组背包 题目背景 直达通天路小A历险记第二篇 题目描述 自01背包问世之后&#xff0c;小A对此深感兴趣。一天&#xff0c;小A去远游&#xff0c;却发现他的背包不同于01背包&#xff0c;他的物品大致可分为k组&#xff0c;每组中的物品相互冲突&#xff0c;现在&a…

c3p0 0.9.1.2 配套mysql_连接数据库,使用c3p0技术连接MySQL数据库

读取配置文件连接MySQL数据库先确认已经导入了 mysql 的驱动包db.propertiesdrivercom.mysql.jdbc.Driverurljdbc:mysql://localhost:3306/v20?useUnicodetrue&characterEncodingutf8usernamerootpassword123456JdbcUtil.javapackage com.stu_mvc.utils;import java.io.Fi…