不点 发表于 2015-6-26 09:08:36

malloc 和 free 的问题,应该抽时间进行完善

这个我以前也提到过,我现在也没有时间去研究代码,不知道这个工作有没有进展。如果没做的话,我觉得 chenall 或 yaya 在空闲时可以做一做。

首先我需要把意思说清楚。

malloc 是内存分配函数。可是,grub4dos 是由内核和用户程序两个部分构成的。grub4dos 内核里面所建立的内存分配链表(其实是数组),是用来给应用程序使用的,不是让内核使用的。内核应该严格使用 32M 以内的空间,不可以以任何方式使用到其他内存空间。目前这个问题之所以不太严重,是因为我们的用户进程设计还不完善(而且太简单),还没有出现内核与用户进程内存使用发生冲突的情况。

为了展示其严重性,我试试继续加以解释。

我们知道,DOS 在给 .com 程序分配内存时,是将全部可用内存都分配给了这个 .com 进程。而我当初为 grub4dos 设计进程管理的时候,就是以 dos 的 .com 程序的逻辑框架为参考模型的。

好的,假如我们在 grub4dos 执行某个 32 位程序的时候,分配该程序全部的内存,那么,此时如果这个程序要调用内核的某个功能,而假如碰巧此时的内核又要用 malloc 来分配内存,则此时已经没有内存了,因为内存全部分配给用户的 32 位程序了。因此,此时的功能调用会失败。

所以,内核使用的 malloc 函数应该与用户使用的 malloc 函数隔离开来。内核可以有 kmalloc、kfree 之类的函数,而且它们只能触碰 32M 以内的专门保留给内核所使用的内存,而不可以超限使用内存。

可以参考一下 Linux 的 kernel,它的内核就使用了 kmalloc 之类的函数,与用户进程的 malloc 函数完全隔离。

2011yaya2007777 发表于 2015-7-10 12:50:06

本帖最后由 2011yaya2007777 于 2015-7-10 13:02 编辑

这个问题不是太懂。我看到有 grub_malloc,grub_free 函数。这个函数是供内核使用的,还是供用户使用的?
只是登记一下使用内存的位置及尺寸,以便供后续使用者查询?还是直接分配合适的内存?

这还有个是否遵守协定的问题。不使用函数,直接分配和使用内存,也没有办法。

我觉得对于32M内核使用内存,开发者应当在 shared.h 予以登记,至少在 .h 文件登记。
不要在代码中使用 (unsigned char *)0x1000000 这样直接赋值。没有多少人有时间在浩瀚的代码中寻找内存使用位置。

我查询到的内存分布,肯定还有遗漏。


名称                                                                        中文                                                                        位置                                长度                                定义

BOOT_PART_TABLE                                                引导分区表                                                                0x07be                        0x200                        shared.h

MB_CMDLINE_BUF                                                多重引导命令行缓冲区地址                                        0x7000                        0x1000                        shared.h
BOOTSEC_LOCATION                                                BOOTSEC位置                                                        0x7C00                                                         shared.h
mbr                                                                        主文件分配表                                                        0x8000                        0x200                        disk_io.c
terminfo                                                                                                                                        0x8000                        0x200                        builtins.c
LINUX_HEAP_END_OFFSET                                        LINUX堆结束偏移                                                0x9000 - 0x200                                                 shared.h
LINUX_ZIMAGE_ADDR                                                LINUX Z映像地址                                                0x10000                                                         shared.h


SCRATCHADDR                                                        SCRATCH地址                                                        0x1F000                        0x200                        shared.h
SCRATCHADDR                                                                                                                                0x1F000                                                        builtins.c
GEOMTUNE_SEG                                                                                                                         0x20000                        0x10000                        ams.sgeometry_tune
                                                                        读缓存                                                                0x2F000                        0x200                        bios.c
                                                                        读缓存                                                                0x2F000                        0x800                        builtins.c
GEOMTUNE_BUFFERSEG                                                                                                                0x30000                        0x8000                        ams.sgeometry_tune
BUFFERADDR                                                        缓冲区地址                                                                0x30000                        0x10000                        shared.h
PXE_BUF                                                                PXE缓存地址                                                        0x30000                        0xFE00                        fsys_pxe.c
ADDR_RET_STR                                                 地址返回字符串                                                        0x4CA00                                                         shared.h
CMD_RUN_ON_EXIT                                                 命令运行在退出                                                        0x4CB08                                                         shared.h
LINUX_OLD_REAL_MODE_ADDR                                LINUX旧实模式地址                                                0x90000                                                         shared.h
VIDEOMEM                                                         图形视频内存                                                        0xA0000
HERCULES_VIDEO_ADDR        RAW_ADDR                 hercules视频地址                                                0xB0000                                                        hercules,h

