Linux Kernel-Fork () function creation process

Source: Internet
Author: User

The Analysis Based on Linux 0.11 kernel, reprinted please indicate the source http://blog.csdn.net/yming0221/archive/2011/06/05/6527337.aspx

 

 

In Linux, after move_to_user_mode (), process 0 generates a sub-process through fork (), which is actually process 1 (INIT process ).

Fork () is provided in the form of Embedded Assembly.

# DEFINE _ syscall0 (type, name)/<br/> type name (void)/<br/>{/ <br/> long _ res; /<br/>__ ASM _ volatile ("int $0x80" // call the system interrupt 0x80. <Br/>: "= A" (_ res) // return value ?? Eax (_ res ). <Br/>: "" (_ nR _ # Name); // The input is the system interruption call number _ nr_name. <Br/> If (_ res> = 0) // If the returned value is greater than or equal to 0, this value is directly returned. <Br/> return (type) _ res; errno =-_ res; // otherwise, the error code is set and-1 is returned. <Br/> return-1 ;}< br/> 

In this way, the int 0x80 interrupt is used, and the sys_fork system call is called to create a process. The detailed process is as follows:

In sched. C, the sched_init () function finally sets the system call interrupt gate.

Set_system_gate (0x80, & system_call );

Set the interrupt Number of the system call.

Call sys_fork () through int 0x80 ()

It is implemented using assembly

The system adds the stack content to the stack and then executes call _ sys_call_table (, % eax, 4)

Call address = _ sys_call_table + % eax * 4

Then call sys_fork ()

_ Sys_fork: <br/> call _ find_empty_process # Call find_empty_process () (kernel/fork. C, 135 ). <Br/> testl % eax, % eax <br/> JS 1f <br/> push % GS <br/> pushl % ESI <br/> pushl % EDI <br/> pushl % EBP <br/> pushl % eax <br/> call _ copy_process # Call C function copy_process () (kernel/fork. c, 68 ). <Br/> addl $20, % ESP # discard all the pressure stack content. <Br/> 1: Ret 

 

Then call find_empty_process ()

Int find_empty_process (void) <br/>{< br/> int I; <br/> repeat: <br/> If (++ last_pid) <0) <br/> last_pid = 1; <br/> for (I = 0; I <nr_tasks; I ++) <br/> If (task [I] & task [I]-> pid = last_pid) <br/> goto repeat; <br/> for (I = 1; I <nr_tasks; I ++) // task 0 is excluded. <Br/> If (! Task [I]) <br/> return I; <br/> return-eagain; <br/>} 

This function sets last_pid to the last available non-repeated PID Number, and then returns the index of idle items in the task [] array, which is stored in eax.

Then, import the corresponding registers to the stack and call copy_process () as a parameter of the C function ()

