kmalloc() kcalloc() vmalloc() 和 kzalloc() 之间有什么区别?
Hi all,
我目前正在调试设备驱动程序,并且遇到内核恐慌。检查回溯或错误日志后,问题似乎出在 kmalloc 上。我在想也许我可以用其他分配函数来改变 kmalloc 。他们有什么区别?
这是错误日志:
Unable to handle kernel NULL pointer dereference at virtual address 0000000d
pgd = c7bdc000
[0000000d] *pgd=4785f031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1] PREEMPT
Modules linked in: bcm5892_secdom_fw(P) bcm5892_lcd snd_bcm5892 msr bcm5892_sci bcm589x_ohci_p12 bcm5892_skeypad hx_decoder(P) pinnacle hx_memalloc(P) bcm_udc_dwc scsi_mod g_serial sd_mod usb_storage
CPU: 0 Tainted: P (2.6.27.39-WR3.0.2ax_standard #1)
PC is at __kmalloc+0x70/0xdc
LR is at __kmalloc+0x48/0xdc
pc : [<c0098cc8>] lr : [<c0098ca0>] psr: 20000093
sp : c7a9fd50 ip : c03a4378 fp : c7a9fd7c
r10: bf0708b4 r9 : c7a9e000 r8 : 00000040
r7 : bf06d03c r6 : 00000020 r5 : a0000093 r4 : 0000000d
r3 : 00000000 r2 : 00000094 r1 : 00000020 r0 : c03a4378
Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
Control: 00c5387d Table: 47bdc008 DAC: 00000015
Process sh (pid: 1088, stack limit = 0xc7a9e260)
Stack: (0xc7a9fd50 to 0xc7aa0000)
fd40: c7a6a1d0 00000020 c7a9fd7c c7ba8fc0
fd60: 00000040 c7a6a1d0 00000020 c71598c0 c7a9fd9c c7a9fd80 bf06d03c c0098c64
fd80: c71598c0 00000003 c7a6a1d0 bf06c83c c7a9fdbc c7a9fda0 bf06d098 bf06d008
fda0: c7159880 00000000 c7a6a2d8 c7159898 c7a9fde4 c7a9fdc0 bf06d130 bf06d078
fdc0: c79ca000 c7159880 00000000 00000000 c7afbc00 c7a9e000 c7a9fe0c c7a9fde8
fde0: bf06d4b4 bf06d0f0 00000000 c79fd280 00000000 0f700000 c7a9e000 00000241
fe00: c7a9fe3c c7a9fe10 c01c37b4 bf06d300 00000000 c7afbc00 00000000 00000000
fe20: c79cba84 c7463c78 c79fd280 c7473b00 c7a9fe6c c7a9fe40 c00a184c c01c35e4
fe40: 00000000 c7bb0005 c7a9fe64 c79fd280 c7463c78 00000000 c00a1640 c785e380
fe60: c7a9fe94 c7a9fe70 c009c438 c00a164c c79fd280 c7a9fed8 c7a9fed8 00000003
fe80: 00000242 00000000 c7a9feb4 c7a9fe98 c009c614 c009c2a4 00000000 c7a9fed8
fea0: c7a9fed8 00000000 c7a9ff64 c7a9feb8 c00aa6bc c009c5e8 00000242 000001b6
fec0: 000001b6 00000241 00000022 00000000 00000000 c7a9fee0 c785e380 c7473b00
fee0: d8666b0d 00000006 c7bb0005 00000300 00000000 00000000 00000001 40002000
ff00: c7a9ff70 c79b10a0 c79b10a0 00005402 00000003 c78d69c0 ffffff9c 00000242
ff20: 000001b6 c79fd280 c7a9ff64 c7a9ff38 c785e380 c7473b00 00000000 00000241
ff40: 000001b6 ffffff9c 00000003 c7bb0000 c7a9e000 00000000 c7a9ff94 c7a9ff68
ff60: c009c128 c00aa380 4d18b5f0 08000000 00000000 00071214 0007128c 00071214
ff80: 00000005 c0027ee4 c7a9ffa4 c7a9ff98 c009c274 c009c0d8 00000000 c7a9ffa8
ffa0: c0027d40 c009c25c 00071214 0007128c 0007128c 00000241 000001b6 00000000
ffc0: 00071214 0007128c 00071214 00000005 00073580 00000003 000713e0 400010d0
ffe0: 00000001 bef0c7b8 000269cc 4d214fec 60000010 0007128c 00000000 00000000
Backtrace:
[<c0098c58>] (__kmalloc+0x0/0xdc) from [<bf010a00>] (GadgetEpRequestAlloc+0x28/0x70 [bcm_udc_dwc])
r8:bf017c80 r7:c79de2d8 r6:c79de2d8 r5:00000000 r4:00000040
[<bf0109d8>] (GadgetEpRequestAlloc+0x0/0x70 [bcm_udc_dwc]) from [<bf0181d4>] (gs_alloc_req+0x44/0xf0 [g_serial])
r5:00000000 r4:00000040
[<bf018190>] (gs_alloc_req+0x0/0xf0 [g_serial]) from [<bf0182b4>] (gs_alloc_requests+0x34/0xb4 [g_serial])
r7:c79de2d8 r6:c79aa198 r5:00000000 r4:c79aa180
[<bf018280>] (gs_alloc_requests+0x0/0xb4 [g_serial]) from [<bf018368>] (gs_start_io+0x34/0xb8 [g_serial])
r9:c7b84000 r8:c7b48c00 r7:c79aa198 r6:c79de2d8 r5:c79aa180
r4:c79aa180
[<bf018334>] (gs_start_io+0x0/0xb8 [g_serial]) from [<bf018730>] (gs_open+0x1d0/0x23c [g_serial])
r9:c7b84000 r8:c7b48c00 r7:00000000 r6:00000000 r5:c79aa180
r4:c7924300
[<bf018560>] (gs_open+0x0/0x23c [g_serial]) from [<c01c3754>] (tty_open+0x1dc/0x314)
[<c01c3578>] (tty_open+0x0/0x314) from [<c00a184c>] (chrdev_open+0x20c/0x22c)
[<c00a1640>] (chrdev_open+0x0/0x22c) from [<c009c438>] (__dentry_open+0x1a0/0x2b8)
r8:c79aa300 r7:c00a1640 r6:00000000 r5:c74685a8 r4:c7a9f5a0
[<c009c298>] (__dentry_open+0x0/0x2b8) from [<c009c614>] (nameidata_to_filp+0x38/0x50)
[<c009c5dc>] (nameidata_to_filp+0x0/0x50) from [<c00aa6bc>] (do_filp_open+0x348/0x6f4)
r4:00000000
[<c00aa374>] (do_filp_open+0x0/0x6f4) from [<c009c128>] (do_sys_open+0x5c/0x170)
[<c009c0cc>] (do_sys_open+0x0/0x170) from [<c009c274>] (sys_open+0x24/0x28)
r8:c0027ee4 r7:00000005 r6:0007121c r5:0007129c r4:0007121c
[<c009c250>] (sys_open+0x0/0x28) from [<c0027d40>] (ret_fast_syscall+0x0/0x2c)
Code: e59c4080 e59c8090 e3540000 159c308c (17943103)
---[ end trace b9a765ee07f8c06b ]---
Hi all,
I'm currently debugging a device driver and I'm getting a kernel panic. After checking the backtrace or the error log, it appears to be that the problem is with kmalloc. I was thinking maybe I could change kmalloc with other allocation functions. What are their differences?
here's the error log:
Unable to handle kernel NULL pointer dereference at virtual address 0000000d
pgd = c7bdc000
[0000000d] *pgd=4785f031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1] PREEMPT
Modules linked in: bcm5892_secdom_fw(P) bcm5892_lcd snd_bcm5892 msr bcm5892_sci bcm589x_ohci_p12 bcm5892_skeypad hx_decoder(P) pinnacle hx_memalloc(P) bcm_udc_dwc scsi_mod g_serial sd_mod usb_storage
CPU: 0 Tainted: P (2.6.27.39-WR3.0.2ax_standard #1)
PC is at __kmalloc+0x70/0xdc
LR is at __kmalloc+0x48/0xdc
pc : [<c0098cc8>] lr : [<c0098ca0>] psr: 20000093
sp : c7a9fd50 ip : c03a4378 fp : c7a9fd7c
r10: bf0708b4 r9 : c7a9e000 r8 : 00000040
r7 : bf06d03c r6 : 00000020 r5 : a0000093 r4 : 0000000d
r3 : 00000000 r2 : 00000094 r1 : 00000020 r0 : c03a4378
Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
Control: 00c5387d Table: 47bdc008 DAC: 00000015
Process sh (pid: 1088, stack limit = 0xc7a9e260)
Stack: (0xc7a9fd50 to 0xc7aa0000)
fd40: c7a6a1d0 00000020 c7a9fd7c c7ba8fc0
fd60: 00000040 c7a6a1d0 00000020 c71598c0 c7a9fd9c c7a9fd80 bf06d03c c0098c64
fd80: c71598c0 00000003 c7a6a1d0 bf06c83c c7a9fdbc c7a9fda0 bf06d098 bf06d008
fda0: c7159880 00000000 c7a6a2d8 c7159898 c7a9fde4 c7a9fdc0 bf06d130 bf06d078
fdc0: c79ca000 c7159880 00000000 00000000 c7afbc00 c7a9e000 c7a9fe0c c7a9fde8
fde0: bf06d4b4 bf06d0f0 00000000 c79fd280 00000000 0f700000 c7a9e000 00000241
fe00: c7a9fe3c c7a9fe10 c01c37b4 bf06d300 00000000 c7afbc00 00000000 00000000
fe20: c79cba84 c7463c78 c79fd280 c7473b00 c7a9fe6c c7a9fe40 c00a184c c01c35e4
fe40: 00000000 c7bb0005 c7a9fe64 c79fd280 c7463c78 00000000 c00a1640 c785e380
fe60: c7a9fe94 c7a9fe70 c009c438 c00a164c c79fd280 c7a9fed8 c7a9fed8 00000003
fe80: 00000242 00000000 c7a9feb4 c7a9fe98 c009c614 c009c2a4 00000000 c7a9fed8
fea0: c7a9fed8 00000000 c7a9ff64 c7a9feb8 c00aa6bc c009c5e8 00000242 000001b6
fec0: 000001b6 00000241 00000022 00000000 00000000 c7a9fee0 c785e380 c7473b00
fee0: d8666b0d 00000006 c7bb0005 00000300 00000000 00000000 00000001 40002000
ff00: c7a9ff70 c79b10a0 c79b10a0 00005402 00000003 c78d69c0 ffffff9c 00000242
ff20: 000001b6 c79fd280 c7a9ff64 c7a9ff38 c785e380 c7473b00 00000000 00000241
ff40: 000001b6 ffffff9c 00000003 c7bb0000 c7a9e000 00000000 c7a9ff94 c7a9ff68
ff60: c009c128 c00aa380 4d18b5f0 08000000 00000000 00071214 0007128c 00071214
ff80: 00000005 c0027ee4 c7a9ffa4 c7a9ff98 c009c274 c009c0d8 00000000 c7a9ffa8
ffa0: c0027d40 c009c25c 00071214 0007128c 0007128c 00000241 000001b6 00000000
ffc0: 00071214 0007128c 00071214 00000005 00073580 00000003 000713e0 400010d0
ffe0: 00000001 bef0c7b8 000269cc 4d214fec 60000010 0007128c 00000000 00000000
Backtrace:
[<c0098c58>] (__kmalloc+0x0/0xdc) from [<bf010a00>] (GadgetEpRequestAlloc+0x28/0x70 [bcm_udc_dwc])
r8:bf017c80 r7:c79de2d8 r6:c79de2d8 r5:00000000 r4:00000040
[<bf0109d8>] (GadgetEpRequestAlloc+0x0/0x70 [bcm_udc_dwc]) from [<bf0181d4>] (gs_alloc_req+0x44/0xf0 [g_serial])
r5:00000000 r4:00000040
[<bf018190>] (gs_alloc_req+0x0/0xf0 [g_serial]) from [<bf0182b4>] (gs_alloc_requests+0x34/0xb4 [g_serial])
r7:c79de2d8 r6:c79aa198 r5:00000000 r4:c79aa180
[<bf018280>] (gs_alloc_requests+0x0/0xb4 [g_serial]) from [<bf018368>] (gs_start_io+0x34/0xb8 [g_serial])
r9:c7b84000 r8:c7b48c00 r7:c79aa198 r6:c79de2d8 r5:c79aa180
r4:c79aa180
[<bf018334>] (gs_start_io+0x0/0xb8 [g_serial]) from [<bf018730>] (gs_open+0x1d0/0x23c [g_serial])
r9:c7b84000 r8:c7b48c00 r7:00000000 r6:00000000 r5:c79aa180
r4:c7924300
[<bf018560>] (gs_open+0x0/0x23c [g_serial]) from [<c01c3754>] (tty_open+0x1dc/0x314)
[<c01c3578>] (tty_open+0x0/0x314) from [<c00a184c>] (chrdev_open+0x20c/0x22c)
[<c00a1640>] (chrdev_open+0x0/0x22c) from [<c009c438>] (__dentry_open+0x1a0/0x2b8)
r8:c79aa300 r7:c00a1640 r6:00000000 r5:c74685a8 r4:c7a9f5a0
[<c009c298>] (__dentry_open+0x0/0x2b8) from [<c009c614>] (nameidata_to_filp+0x38/0x50)
[<c009c5dc>] (nameidata_to_filp+0x0/0x50) from [<c00aa6bc>] (do_filp_open+0x348/0x6f4)
r4:00000000
[<c00aa374>] (do_filp_open+0x0/0x6f4) from [<c009c128>] (do_sys_open+0x5c/0x170)
[<c009c0cc>] (do_sys_open+0x0/0x170) from [<c009c274>] (sys_open+0x24/0x28)
r8:c0027ee4 r7:00000005 r6:0007121c r5:0007129c r4:0007121c
[<c009c250>] (sys_open+0x0/0x28) from [<c0027d40>] (ret_fast_syscall+0x0/0x2c)
Code: e59c4080 e59c8090 e3540000 159c308c (17943103)
---[ end trace b9a765ee07f8c06b ]---
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
kmalloc 被破坏的可能性很小,因为它在内核中的任何地方都被使用。但是,kmalloc 可能会失败。假设 kmalloc 没有被破坏,那么调用的代码是一个很好的候选者:
为了更直接地回答所提出的问题:
kcmalloc 为数组分配内存,它不是 kmalloc 的替代品:
void *kcalloc(size_t n, size_t size, gfp_t flags)
vmalloc 与 kmalloc 相同,只不过它分配的内存只是虚拟连续的。底层物理内存可以是不连续的。
所以 kmalloc 最终可以被调用 kzalloc 代替,但它不太可能解决你的问题。
It is very unlikely that kmalloc is broken, since it is used everywhere in the kernel. However, kmalloc can fail. Assuming that kmalloc is not broken then the code calling is a good candidate :
To answer more directly to the question asked :
kcmalloc allocates memory for an array, it is not a replacement for kmalloc :
void *kcalloc(size_t n, size_t size, gfp_t flags)
vmalloc is the same as kmalloc, except that it allocates memory that is only virtually contiguous. The underlying physical memory can be discontiguous.
So kmalloc can eventually be replaced by a call to kzalloc, but it is unlikely to solve your problem .
我认为kmalloc、vmalloc和其他分配技术之间的选择在于实现。他们每个人的失败也是偶然的。
如果您需要多个内存页面,请选择页面分配技术。它们既简单又快速。
但是,如果您需要一定量的数据(以字节表示),那么仍然可以在 kmalloc(及其变体)和 vmalloc 之间进行选择。
kmalloc 速度更快并且提供连续的内存分配(在 DMA 的情况下特别有用)。实现它的算法非常快。但是,如果您的内存高度碎片化,那么当您请求大内存时可能会出现问题。如果找不到足够的连续空间,则尽管内存有足够的空间可容纳,但仍会失败。
另一方面,vmalloc 不需要连续的内存分配。然而,它的速度相当慢。它通过适当设置页表条目来工作。此外,内核通常不会为 vmalloc 分配大量空间。
因此,就您而言,我认为这取决于您使用的应用程序类型。但是,大多数情况下,使用 vmalloc 代替 kmalloc 并不是解决方案(除了高度碎片化的内存中的大内存分配)。在这种情况下,您可以直接选择页面分配。
I think the choice between the kmalloc, vmalloc and other allocation techniques lies in the implementation. The failure of each of them is also contingent.
If you need multiple of pages of memory rather go with the pages allocation techniques. They are simple and fast as well.
However, if you need certain amount of data (expressed in terms of bytes) then the choice remains between kmalloc( and its variants) and vmalloc.
kmalloc is faster and provides the contiguous memory allocation( especially useful in the case of DMA). The algorithm implementing it is very fast. However, if your memory is highly fragmented then the problem may arise when you request for a large memory. If it can't find enough contiguous space, if fails despite the memory having enough space to accommodate.
vmalloc on the other hand doesn't need the contiguous memory allocation. However, it is quite slow. It works by suitably setting up the page table entries. Furthermore, kernel usually doesn't allocate lots of space for the vmalloc.
So, in your case I think it is contingent on what type of applications you are using. However, using vmalloc instead of kmalloc isn't the solution most of the time( except for the large memory allocations in highly fragmented memory). In such cases you can directly opt for pages allocation.
仅当内存碎片并且找不到连续内存时,kmalloc 才可能成为罪魁祸首。因此,取决于您尝试分配的内存块有多大。
在这种情况下,使用 vmalloc 会产生良好的结果。在最佳实践中,
如果您想更好地使用 kmalloc,请使用 kzmalloc。
如果你的分配量很大,最好使用vmalloc。
现在根据错误情况检查什么最适合您。
kmalloc could be culprit only when your memory is fragmented and fails allocating memory if it does not find contiguous memory. So depending on how big of chunk of memory you are trying to allocate.
In such cases, using vmalloc yields good results. In best practices,
if you want use kmalloc better use kzmalloc.
If your allocation is big better use vmalloc.
Now check what is best for you based on the error condition.