Understanding of Process Creation fork () in the Linux 0.11 version kernel __linux

Source: Internet
Author: User

First look at the fork system call, the source code is as follows:

_sys_fork: Call
	_find_empty_process  #这个函数用来取得一个pid, if a negative number directly exit
	testl%eax,%eax     
	JS 1f
	push%gs
	pushl%esi
	pushl%edi
	pushl%ebp pushl%eax call
	_copy_process   #这个函数用来复制进程
	addl $20,% ESP       #前面压了5个参数, each 4 byte, a total of 20 bytes, which means discarding the value of these stacks
1:	ret
Overall, see here I think the process should be to get a PID, and then copy the process descriptor to modify the parent process, and then copy the page table, set off the Gdt,ldt. Find_empty_process () source code is as follows:
int find_empty_process (void)
{
	int i;

	Repeat:
		if ((++last_pid) <0) last_pid=1;
		For (i=0 i<nr_tasks i++)
			if (task[i] && task[i]->pid = last_pid) goto repeat;
	for (I=1 i<nr_tasks; i++)
		if (!task[i)) return
			i;
	Return-eagain;
}
Analysis: In fact, it is last_pid constantly add one, and then determine whether the process number has been used by any process, some words repeat the process, no words continue to execute, and then find an idle task item, return. Where Last_pid is a global variable, recording the current can be allocated PID, do not have to return. Copy_process () The code is relatively long, directly in the code using annotations to explain, the following is the Copy_process () Source:

int copy_process (int nr,long ebp,long edi,long esi,long gs,long None, Long Ebx,long ecx,long edx, long Fs,long Es,long
	DS, Long Eip,long cs,long eflags,long Esp,long ss) {struct task_struct;
	int i;

struct file *f; * * using get_free_page () to apply for a page space is 4K, this memory is used to store the process descriptor, which is the idle task number returned by the previous function, points the task number to the newly assigned process descriptor, and then copies the contents of the current task descriptor into the newly allocated memory.
	Now the descriptor of the subprocess is exactly the same as the parent process * * p = (struct task_struct *) get_free_page ();
	if (!p) Return-eagain;
	TASK[NR] = p;	*p = *current; /* note! This doesn ' t copy the supervisor Stack */////////////////p->state = task_uninterruptible;                   First set to be not interrupted sleep, avoid accidentally switch in p->pid = Last_pid;             Get the PID P->father = current->pid; of the sub process             The parent process P->counter = p->priority; for the current process                      The time slice is a priority value p->signal = 0;                      Clear the signal bitmap p->alarm = 0;		                 Empty alarm timing P->leader = 0;            The leading position of the conversation cannot be the same as the parent process p->utime = P->stime = 0; Some statistical information zero, user state and kernel state time P->cutime = P->csTime = 0;              Child process user state and kernel state time p->start_time = jiffies;               Set the time when the subprocess started running/* The TSS segment of the subprocess has a place that the parent process does not want to listen to and needs to be modified/p->tss.back_link = 0; I'm not really sure about that either. p->tss.esp0 = Page_size + (long) p;                 The kernel-state stack pointer should point to the top of the allocated memory P->tss.ss0 = 0x10;        
	Kernel-State stack selector, same as data segment P-&GT;TSS.EIP = EIP;
	P->tss.eflags = EFlags;       P->tss.eax = 0;
	The return value of the child process is 0 p->tss.ecx = ecx;
	P->tss.edx = edx;
	P-&GT;TSS.EBX = EBX;
	P-&GT;TSS.ESP = ESP;
	P-&GT;TSS.EBP = EBP;
	P->tss.esi = ESI;
	P->tss.edi = EDI;
	p->tss.es = es & 0xffff;
	P->tss.cs = cs & 0xFFFF;
	P-&GT;TSS.SS = ss & 0xFFFF;
	P->tss.ds = ds & 0xFFFF;
	P->tss.fs = FS & 0xFFFF;
	P->tss.gs = GS & 0xFFFF; P->tss.ldt = _ldt (NR);

	_ldt (NR) is to find out the position of the task number in the GDT, that is, the selector, GDT's structure in a previous blog post mentioned p->tss.trace_bitmap = 0x80000000; if (Last_task_used_math = = current)//No understanding of the coprocessor, this probably means that the parent process has used the coprocessor, it is necessary to save the context __asm__ ("clts;

Fnsave%0 "::" M "(p->tss.i387)); /* Next to TuneUse the Copy_mem () function to reset the child Process code snippet and data segment, and copy the page table, followed by the analysis of the */if (Copy_mem (nr,p)) {TASK[NR] = NULL;
		Free_page ((long) p);
	Return-eagain; }/* If the file is open, then the file's System files open Table add one, the parent-child process can share these files open the table, and other pwd and so on these references should be increased by a * for (i=0 i<nr_open;i++) if (f=p->filp[i)) F-&G
	t;f_count++;
	if (CURRENT-&GT;PWD) current->pwd->i_count++;
	if (current->root) current->root->i_count++;

if (current->executable) current->executable->i_count++; The first four/*gdt are null, kernel code segment, kernel data segment, system call segment, plus First_tss_entry is skipped the first four segments, then the TSS and LDT sections of task 0, the TSS and Ldt of Task 1, and so on, so plus (nr< &LT;1) refers to the content of the NR task in GDT, the first sentence sets the task's TSS in the GDT descriptor, the second sentence sets the LDT in the GDT descriptor, then makes the task operational, and then exits/Set_tss_desc (gdt+
	<1) +first_tss_entry,& (P-&GT;TSS));
	Set_ldt_desc (gdt+ (nr<<1) +first_ldt_entry,& (P->ldt));	P->state = task_running;
/* Do this last, just into case/return last_pid; }
Next look at Copy_mem () The source code, as follows:

int copy_mem (int nr,struct task_struct * p) {unsigned long old_data_base,new_data_base,data_limit;

unsigned long old_code_base,new_code_base,code_limit; /*0X0F is the selector of the code snippet in Ldt, the 0x17 is the descriptor of the data segment, the identifier is found by the selector to find the segment limit length/Code_limit=get_limit (0x0f), and the 0x0f is the selector of the code snippet, data_limit= by the selector

Get_limit (0x17);
	/*ldt[1] refers to the descriptor of the code snippet, ldt[2] refers to the descriptor of the data segment, through which the segment base address/old_code_base = Get_base (current->ldt[1]) is obtained;

Old_data_base = Get_base (current->ldt[2]); /*linux 0.11 inside the data segment and the code segment is not separate, that is, the base and the limit is the same, is not the same as the error/if (old_data_base!= old_code_base) Panic ("We don ' t support separate the i&
	Amp;d ");

if (Data_limit < Code_limit) Panic ("Bad data_limit"); /*0x4000000 represents a 64M space, each task occupies 64M in the linear address space, its starting address is NR * 0x4000000, this address is the segment base of the child process * * * new_data_base = New_code_base = nr * 0x4
	000000;
	P->start_code = New_code_base;
	Set_base (p->ldt[1],new_code_base);

Set_base (p->ldt[2],new_data_base); /* The page table entry in the parent process is copied so that the parent-child process shares the */if (Copy_page_tables (Old_data_base,new_data_base,data_limit)) {Free_page_tables (new_ Data_base,data_limit);
	Return-enomem;
return 0; }
Summarize the entire process of fork (), start with a PID and an idle task number, then call copy_process to create space for the child process task structure, copy the contents of the parent process to the new application space, and then modify the content in the process descriptor, including PID, statistics, Semaphore, and so on, also modifies the TSS segment of the subprocess to the address of the content, including the eax inside, the kernel stack pointer, and the index number of the GDT in the sub process LDT. After that, you set up a subprocess to ldt the base and length of the neutron process code segment and data segment, copy the page table for the code snippet data segment of the parent process, add a second table to the file tables that are open in the parent process, and finally set the GDT TSS and LDT descriptors.



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.