LINUX_BZIMAGE_ADDR                                        LINUX BZ映像地址                                              0x100000                                                         shared.h
buf_addr                                                                存放UNIFONT字符                                                0x100000                        0x10000                        builtins.c
FB_MENU_ADDR                                                        FB菜单地址                                                        0x150000                        0x10000                        fsys_fb.c
                                                                        读缓存                                                                0x200000                                                        builtins.c
                                                                        读缓存                                                                0x2A0000                                                        builtins.c
HMA_ADDR                                                                                                                                0x2B0000                                                        builtins.c
HMA_ADDR                                                        高端内存区地址                                                        0x2B0000                                                         shared.h

                                                                        第二块固定变量区                                                0x307000~0x308200        0x1200
use_preset_menu                                                 使用预值菜单地址                                                0x307FF8                                                         shared.h
preset_menu                                                         预设菜单                                                                0x307FFC                                                        stage2
                                                                        cpu 的信息                                                                0x308000                                                        0x20


JPG_FILE                                                                jpg文件缓存                                                        0x3A0000                        0x8000                        graphics.h
MENU_TITLE                                                        菜单总标题缓存                                                        0x3A8000                        0x800                        shared,h

#define VSHADOW VSHADOW1
/* 8x16 点阵字符,总字符 = 80*30. 平面尺寸 = 80*30*16 = 38400字节 */
/* 8x16 点阵字符,总字符 = 100*37. 平面尺寸= 800*600/8 = 60000字节 */
VSHADOW1                                                                                                                                0x3A0000                        0xea60                        graphics.c
VSHADOW2                                                                                                                                0x3AEA60                        0xea60                        graphics.c
VSHADOW4                                                                                                                                0x3BD4C0                        0xea60                        graphics.c
VSHADOW8                                                                                                                                0x3CBF20                        0xea60                        graphics.c                //end at 0x3DA980
text                                                                                                                                                0x3FC000                        100*37*4 = 0x39D0        graphics.c


FSYS_BUF RAW_ADDR                                         文件系统缓存地址                                                0x3E0000                        0x8000                        shared.h
PART_TABLE_BUF                                                分区表缓存地址                                                        0x3E8000                        0x1000                         shared.h
PART_TABLE_TMPBUF                                                分区表临时缓存地址                                                0x3E9000                        0x200                         shared.h
CMDLINE_BUF                                                        命令行缓存地址                                                0x3E9200                        0x640                         shared.h
COMPLETION_BUF                                                完成缓冲区地址                                                0x3E9840                        0x640                         shared.h
UNIQUE_BUF                                                        UNI字符串缓冲区地址                                        0x3E9E80                        0x640                         shared.h
HISTORY_BUF                                                        命令行历史缓冲区地址                                        0x3EA4C0                        0x320                         shared.h
font8x16                                                                                                                                        0x580000                        0x1000                        builtins.c
mem_alloc_array_start                                                                                                                0x800000                                                        ams.s
mem_alloc_array_end                                                                                                                        0xA00000                                                        ams.s
page_map_start                                                                                                                                0xA00000                                                        ams.s
page_map_end                                                                                                                                0xE00000                                                        ams.s
PAGING_TABLES_BUF                                                分页表缓冲区                                                        0xEFC000                        0x4000                        shared.h
PAGING_TABLES_BUF                                              分页表缓存                                                                0xEFC000                        0x4000                        shared.h

IMAGE_BUFFER                                                        vbe图像缓存                                                        0x1000000                        0xa8c000                        graphics.h                (1920*1440*4)                                                                               
UNIFONT_START                                                UNI字体开始                                                        0x1800000
SYSTEM_RESERVED_MEMORY                                系统保留的内存                                                        0x2000000

GRUB_MOD_ADDR                                                                                                                        0x2000000-100000                                        builtins.c
cmd_buffer                                                        命令缓存                                                                0x2000000-0x10000                                        cmdline.c
PRINTF_BUFFER                                                 打印缓存                                                                0x2000000+0x20000                                        cmdline.c


LINUX_INITRD_MAX_ADDRESSLINUX                        初始化RAM磁盘最大地址                                        0x38000000                                                 shared.h



graphics.c 使用 0x3A0000 - 0x3DA980 和 0x3FC000 - 0x3FF9D0 切换到实模式扩展chainloader代码地址


VM_RFC1048                                                        0x63825363L                                                                                                                        pxe.h
linalloc_topaddr                                                        窗口的大小                                                                ((saved_mem_upper << 10) + 0x100000) 0x8000UL                gunzip.c

