Thread (17 messages) flat view 17 messages, 7 authors, 2012-09-03

How to understand the macro __init?

From: Amarnath Revanna <hidden>
Date: 2012-08-16 18:39:28

Just want to add a little more for better understanding:

When I spoke about .init section of the final kernel image, please note
that this section is going to
contain all the __init data (and functions) coming from _All_ the drivers
and modules that were included
as part of the kernel image. Hence, after initialization when we look at
the print:

" [1.011596] Freeing unused kernel memory: 664k freed "

we see 664k bytes being freed.

This is a significant amount of contiguous physical memory that we can see
being released by the kernel.

The same cannot be held true for a single loadable module which may be
releasing just a few, virtually
contiguous memory.

Regards,
-Amar


On Thu, Aug 16, 2012 at 11:57 PM, Amarnath Revanna <
amarnath.revanna@gmail.com> wrote:
Hi Ezequiel,

On Thu, Aug 16, 2012 at 10:53 PM, Ezequiel Garcia [off-list ref]wrote:
quoted
Hi Amar,

On Thu, Aug 16, 2012 at 1:08 PM, Amarnath Revanna
[off-list ref] wrote:
quoted
On the other hand, any other kernel module that you load using insmod or
modprobe comes after this stage, wherein the kernel was already booted,
and
quoted
hence, no memory area of __init will ever be freed.
Modules are loaded with vmalloc, right?

Could you explain why the kernel can't free those __init symbols
from memory also in this case?

Thanks,
Ezequiel.
When we look at the definition of __init & __initdata in
http://lxr.free-electrons.com/source/include/linux/init.h#L44,

 44 <http://lxr.free-electrons.com/source/include/linux/init.h#L44> #define __init <http://lxr.free-electrons.com/ident?i=__init>          __section <http://lxr.free-electrons.com/ident?i=__section>(.init <http://lxr.free-electrons.com/ident?i=init>.text <http://lxr.free-electrons.com/ident?i=text>) __cold <http://lxr.free-electrons.com/ident?i=__cold> notrace <http://lxr.free-electrons.com/ident?i=notrace>
 45 <http://lxr.free-electrons.com/source/include/linux/init.h#L45> #define __initdata <http://lxr.free-electrons.com/ident?i=__initdata>      __section <http://lxr.free-electrons.com/ident?i=__section>(.init <http://lxr.free-electrons.com/ident?i=init>.data <http://lxr.free-electrons.com/ident?i=data>)
 46 <http://lxr.free-electrons.com/source/include/linux/init.h#L46> #define __initconst <http://lxr.free-electrons.com/ident?i=__initconst>     __section <http://lxr.free-electrons.com/ident?i=__section>(.init <http://lxr.free-electrons.com/ident?i=init>.rodata <http://lxr.free-electrons.com/ident?i=rodata>)
 47 <http://lxr.free-electrons.com/source/include/linux/init.h#L47> #define __exitdata <http://lxr.free-electrons.com/ident?i=__exitdata>      __section <http://lxr.free-electrons.com/ident?i=__section>(.exit <http://lxr.free-electrons.com/ident?i=exit>.data <http://lxr.free-electrons.com/ident?i=data>)
 48 <http://lxr.free-electrons.com/source/include/linux/init.h#L48> #define __exit_call <http://lxr.free-electrons.com/ident?i=__exit_call>     __used <http://lxr.free-electrons.com/ident?i=__used> __section <http://lxr.free-electrons.com/ident?i=__section>(.exitcall.exit <http://lxr.free-electrons.com/ident?i=exit>)

we can notice that the functions represented by __init and any data
represented by __initdata are going to be placed
in a separate section of the final kernel binary image
(zImage/uImage/vmlinux)  by the linker.

This section is going to be called the .init section.

The idea behind forming this separate .init section in the final kernel
image is to hold all those functions and data structures
that are going to be required only once during initialization, together.

By doing so, the kernel, once it boots up, would have already utilized all
these resources once during bootup sequence and
hence, can now be released from the memory. As a result, the kernel would
simply discard this entire ".init" section from the
RAM in one go, there by freeing the memory. The amount of memory being
freed by removing this section is thus printed in
the line:

" [1.011596] Freeing unused kernel memory: 664k freed "

Now, when we think about loadable modules, as you rightly said, are loaded
into the kernel memory by obtaining the memory
area from the heap using vmalloc. The interesting thing about this is
that, since we are going to load only one module
within this vmalloc'd area, we can normally expect the size of __initdata
and __init function to be pretty small, in few bytes.
Now, it becomes too difficult for the kernel to manage (keep track of and
free) these smaller memory areas coming up from
every individual loaded module.

Another thing to add is that, in case of freeing up an entire .init
section from the RAM, we are recovering the entire .init
section size'd _contiguous_ physical memory area back to the kernel.
However, in case of Loaded Kernel Module (LKM) if we
try to free up the __init memory of an LKM that was allocated using
vmalloc, we may only be freeing up few bytes of memory
that was virtually contiguous. This may not be of much significance for
the kernel operation as compared to its overhead
involved with managing a process to keep track of and freeing up all
these __init memory in vmalloc area.

In short, its kind of a nice trade off done to leave this __init data
cleanup for LKM while keeping its significance for all built in
drivers/modules.

Regards,
-Amar
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20120817/f741723e/attachment.html 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help