Int <br/> copy_process (int nr, long EBP, long EDI, long ESI, long Gs, long none, <br/> long EBX, long ECx, long edX, <br/> long FS, long es, long ds, <br/> long EIP, long CS, long eflags, long ESP, long SS) <br/>{< br/> struct task_struct * P; <br/> int I; <br/> struct file * F; <br/> P = (struct task_struct *) get_free_page (); // allocate memory for the new task data structure. <Br/> If (! P) // if an error occurs in memory allocation, the error code is returned and the system exits. <Br/> return-eagain; <br/> task [Nr] = P; // Add the new task structure pointer to the task array. <Br/> // where NR is the task number, which is returned by find_empty_process. <Br/> * P = * Current;/* Note! This doesn' t copy the supervisor stack */<br/>/* Note! In this way, the superuser stack is not copied */(only the content of the current process is copied ). <Br/> P-> state = task_uninterruptible; // set the status of the new process to the non-disruptive wait state. <Br/> P-> pid = last_pid; // The new process ID. Obtained by calling find_empty_process. <Br/> P-> father = Current-> PID; // set the parent process ID. <Br/> P-> counter = p-> priority; <br/> P-> signal = 0; // set the signal bitmap to 0. <Br/> P-> alarm = 0; <br/> P-> leader = 0; /* process leadership doesn' t inherit */<br/>/* the process's leadership cannot be inherited */<br/> P-> utime = p-> stime = 0; // initialize the user State time and core state time. <Br/> P-> cutime = p-> cstime = 0; // initialize the subprocess user State and core state time. <Br/> P-> start_time = jiffies; // The current answer time. <Br/> // set the data required by TSS in the task Status section below (see the description after the list ). <Br/> P-> TSS. back_link = 0; <br/> P-> TSS. esp0 = page_size + (long) P; // Stack pointer (because 1 page is allocated to the task structure P <br/> // new memory, so esp0 points to the top of the page ). <Br/> P-> TSS. ss0 = 0x10; // stack segment selection character (kernel data segment) [?]. <Br/> P-> TSS. EIP = EIP; // command code pointer. <Br/> P-> TSS. eflags = eflags; // The flag register. <Br/> P-> TSS. eax = 0; <br/> P-> TSS. ECX = ECx; <br/> P-> TSS. edX = edX; <br/> P-> TSS. EBX = EBX; <br/> P-> TSS. ESP = ESP; <br/> P-> TSS. EBP = EBP; <br/> P-> TSS. ESI = ESI; <br/> P-> TSS. EDI = EDI; <br/> P-> TSS. es = ES & 0 xFFFF; // The segment register is only valid for 16 bits. <Br/> P-> TSS. cs = cs & 0 xFFFF; <br/> P-> TSS. ss = SS & 0 xFFFF; <br/> P-> TSS. DS = DS & 0 xFFFF; <br/> P-> TSS. FS = FS & 0 xFFFF; <br/> P-> TSS. GS = GS & 0 xFFFF; <br/> P-> TSS. LDT = _ LDT (NR); // select the Local Descriptor Table of the new task NR (the LDT descriptor is in gdt ). <Br/> P-> TSS. trace_bitmap = 0x80000000; <br/> // if the current task uses a coprocessor, the context is saved. <Br/> If (last_task_used_math = Current) <br/> _ ASM _ ("clts; fnsave % 0": "M" (p-> TSS. i387); <br/> // set the code and Data Segment Base Address of the new task, limit the length, and copy the page table. If an error occurs (the return value is not 0), <br/> // the corresponding item in the reset task array and release the Memory Page allocated for the new task. <Br/> If (copy_mem (NR, p) <br/> {// If the returned value is not 0, an error occurs. <Br/> task [Nr] = NULL; <br/> free_page (long) P); <br/> return-eagain; <br/>}< br/> // if a file in the parent process is opened, the number of opened files increases by 1. <Br/> for (I = 0; I <nr_open; I ++) <br/> If (F = p-> filp [I]) <br/> F-> f_count ++; <br/> // increase the number of PWD, root, and executable references of the current process (parent process) by 1. <Br/> If (current-> pwd) <br/> current-> pwd-> I _count ++; <br/> If (current-> root) <br/> current-> root-> I _count ++; <br/> If (current-> executable) <br/> current-> executable-> I _count ++; <br/> // set the TSS and LDT descriptor items of the new task in gdt. The data is obtained from the task structure. <Br/> // when the task is switched, the task register TR is automatically loaded by the CPU. <Br/> set_tss_desc (gdt + (NR <1) + first_tss_entry, & (p-> TSS); <br/> set_ldt_desc (gdt + (NR <1) + first_ldt_entry, & (p-> LDT); <br/> P-> state = task_running;/* do this last, just in case */<br/>/* Finally, set the new task to a running state, in case */<br/> return last_pid; // return the new process number (which is different from the task number ). <Br/>} 

The execution content of this Code is: first allocate memory for the process, then put the pointer of the new task into the idle task [] array item found in the previous step, then copy the content of the parent process and modify the current

A part of the attributes and TSS (Task status segment) of the process. Finally, set the code segment and Data Segment of the new process. The limit is long. In gdt, set the TSS and LDT descriptor items of the new task, the data is retrieved from the task structure. During task switching, the task register TR is automatically loaded by the CPU.

Set_tss_desc (gdt + (NR <1) + first_tss_entry, & (p-> TSS ));

Set_ldt_desc (gdt + (NR <1) + first_ldt_entry, & (p-> LDT ));

P-> state = task_running;

In this way, the new process is created.

The copy page table function copy_mem () is to be continued .......

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.