Linux 시스템에서 새 프로세스 생성(하)

6186 단어
생성 프로세스에 대한 키 코드 찾아보기
도 봐봐.fork     /linux-3.18.6/kernel/fork.c#do_fork
1651	p = copy_process(clone_flags, stack_start, stack_size,      //          
1652			 child_tidptr, NULL, trace);

코피 한번...process     /linux-3.18.6/kernel/fork.c#copy_process
1240	p = dup_task_struct(current);      //   PCB

dup 한번 봅시다.task_struct     /linux-3.18.6/kernel/fork.c#dup_task_struct
320	err = arch_dup_task_struct(tsk, orig);      //     ,orig     
316	ti = alloc_thread_info_node(tsk, node);      //     alloc      

324 tsk->stack = ti; // alloc stack

archdup_task_struct    /linux-3.18.6/kernel/fork.c#arch_dup_task_struct
290int __weak arch_dup_task_struct(struct task_struct *dst,
291					       struct task_struct *src)
292{
293	*dst = *src;      //         *,           , *,     
294	return 0;
295}

alloc 보세요.thread_info_node    /linux-3.18.6/kernel/fork.c#alloc_thread_info_node
150static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
151						  int node)
152{
153	struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP,
154						  THREAD_SIZE_ORDER);
155
156	return page ? page_address(page) : NULL;
157}

실제 내부 핵 창고 공간을 분배하는 효과를 냈는데, 실제 코드는allockmem_pages_de, 일정한 크기의 페이지를 만들었습니다. 페이지의 일부분은thread 를 저장하는 데 사용됩니다.info, 다른 부분은 높은 주소에서 낮은 주소로 핵 창고입니다
dup으로 돌아가기task_struct, 현재 부모 프로세스의 PCB, 즉task 를struct 데이터 구조가 복사되었습니다. 즉 p가 가리키는 하위 프로세스의 PCB (프로세스 설명자)
1240	p = dup_task_struct(current);      //   PCB

이후의 코드는 서브프로세스 내용을 대량으로 수정한 코드가 있는데, 초기화하면 이것들은 모두 추상화할 수 있다
1375	retval = copy_files(clone_flags, p);

1378	retval = copy_fs(clone_flags, p);      //        

1381	retval = copy_sighand(clone_flags, p);

1384	retval = copy_signal(clone_flags, p);      //      

1387	retval = copy_mm(clone_flags, p);      //      

1390	retval = copy_namespaces(clone_flags, p);

1393	retval = copy_io(clone_flags, p);      //    IO

1396 retval = copy_thread(clone_flags, stack_start, stack_size, p); //

코피 한번...thread   /linux-3.18.6/arch/x86/kernel/process_32.c#132
135	struct pt_regs *childregs = task_pt_regs(p);

여기에서 볼 수 있듯이 하위 프로세스의pid, 즉 내부 창고의 위치에서 창고 공간을 찾았습니다.SAVEALL의 일부 내용, SAVEAll 주소
139	p->thread.sp = (unsigned long) childregs;      //             

창고의 밑천을 물다
커널 스택 데이터 복사 및 새 프로세스의 첫 번째 명령 주소 지정
159	*childregs = *current_pt_regs();      //       

현재 프로세스, 즉 아버지 프로세스입니다. 왜냐하면 이 실행 프로세스는 아버지 프로세스의 실행 상하문에 있기 때문입니다.상위 프로세스의 커널 스택, 즉 SAVEAll의 내용을 복사해 오너라. 이곳은 실제적으로 내부 핵 창고에 이미 있는 데이터를 복사하는 것이다
주의해야 할 점: 코어 스택을 복제할 때 SAVE와만 복제됨ALL과 관련된 부분은 struct pt 만 복사됩니다.regs
한번 struct ptregs 데이터 구조의 내용/linux-3.18.6/arch/x86/include/asm/ptrace.h
9#ifdef __i386__
10
11struct pt_regs {

// SAVE_ALL
12 unsigned long bx; 13 unsigned long cx; 14 unsigned long dx; 15 unsigned long si; 16 unsigned long di; 17 unsigned long bp; 18 unsigned long ax; // 19 unsigned long ds; 20 unsigned long es; 21 unsigned long fs; 22 unsigned long gs; 23 unsigned long orig_ax; // eax
// int 0x80 ,CPU
24 unsigned long ip; 25 unsigned long cs; 26 unsigned long flags; 27 unsigned long sp; 28 unsigned long ss; 29}; 30 31#else /* __i386__ */

내부 핵 창고를 복제할 때 i386은 내부 핵 창고의 가장 창고 밑의 일부분만 복제했다. 즉, 시스템이 창고를 압축하는 과정, int 0x80 명령어(CPU 자동)와 SAVEAll이 커널 스택에 깔린 내용
160	childregs->ax = 0;      //        fork  0,      !

되돌아오는 값은 eax에 저장되고 pid=0은 이 값에 저장됩니다.하위 프로세스의 반환 값이 0이기 때문에 복사가 끝나면 내장 창고에 눌린 반환 값을 수정해야 합니다
161	if (sp)
162		childregs->sp = sp;      // sp    copy_thread      stack_start

스택 베이스 데이터 포함
164	p->thread.ip = (unsigned long) ret_from_fork;      //                

할당 thread.ip의 내용은retfrom_fork, 하위 프로세스가 프로세스 스케줄링을 받고 CPU를 받을 때 이 위치에서 실행됩니다
엔리 봐봐요.32.S   /linux-3.18.6/arch/x86/kernel/entry_32.S
시스템 호출 총 제어 프로그램,ret 찾기from_fork
290ENTRY(ret_from_fork)
291	CFI_STARTPROC
292	pushl_cfi %eax
293	call schedule_tail
294	GET_THREAD_INFO(%ebp)
295	popl_cfi %eax
296	pushl_cfi $0x0202		# Reset kernel eflags
297	popfl_cfi
298	jmp syscall_exit		//        syscall_exit
299	CFI_ENDPROC
300END(ret_from_fork)

syscall_exit는 어디에 있습니까?
490ENTRY(system_call)

493	pushl_cfi %eax			# save orig_eax
494	SAVE_ALL			//     SAVE_ALL

501syscall_call:			//     system_call
502	call *sys_call_table(,%eax,4)
503syscall_after_call: // call //
504 movl %eax,PT_EAX(%esp) # store the return value 505syscall_exit:

call 되돌아오기, 내부 창고로 되돌아오기, 즉 내부 창고가 어떻게 창고에 쌓이면 어떻게 나오는지,syscallexit 때, 실제로sys콜하기 전에 얘가 쌓인 상태가 똑같아요.
그래서retfrom_forksyscall 로 건너뛰기exit 오면 계속 아래로 실행할 수 있고 사용자 상태로 정상적으로 되돌아갈 수 있습니다
즉, 하위 프로세스가 CPU 제어권을 얻고 실행을 시작할 때 그의retfrom_kk는 뒤에 있는 창고를 창고에서 내보낼 수 있습니다.iret에서 사용자 상태로 되돌려줍니다. 이때 사용자 상태로 되돌려줍니다. 원래 아버지 프로세스의 프로세스 공간이 아니라 하위 프로세스의 프로세스 공간입니다.
(다음 편 끝)

좋은 웹페이지 즐겨찾기