fsys_pxe.c
#define PXE_MIN_BLKSIZE        128
#define PXE_MAX_BLKSIZE        16384
#define DOT_SIZE        1048576


#define CMP_BUF_SIZE 0x8000ULL
addr1 = (char *) RAW_ADDR (0x100000);
addr2 = addr1 + CMP_BUF_SIZE;

不点 发表于 2015-7-10 16:57:47

当初这个不良的状况,可以说是我造成的,也可以说不是我,而是原始的 GNU GRUB 开发者造成的。他们并未写一个内存分配函数,而是直接使用内存。而且那时的情况很糟糕,统统只使用 1M 以内的常规内存,所以那时的程序无法增加功能;稍微改动一点,就容易死机崩溃。

chenall 写了一个 malloc 函数,不过,在我看来,应该把这个函数劈成两个,一个是内核使用的 kmalloc,另一个是用户使用的 malloc。内核所使用的 malloc,只能严格使用 32M 以内的可用空闲空间,用过之后应该用 kfree 函数来释放内存。比如说,可以让 kmalloc 只使用从 28M 至 32M 之间的 4M 内存。只要在 32M 以内找一块比较大的空闲内存可供 kmalloc 使用便可。

而用户使用的内存,倒是可以像目前这样,用 mem alloc array 来圈定。所以,需要做的工作其实是增加一个 kmalloc 函数,而保持现在的 malloc 函数不动。增加 kmalloc 函数之后,内核中所有对 malloc 的调用,都应该改为对 kmalloc 的调用。同时,用户的程序不可以使用 kmalloc 函数,而只能使用 malloc 函数。也就是说,不给用户提供 kmalloc 函数的接口,让用户根本就无法使用它。

我好像已经提到了,这个问题并不迫切,可以在自己确实愿意做的时候再做。

再提醒注意一点:位于 15M 至 16M 之间的内存,是 grub4dos 不使用的内存。原因是,这个 1M 空间被某些主板芯片使用,如果我们也使用它,就会与主板 BIOS 发生冲突。所以,迫使我们放弃使用这 1M 内存。在这样的机器上,其主板的 int15/E820/E801 应该会报告这个空间不是用户可用的自由空间,而是被主板保留的空间(甚至也有可能是不可写的 ROM)。

chenall 发表于 2015-7-10 17:11:14

我也觉得目前GRUB4DOS的内存使用情况确实是有一些乱。

要整理的话需要有足够的时间,而且我对这些不是很熟悉,不清楚哪一些不能改。

yaya可以尝试整理一下,也方便后来的开发者。我觉得除非有必要否则能够使用自动分配的内存就尽量使用自动分配,可以避免内存冲突。

不点 发表于 2015-7-10 17:30:18

另外,你上面列出的那些内存,好像存在冲突的情况。比如说,

#define CMP_BUF_SIZE 0x8000ULL
addr1 = (char *) RAW_ADDR (0x100000);
addr2 = addr1 + CMP_BUF_SIZE;

老天爷,1M 处的 64K 内存已经被 dd 命令使用了。不过 dd 也仅仅是把这块内存作为缓冲区使用。所以,好像并未真正产生冲突。如果你将来写出个 kmalloc 函数,那就可以让 dd 和 cmp 命令都使用 kmalloc 来分配内存,而不是使用固定的内存地址。

那些 VSHADOW 内存,是支持 VGA 图形模式的内存。目前其实 VGA 还被 grub4dos 内核支持,只是不建议使用罢了(而是建议用户使用 VBE 图形模式)。所以,这些 VSHADOW 内存,还得保留着,它们占用的空间也不算是太大。

虽然 VGA 代码基本不使用了,但是也尽量不要删除掉。因为 grub.exe 和 DOS 互通的时候,从 grub4dos 返回到 DOS,需要经过 VGA 的图形模式转换,才能正常进入中文 DOS 环境。否则进入 DOS 后出现屏幕无反应的假死现象。这是因为,当 grub4dos 运行于 VBE 模式,如果此时直接切换到 DOS,则 DOS 的图形模式不对(中文 DOS 基本上都是 VGA 图形模式),调用 VGA BIOS 清屏也没用。必须在进入 DOS 前利用 graphicsmode 0x12 进行中转,才能保证一切正常。 利用模式 0x12 中转,可以适应中英文两种 DOS 环境,非常好,非常可靠。这个工作我在当时就已经做好了,将来如果有需要的时候,只需打上补丁即可(补丁就在论坛上那个相关的帖子里面)。

页: [1]
查看完整版本: malloc 和 free 的问题,应该抽时间进行完善