免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7292 | 回复: 7
打印 上一主题 下一主题

请教关于“kmalloc分配内存出错”,感谢 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-01 23:09 |只看该作者 |倒序浏览
10可用积分
我的目标平台为 s3c2410-linux2.4.18
宿主机为readhat9.0
做对UART2以DMA方式进行数据读取的驱动

在设置缓冲区的函数里,
当为DMA内核缓冲区数据结构(uart_buf_t)分配内存时,
(构建s->nbfrags个这样的缓冲区,所以乘以 s->nbfrags)
(s->nbfrags根据需要设定,在我看的音频驱动中,设定为最大8个)

kmalloc(sizeof(uart_buf_t) * s->nbfrags, GFP_KERNEL);
// 其中 sizeof(uart_buf_t) = 36
// s->nbfrags = 2

当s->nbfrags为2或者3时,能正常分配。当s->nbfrags为1, 4, 8 ... 出现如下错误:

kernel BUG at slab.c:1099!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c3b2c000
*pgd = 33c11001, *pmd = 33c11001, *pte = 00000000, *ppte = 00000000
Internal error: Oops: ffffffff
CPU: 0
pc : [<c001e858>]    lr : [<c0025d74>]    Tainted: P
sp : c3b35e60  ip : c3b35e18  fp : c3b35e70
r10: c3b34000  r9 : 00149898  r8 : 00000000
r7 : 00000000  r6 : c02073b0  r5 : 00000007  r4 : 00000000
r3 : 00000000  r2 : 00000001  r1 : 00000001  r0 : 00000001
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  Segment user
Control: C000317F  Table: 33B2C000  DAC: 00000015
Process insmod (pid: 53, stackpage=c3b35000)
Stack: (0xc3b35e50 to 0xc3b36000)
......
......

----------------------------------------------------------------------------

请问:

我看了kmalloc的用法,原型是 void *kmalloc(unsigned int len, int priority);
priority,也应该传入参数GFP_KERNEL。

只是分配的内存长度不一样怎么会出错呢? 而且我分配的内存空间并不大。

请高手指点,感谢!


----------------------------------------------------------------------------
kmaolloc的相关代码如下:

void * kmalloc (size_t size, int flags)
{
        cache_sizes_t *csizep = cache_sizes;

        for (; csizep->cs_size; csizep++) {
                if (size > csizep->cs_size)
                        continue;
                return __kmem_cache_alloc(flags & GFP_DMA ?
                         csizep->cs_dmacachep : csizep->cs_cachep, flags);
        }
        return NULL;
}

static cache_sizes_t cache_sizes[] = {
#if PAGE_SIZE == 4096
        {    32,        NULL, NULL},
#endif
        {    64,        NULL, NULL},
        {   128,        NULL, NULL},
        {   256,        NULL, NULL},
        {   512,        NULL, NULL},
        {  1024,        NULL, NULL},
        {  2048,        NULL, NULL},
        {  4096,        NULL, NULL},
        {  8192,        NULL, NULL},
        { 16384,        NULL, NULL},
        { 32768,        NULL, NULL},
        { 65536,        NULL, NULL},
        {131072,        NULL, NULL},
        {     0,        NULL, NULL}
};

论坛徽章:
0
2 [报告]
发表于 2008-08-03 11:18 |只看该作者
先判断下返回地址是否为空也会出现这样的情况吗??

论坛徽章:
0
3 [报告]
发表于 2008-08-04 11:25 |只看该作者

难道要做指针转换?

int s3c2410_dma_queue_buffer(dmach_t channel, void *buf_id,
                             dma_addr_t data, int size, int write)
中:

