Recursive page directory and address space copy
Recursive page directory and address space copy
Hi there,
i have a (maybe) stupid question. I use recursive page directory to access to the CURRENT process page tables via the 0xFFC00000 etc etc etc.
The question is thi works well if the kernel have to interact with just the current process page tables what about other processes?!
For example in the fork routine i copy the CURRENT process page directory and tables entryes to another page table.
I can access to the current page tables with the recursive trick but how i copy the entries in the new process page table? i have to map the new process page tables to a temporary location just to copy the content of the current?!
Tnx Dave
i have a (maybe) stupid question. I use recursive page directory to access to the CURRENT process page tables via the 0xFFC00000 etc etc etc.
The question is thi works well if the kernel have to interact with just the current process page tables what about other processes?!
For example in the fork routine i copy the CURRENT process page directory and tables entryes to another page table.
I can access to the current page tables with the recursive trick but how i copy the entries in the new process page table? i have to map the new process page tables to a temporary location just to copy the content of the current?!
Tnx Dave
Re: Recursive page directory and address space copy
basically, if you want to modify non-current page directory, of course you must map it into the current process space, so yes, that is one way to do it
however, it is also possible that you don't need to copy at all, since if you are simply duplicating the address space, you can just reuse the same page tables, and mark them for COW (which could be done in the context of the new process -- meaning your old process doesn't need to modify the page tables for the new process at all)
*disclaimer: i don't use anything like fork in my OS, and know very little about how it works or what exactly its supposed to do
however, it is also possible that you don't need to copy at all, since if you are simply duplicating the address space, you can just reuse the same page tables, and mark them for COW (which could be done in the context of the new process -- meaning your old process doesn't need to modify the page tables for the new process at all)
*disclaimer: i don't use anything like fork in my OS, and know very little about how it works or what exactly its supposed to do
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Recursive page directory and address space copy
You can use the recursive trick multiple times. If your current process' page directory is mapped as the last page table, you'll get the page tables laid out from 0xFFC00000 to the end of memory; if another process' page directory is then mapped as the second-to-last page table in the current process, you'll get its page tables laid out from 0xFF800000 to 0xFFC00000. In short, any page directory placed as a page table in the current process' page directory will create a mapping of that page directory's page tables into the corresponding 4 MB region in virtual address space.
Also, for best results, every page directory should have itself as its last entry, so that even when it is mapped in by another page directory, it still will place itself at the end of that 4 MB region.
Also, for best results, every page directory should have itself as its last entry, so that even when it is mapped in by another page directory, it still will place itself at the end of that 4 MB region.
Re: Recursive page directory and address space copy
mmm...not so easy to take a decision...i i use recursive mapping to map the noncurrent process page directory in the current address space is a mess...because i have to map the noncurrent process directory somewere anyway to write on it, and the same is for the pagetables. I start to don't linke too much this recursive trick it waste a lot of virtual memory addresses.
Is not more simple to reserve 3 pages addresses to map the noncurrent process directory, pagetable; make the copy of the page i have to copy and unmap it on the fly?! If it's possible wich metod use linux and other tested and stable systems?!
Tnx
Is not more simple to reserve 3 pages addresses to map the noncurrent process directory, pagetable; make the copy of the page i have to copy and unmap it on the fly?! If it's possible wich metod use linux and other tested and stable systems?!
Tnx
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Recursive page directory and address space copy
8 MB of virtual address space is not much to pay out of 4 GB total, especially because it greatly simplifies this cloning task. If you just reserve three pages for copying purposes, you have to modify the page tables every time want to copy a frame in order to change the mappings of those three pages, which means a TLB flush for every frame copied. I don't know what Linux or other systems do (especially because PAE is usually used, and makes the recursive trick different,) but for this task, it's hard to get more efficient than the recursive page table trick AFAIK.
Re: Recursive page directory and address space copy
Here is the incriminated part that i can't understand:
my problem is that I HAVE to map somewhere anyway the noncurrent process directory because i can't access to it since it's last entry (in the new allocated frame) is empty...
what i need to do to access to it to set the last entry to itself otherwise i cant access to the directory anyway...
something like:
what is the alternative?! i don't see an alternative to map somewhere the directory to fill it's last entry, and at this point the mapping in src_dir[1022] become useless...
Tell me if im wrong.
Thanks
Dave
Code: Select all
dst_dir = (uint *) (0xFFBFF000); // the non current process page dir virtual address
dst_dir_phys = get_frame(dst_dir); // get a free physical frame, and the address for the noncurrent proc directory
set_frame(dst_dir_phys); // set the frame as in use
src_dir[1022] = dst_dir_phys | 0x5; // map it in the current process dir as 0xFF800000
flush_tlb();
memset(dst_dir, 0 ,sizeof(uint)*1024); // Page fault
what i need to do to access to it to set the last entry to itself otherwise i cant access to the directory anyway...
something like:
Code: Select all
dst_dir_phys = memmap(A_POINTER); // map the virtual address and returns the phys frame of where is mapped
A_POINTER[1023] = dst_dir_phys | 0x5;
src_dir[1022] = dst_dir_phys | 0x5; // but now it's useless to do this, since i can access to the dst dir simply by A_POINTER what
Tell me if im wrong.
Thanks
Dave
Re: Recursive page directory and address space copy
You are attempting to save a few cycles on an implementation of fork(), which is an inherently slow process. There is no way to directly clone a process' paging structures without mapping in an equivalent number of free pages to copy the page table/directory/PDPT/PML4 (delete as appropriate depending on architecture) data to, with the attached tlb misses and time taken by the actual copying process.
Think of the situations in which fork() is used - in the main there are only two. First, to execute a new process a shell will typically do something along the lines of fork(); execve();. This causes the shell's environment to be cloned, and then immediately replaced with that of the new process. If you spend time cloning all the paging structures for the shell, just to have them overwritten, you are wasting a lot of resources. The most commonly used solution here is copy-on-write, where a copy of the data is only performed if that particular page of memory (which can just as easily be a paging structure) is altered. The other situation in which fork() is used is in network servers which classically create a copy of themselves to deal with an incoming request. This can again be optimized with copy-on-write but IMHO this practice should be discouraged anyway and be replaced with a threaded alternative.
Regards,
John.
Think of the situations in which fork() is used - in the main there are only two. First, to execute a new process a shell will typically do something along the lines of fork(); execve();. This causes the shell's environment to be cloned, and then immediately replaced with that of the new process. If you spend time cloning all the paging structures for the shell, just to have them overwritten, you are wasting a lot of resources. The most commonly used solution here is copy-on-write, where a copy of the data is only performed if that particular page of memory (which can just as easily be a paging structure) is altered. The other situation in which fork() is used is in network servers which classically create a copy of themselves to deal with an incoming request. This can again be optimized with copy-on-write but IMHO this practice should be discouraged anyway and be replaced with a threaded alternative.
Regards,
John.
Re: Recursive page directory and address space copy
You've just discovered the tip of the iceberg. You kernel will probably need efficient ways to copy data between processes and between the kernel and a process that may not be currently active.
How this is done rather depends on the processor architecture, your memory manager and how much physical memory there is and the number of bytes that need to be copied. A number of methods are available and you probably need most of them...
1. Temporarily switch to the other context to access the data. Perhaps copy to temporary buffer.
2. Map part (or all) of the other context into the current context so both are accessible together.
3. Have most (or all) of physical memory permanently mapped into the kernel space so the kernel can access an alias of all memory. This is the old linux way.
1. is a pain and the double copy can make it slow unless the data is small. I use this for small data, usually less than 100 bytes or so. Avoid the context switch by copying to the kernel when the data is available.
2. can be surprisingly fast. Especially if you don't need to do a full context switch. Perhaps a couple of 4MB pages is enough.
3. was good on x86 when installed memory was less than 1GB. It's useful again in a 64 bit kernel.
BTW, when you fork() you shouldn't be copying page tables anyway. It's the user address space that is forked, not the page tables. You should be copying the contents of the process address space.
How this is done rather depends on the processor architecture, your memory manager and how much physical memory there is and the number of bytes that need to be copied. A number of methods are available and you probably need most of them...
1. Temporarily switch to the other context to access the data. Perhaps copy to temporary buffer.
2. Map part (or all) of the other context into the current context so both are accessible together.
3. Have most (or all) of physical memory permanently mapped into the kernel space so the kernel can access an alias of all memory. This is the old linux way.
1. is a pain and the double copy can make it slow unless the data is small. I use this for small data, usually less than 100 bytes or so. Avoid the context switch by copying to the kernel when the data is available.
2. can be surprisingly fast. Especially if you don't need to do a full context switch. Perhaps a couple of 4MB pages is enough.
3. was good on x86 when installed memory was less than 1GB. It's useful again in a 64 bit kernel.
BTW, when you fork() you shouldn't be copying page tables anyway. It's the user address space that is forked, not the page tables. You should be copying the contents of the process address space.
If a trainstation is where trains stop, what is a workstation ?
Re: Recursive page directory and address space copy
Ok i understood. It looks that the best way is to assign to the new process the same cr3 value of the current process, and do the copy on write for the usetmode space (in my case the addresses < 0xC0000000).
It's implemented marking the pages as read only and when a page fault happens because one of the forked processes tries to write the page is copied and marked as rw right?!
Anyway i need a counter for the references to that page, so the read only flag is cleared when the counter reaches 1 reference.
Thanks for the suggestions. Dave
It's implemented marking the pages as read only and when a page fault happens because one of the forked processes tries to write the page is copied and marked as rw right?!
Anyway i need a counter for the references to that page, so the read only flag is cleared when the counter reaches 1 reference.
Thanks for the suggestions. Dave
Re: Recursive page directory and address space copy
mmm...NO!!! ahahahhaha
maybe the best way is to create a new page directory and pagetables for the new process and LINK to the same frames of the running process; marking as read only just the entries of the new process pagetables. This is better
Cheers
maybe the best way is to create a new page directory and pagetables for the new process and LINK to the same frames of the running process; marking as read only just the entries of the new process pagetables. This is better
Cheers