Page 1 of 1

fork() with higher half kernel

Posted: Thu Jul 23, 2015 5:34 am
by tkausl
Hello,

i'm having a big problem at the moment, i don't know *anything* i could do about it.

I am using a higher half kernel, mapped at 3GB. Now i am implementing multithreading. Everything works really good at the moment, i can run two processes in kernel-space and i can even load my initrd elf file and start this one. But now i want to implement exec() and fork(). The thing is, for fork, i need to create a new page-directory and 'deep'-copy everything over. This means, new page-tables and everything that is mapped in process1's address-space needs to be copied. But, i don't see any possibility how i could copy the data in ram since there is 'no' way i can map in both directory's at the same time (Remember, after i've copied the page-directory and all tables, 0x10 in the first addressspace maps to another physical address then 0x10 in the second addressspace). I've seen in some tutorial that he disabled paging to copy everything over, but i just can't disable paging since my IP is at some high address >3GB. The only way i could think of is identity-map the kernel again, jump back to a ~1MB address, disable paging, copy everything over, enable paging again, jump back to higher half. But not even that is (easy) doable since the processes address-spaces are *not* necessarily a continuous block of *physical* memory.

Every bit of information could be helpful, i hope someone can give me a pointer :wink:

Re: fork() with higher half kernel

Posted: Thu Jul 23, 2015 6:00 am
by Combuster
You can always map pages temporarily to write them.

Re: fork() with higher half kernel

Posted: Thu Jul 23, 2015 6:02 am
by tkausl
Combuster wrote:You can always map pages temporarily to write them.
Yeah i thought the same, but this has to be a badass-logic to find free pages and don't overwrite the actual used pages...

Re: fork() with higher half kernel

Posted: Thu Jul 23, 2015 7:41 am
by iansjack
You're not keeping track of which pages are in use and which aren't?

Re: fork() with higher half kernel

Posted: Thu Jul 23, 2015 10:33 pm
by linguofreak
tkausl wrote:Hello,

i'm having a big problem at the moment, i don't know *anything* i could do about it.

I am using a higher half kernel, mapped at 3GB. Now i am implementing multithreading. Everything works really good at the moment, i can run two processes in kernel-space and i can even load my initrd elf file and start this one. But now i want to implement exec() and fork(). The thing is, for fork, i need to create a new page-directory and 'deep'-copy everything over. This means, new page-tables and everything that is mapped in process1's address-space needs to be copied. But, i don't see any possibility how i could copy the data in ram since there is 'no' way i can map in both directory's at the same time (Remember, after i've copied the page-directory and all tables, 0x10 in the first addressspace maps to another physical address then 0x10 in the second addressspace). I've seen in some tutorial that he disabled paging to copy everything over, but i just can't disable paging since my IP is at some high address >3GB. The only way i could think of is identity-map the kernel again, jump back to a ~1MB address, disable paging, copy everything over, enable paging again, jump back to higher half. But not even that is (easy) doable since the processes address-spaces are *not* necessarily a continuous block of *physical* memory.
Modern *nixes tend to implement fork() with a copy-on-write mechanism. The page table entries for the original process are marked as read-only and copy-on-write, then duplicated for the new process, so that not only are the content's of both processes' address spaces identical, but they're actually using the same physical memory. When one of the processes writes to a (virtual) page, it causes a page fault because the page is marked read only. The kernel then sees that the page is also marked copy-on-write, finds a free physical page, assigns that page to the virtual page slot in question for the process attempting to write, copies the data into it, leaves the original physical page assigned to the other process, and removes the copy-on-write and read only markings for the virtual page in both proceses. So no userspace data is actually copied at all during the original fork() call: data is only copied in small chunks, and only when one of the processes need to modify it. Data that both processes are reading from without writing to can be, and is, left uncopied.
Every bit of information could be helpful, i hope someone can give me a pointer :wink:
0x00FCDC9A :P