sizeof(*buf)等于24 )。DMA缓冲区的指针。buf的定义为:(

          dma_buf_t *buf;

原来kmalloc的语句为:

          buf = kmalloc(sizeof(*buf), GFP_ATOMIC);

我改为:

          buf = (dma_buf_t*) kmalloc(sizeof(*buf), GFP_ATOMIC);

好像就没出问题了。

论坛徽章:
0
4 [报告]
发表于 2008-08-04 11:45 |只看该作者

kmalloc能处理的最小的内存块是32或者64 ?

sizeof(*buf) = sizeof(dma_buf_t) = 24

但在《LDD3》page217, 有:
   kmalloc能处理的最小的内存块是32或者64,取决于当前体系结构中使用的页面大小


我用kmalloc分配的内存为24字节。这个32/64指内存块,不是指字节吧。

是不是这个原因引起的呢?

论坛徽章:
0
5 [报告]
发表于 2008-08-04 13:54 |只看该作者
原帖由 robotlee2002 于 2008-8-4 11:45 发表
sizeof(*buf) = sizeof(dma_buf_t) = 24

但在《LDD3》page217, 有:
   kmalloc能处理的最小的内存块是32或者64,取决于当前体系结构中使用的页面大小

我用kmalloc分配的内存为24字节。这个32/64指内存 ...



假如你想kmalloc()size大小的内存,那么内核从malloc_sizes[]数组里找到最小的一个元素,其cssize比size要大,见下面代码。
如果你分配24字节,不足malloc_sizes[]里面最小的32字节,那么内核就会kmem_cache_alloc(cachep,flags)从数组第一个32字节内
存slab对应的cachep里面摘下一块内存给你(这个内存的大小为32字节),虽然你只用到其中的24字节。

void * kmalloc (size_t size, int flags)
{
      struct cache_sizes_t *csizep = malloc_sizes;
      kmem_cache_t *cachep;
      for (; csizep->cs_size; csizep++) {
                if (size > csizep->cs_size)
                        continue;
                if(flags & GFP_DMA)
                     cachep=csizep->cs_dmacachep;
                else
                     cachep=csizep->cs_cachep;
                 return kmem_cache_alloc(cachep,flags);
        }
        return NULL;
}

论坛徽章:
0
6 [报告]
发表于 2008-08-04 16:03 |只看该作者

错误总是一会出现,一会不出现。

...
s3c2410_dma_queue_buffer(291): before: kmalloc

kernel BUG at slab.c:1099!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c3b40000
*pgd = 33b95001, *pmd = 33b95001, *pte = 00000000, *ppte = 00000000
Internal error: Oops: ffffffff
CPU: 0
pc : [<c001e858>]    lr : [<c0025d74>]    Tainted: P
sp : c3c7fec4  ip : c3c7fe7c  fp : c3c7fed4
r10: 00000000  r9 : 00000000  r8 : 00000400
r7 : 33ad5400  r6 : c02070a0  r5 : 00000002  r4 : 00000000
r3 : 00000000  r2 : 00000001  r1 : 00000001  r0 : 00000001
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  Segment user
Control: C000317F  Table: 33B40000  DAC: 00000015
Process test (pid: 54, stackpage=c3c7f000)
Stack: (0xc3c7feb4 to 0xc3c80000)
fea0:                                              c0025d74 c001e858 60000013
fec0: ffffffff c02070a0 c3c7fefc c3c7fed8 c003cef4 c001e824 c02070a0 00000002
fee0: c48f2b18 33ad5400 00000400 00000000 c3c7ff14 c3c7ff00 c003d3b4 c003ced0
ff00: c03711c4 00000001 c3c7ff40 c3c7ff18 c48f0504 c003d2a0 00000001 c03711c4
ff20: 00000001 c48f29f0 02008ee0 00000800 c48f1fec c3c7ff78 c3c7ff44 c48f11b0
ff40: c48f0490 00000000 02008ee0 c3bfb7c0 00000800 c3bfb7c0 ffffffea 00000000
ff60: 02008ee0 c3c7e000 401983f8 c3c7ffa4 c3c7ff7c c0046014 c48f1044 401983f8
ff80: c3c7ffac 02008d78 bffffddc 0200053c 00000003 c00197c4 00000000 c3c7ffa8
ffa0: c0019640 c0045f48 02008d78 c001f808 00000003 02008ee0 00000800 02008d70
ffc0: 02008d78 bffffddc 0200053c 00000001 4019a4c4 02000750 401983f8 bffffe68
ffe0: 00000000 bffffd70 0000230c 40029000 60000010 00000003 00000000 00000000
Backtrace:
Function entered at [<c001e814>] from [<c003cef4>]
r4 = C02070A0
Function entered at [<c003cec0>] from [<c003d3b4>]
Function entered at [<c003d290>] from [<c48f0504>]
r5 = 00000001  r4 = C03711C4
Function entered at [<c48f0480>] from [<c48f11b0>]
Function entered at [<c48f1034>] from [<c0046014>]
Function entered at [<c0045f38>] from [<c0019640>]
r8 = C00197C4  r7 = 00000003  r6 = 0200053C  r5 = BFFFFDDC
r4 = 02008D78
Code: eb001c9e e59f0014 eb001c9c e3a03000 (e5833000)
Segmentation fault

奇怪了,错误一会出现。把板子重启后,可能又可以。
我的源码见附件中,感谢熟悉的大拿帮我看看,谢谢。

[ 本帖最后由 robotlee2002 于 2008-8-4 20:08 编辑 ]

linux_uart2-dma.rar

83.88 KB, 下载次数: 66

论坛徽章:
0
7 [报告]
发表于 2008-08-04 16:50 |只看该作者
这个是嵌入式系统,发生这种问题只有一种可能,指针未对齐,或者因此导致的非法内存访问。至于原因,很可能在你那个sizeof(uart_buf_t) = 36上,你换一个32的尝试过没有?或者强制对齐。
还有种导致这种不对齐原因的是,传入函数的缓冲区指针最好能用memmove复制一份再新的函数里,否则也可能产生这种不对齐的影响。
都尝试过后,有无进展请回复一下哦

论坛徽章:
0
8 [报告]
发表于 2008-09-09 18:16 |只看该作者
sizeof(*buf) 多大,你想求的长度是这个吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP