Linux Kernel-Fork () function creation process (continued) copy_mem (int nr, struct task_struct * P)

Source: Internet
Author: User

This analysis based on Linux 0.11 kernel, reprinted please indicate the source http://blog.csdn.net/yming0221/archive/2011/06/06/6528490.aspx

The copy_mem (int nr, struct task_struct * P) function is used to set the base address of the segment for the process and copy the page table. Below is the code

// Set the code and Data Segment Base Address and limit for the new task, and copy the page table. <Br/> // nr is the new task number, and P is the pointer to the data structure of the new task. <Br/> int copy_mem (int nr, struct task_struct * P) <br/>{< br/> unsigned long old_data_base, new_data_base, data_limit; <br/> unsigned long old_code_base, new_code_base, code_limit; <br/> code_limit = get_limit (0x0f); // The length of the middle segment of the descriptor in the partial Descriptor Table. <Br/> data_limit = get_limit (0x17); // The length of the middle section of the data segment descriptor in the Local Descriptor Table. <Br/> old_code_base = get_base (current-> LDT [1]); // obtain the base address of the original code segment. <Br/> old_data_base = get_base (current-> LDT [2]); // obtain the base address of the original data segment. <Br/> If (old_data_base! = Old_code_base) // version 0.11 does not support code and Data Segment separation. <Br/> panic ("we don't support separate I & D"); <br/> If (data_limit <code_limit) // if the data segment length <code segment length is incorrect. <Br/> panic ("Bad data_limit"); <br/> new_data_base = new_code_base = nR x 0x4000000; // new base address = task id * 64 MB (Task size ). <Br/> P-> start_code = new_code_base; <br/> set_base (p-> LDT [1], new_code_base); // set the base domain in the code segment descriptor. <Br/> set_base (p-> LDT [2], new_data_base); // set the base domain in the data segment descriptor. <Br/> If (copy_page_tables (old_data_base, new_data_base, data_limit) <br/> {// copy the code and data segment. <Br/> free_page_tables (new_data_base, data_limit); // release the applied memory if an error occurs. <Br/> return-enomem; <br/>}< br/> return 0; <br/>}< br/> 

Specifically, the get_limit () function uses embedded assembly to get the length limit of the middle part of a specific segment descriptor, where the instruction lsll is used.

// The length of the segment selected by segment. <Br/> // % 0-length of stored segments (number of bytes); % 1-segment selector segment. <Br/> # define get_limit (segment) ({/<br/> unsigned long _ limit;/<br/>__ ASM _ ("lsll % 1, % 0/n/tincl % 0 ":" = r "(_ limit):" R "(segment);/<br/>__ limit ;}) 

Return the segment length limit of the specified descriptor segment. Because the segment length is from 0, you need to add one after lsll.

Why is the LDT data segment descriptor 0x17, while the segment descriptor 0x0 in LDT is the reason that the segment selects the sub-format, a total of 16 bits, 13 BITs indicate the index of the descriptor in the Descriptor Table

[2] bits indicate whether this parameter is gdt or LDT, 0 indicates LDT, and [1] [0] indicates the RPL permission bits. Therefore, 0x17 = 0b0000 0000 0001 0111, 10 indicates the second

Item, 0x0f = 0b0000 0000 0000 1111, indicates the first item in the descriptor table. The base address is in the ldtr register.

Get_base (ADDR) obtains the segment and address pointed to in the descriptor. Its macro definition is as follows:

// Obtain the base address of the segment descriptor referred to by LDT in the Local Descriptor Table. <Br/> # define get_base (LDT) _ get_base (char *) & (LDT) <br/> // obtain the base address of the segment from the descriptor of the address ADDR. The function is the opposite of _ set_base. <Br/> // edX-storage base address (_ base); % 1-address ADDR offset 2; % 2-address ADDR offset 4; % 3-ADDR offset 7. <Br/> # DEFINE _ get_base (ADDR) ({/<br/> unsigned long _ base;/<br/>__ ASM _ ("movb % 3, % DH/n/t "// obtain the high 8-bit (31-24) of the 16-bit base address in [ADDR + 7 )?? DH. <Br/> "movb % 2, % DL/n/t "// take the 8-bit low (23-16) of the 16-bit high base address in [ADDR + 4 )?? DL. <Br/> "shll $16, % edX/n/t" // The base address height is 16 to the Top 16 position in EDX. <Br/> "movw % 1, % dx" // get the base address of [ADDR + 2] at a low 16 bits (15-0 bits )?? DX. <Br/>: "= D" (_ base) // The edX contains a 32-bit segment base address. <Br/>: "M" (* (ADDR) + 2), "M" (* (ADDR) + 4 )), "M" (* (ADDR) + 7); <br/>__ base; <br/>}< br/>) 

Descriptor format:

The copy_page_tables () function is used to copy a page table. It is said to be one of the most complex functions in memory management. It will be studied later ........

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.