In other words when a process gets a new memory page, this one must be
cleaned.
I've solved this issue for Solaris using DTrace.
I found out that in Solaris memory pages are cleaned by pagezero
routine.
So using entry and return probes of fbt provider in DTrace and getting
input and output of the functions which are used in pagezero
implementation I achieved my goal.
And now I have to solve the same task in AIX.
As I understand the source code of AIX is closed and that way which
was used in Solaris isn't fit.
First of all could you tell me how can I translate the virtual address
which was gotten from malloc to the physical address?
I thought it's possible to do using kdb and its tr command.
But when I type the next command in kdb:
(0)> tr 0x20001878
i get the next result:
WARNING: 0000000020001878 invalid sid
where 0x20001878 is the address which was gotten from malloc, and sid
- segment identifier.
May be it's because the main purpose of kdb is debugging of kernel
extension and my actions are wrong?
And one more question: how can i get all physical memory dump in aix?
My system: AIX 6.1 powerpc
HTH
Mark Taylor
Thanks a lot for your feedback, Mark.
But I think the tools which you offered aren't fit for me.
As I understand a new memory page is zero-filled when it's given for a
new process. There is some executable code (may be routine) in AIX
kernel which is invoked every time when a process gets a new memory
page. And I think this routine isn't a part of public AIX kernel
interface.
I have to find some block of physical memory (memory page) and check
that it's dirty (print some piece of it). Then when that block is
given to a process, it must be cleaned by OS (in AIX at least). And
I'll be able to print the same but zero-filled block. That's my
understanding of the issue.
dbx is a user-level debugger and I don't know how it can be useful for
me.
probevue if more relative. But it's weaker then DTrace. Its syscall
probe manager allows to set breakpoints only on well documented system
calls (libc). It's probably because AIX kernel are closed.
As I understand that even if I find the name of routine which zero-
filles memory, I won't be able to do something with my great knowledge
because I don't know how to set a breakpoint on it (kdb won't help me
as I understand).
Ok. I can write the program calling malloc and filling alloced memory
by some test data ("Hello world!" for example ;).
Then I can translate the virtual address returned by malloc to the
corresponding physical address. Using kdb I can got evidence that this
physical memory is dirty.
Then I can write the program calling malloc routine many times. And
every time i will translate the address returned by malloc to the
physical address. If this physical address are equal or near with the
physical address returned by the first program (where malloc was
called once), then the program have got the same memory page as the
first program.
And againg using kdb i can print this page. And if that page was
cleaned I should be happy. ;)
But i don't know how to translate a virtual address to a physical
address. :(((
I'll be happy if you correct me.
If the operating system had to do constantly zero memory, it would be
way slow.
You either have to zero new memory yourself via calloc() or use memset()
prior to the call to free() if you want the to clear the memory that you
used.
> And one more question: how can i get all physical memory dump in aix?
>
> My system: AIX 6.1 powerpc
>
Apart from a full physical dump (sysdumpstart -p) that would bring down
the server hard and dump the memory state to a logical device, you'd
probably be stuck using tools like kdb or dbx.
Regards,
Niel
Thanks a lot, Niel. I considered usage of "sysdumpstart -p".
"When the dump completes, the system halts." - from man sysdumpstart.
So this way doesn't fit for me.
I want to view some dirty physical memory page (it must be dirty if it
was used by another process before) and to view the same physical
memory page after it had been gotten to another process (in first
time).
This mechanism briefly described in http://www.ibm.com/developerworks/aix/library/au-vmm/index.html:
@@AIX maps pages into real memory based on demand. When an application
references a page that is not mapped into real memory, the system
generates a page fault. To resolve the page fault, the AIX kernel
loads the referenced page to a location in real memory. If the
referenced page is a new page (that is, a page in a data heap of the
process that has never been previously referenced), "loading" the
referenced page simply means filling a real memory location with zeros
(that is, providing a zero-filled page). If the referenced page is a
pre-existing page (that is, a page in a file or a previously paged out
page), loading the referenced page involves reading the page from the
disk (paging space or disk file system) into a location in real
memory.@@
Incorrect. AIX hands new zero-filled pages to processes when they
are needed.
Possible answer: not going to happen. You can worry about physical
pages all you like, but you are overlooking the fact that the
hypervisor has some control here as well, underneath whatever the
operating system is doing.
Other answer: You will likely need to learn about the kernel debugger
(accessed via the console) and poke around memory manually.
Or simply trust the design and documentation of the OS and accept
that new pages handed to processes are always zero-filled. A process
can not get a page that was dirtied by another process. Nor can you
look at another process' address space unless you have privilege, which
is what you have when you use the kernel debugger.
On 2009/11/16 5:40 PM, Gary R. Hook wrote:
> Niel Lambrechts wrote:
>> If the operating system had to do constantly zero memory, it would be
>> way slow.
> Incorrect. AIX hands new zero-filled pages to processes when they are
> needed.
Well, does "needed" not imply "if caller used calloc()", or is there
some other condition that would also provide such a mechanism?
If it did not constitute any type of performance overhead, why implement
both malloc() and calloc()? Would a large amount of calloc() calls not
be slower than just plain malloc()?
Niel
Niel
We're talking about two different things here. You asked about what
the OS does on behalf of a process, with respect to new pages. Asking
about the behavior of calloc and malloc is relative to what a library
does within a process, and is all about the implementation of a
function. In other words, if I call calloc I'm going to possibly
get back a pointer to memory (in my heap) that I've previously used,
and was therefore dirty. calloc is a convenience function that takes
the time to fill that memory region with zeroes. This has nothing to
do with pages, nor what the OS does when (e.g.) you call sbrk().
Yes, calloc has overhead. It must take longer than malloc to return
the same amount of memory.
D'oh. Sorry, should have read ahead before posting a reply.
What do you mean? Are you talking about my question about usage of kdb
from my first message of this topic?
Ok. Could I ask you one more question?
Here test program:
int
main()
{
char *va; /* virtual address */
int *pa; /* physical address */
char va_str[20]; /* string representation of va */
FILE * fp;
int sh_ret;
/* First of all I get a virtual address */
va = malloc(100);
if (va == NULL) {
printf("malloc failed\n");
}
printf("%x\n", va);
/* Then I convert it to C-string */
itoa((int)va, va_str);
printf("%s\n", va_str);
/* Form script which will be passed to kdb */
fp = fopen("va2pa.sh", "w");
if (fp == NULL)
printf("fopen(va2pa) failed\n");
fputs("#!/bin/bash\n", fp);
fputs("\n", fp);
fputs("kdb << EOL > pa.txt\n", fp);
fprintf(fp, "tr %s\n", va_str);
fputs("EOL\n", fp);
fclose(fp);
/* Then that script will be executed */
sh_ret = system("./va2pa.sh");
printf("%d\n", sh_ret);
return 0;
}
pa.txt will contain for example the next:
<kdb bla-bla>
(0)> tr 20001dd8
WARNING: 0000000020001DD8 invalid sid
Why it doesn't work??? Privileges?
I can execute tr after the process had been executed and the result
will be the same.
You're mixing apples and oranges.
The address you get in your program from malloc() is a virtual address,
and is useful only within the context of that process. In the kernel
debugger, not so much. The tr command takes an effective address
to translate to a real address, but that's not the same as a virtual
address.
You will need to, in the context of your process, convert that virtual
addr to an effective addr, and in the process you'll get the right
segment ID which can then be used by tr.
If you're not familiar with the addressing layers involved here I
suggest further research and reading on operating systems in general,
including virtual memory. The AIX pubs also contain lots of information
about this subject.