190 likes | 284 Views
제 38 강 : Process (Functions). Ch 3 Process - Functions -. /* this struct shares the supervisor stack pages */ struct thread_info { struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */
E N D
제38강 : Process (Functions) Ch 3 Process- Functions -
/* this struct shares the supervisor stack pages */ struct thread_info{ struct task_struct*task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ unsigned long flags; /* low level flags */ unsigned long status; /* thread-sync flags */ u32 cpu; /* current CPU */ s32 preempt_count; struct restart_block /*restart_block; u8 supervisor_stack[0]; }; task_struct per each thread struct thread_info { task_struct *task;} files per each process per thread basic info fs tty mm kernel stack signals
A Process running on 3 CPU’s thread on CPU1 thread_info task_struct kernel stack (1) thread on CPU2 thread_info Process with 3 threads per thread basic info (0) (1) (0) (1) kernel stack thread on CPU3 thread_info kernel stack
Multiprocessor running many Processes CPU #0 CPU #1 CPU #2 program counter program counter program counter thread_info Shared Memory kernel stack sh a.out thread_info vi a.out kernel stack active thread_info? current_thread_info() thread_info kernel a.out kernel stack
Get currently executing task (1) Invoke current_thread_info()macro from any place in kernel (4) Dereference the pointer current_thread_info() task (3) page boundary address 27770000 task_struct struct thread_info { task_struct *task;} mask files per thread basic info fs (2) CPU SP = 27772345 tty mm Current Process kernel stack signals High Address
Process Creation task_struct • clone() system call, which then calls do_fork() do_fork() copy_process() dup_task_struct() which • kernel stack • create thread_info • task_struct • Assigns new PID • Check flag – either copy or share {files, fs, mm, …} • Can run now - share remaining timeslice with parent (1) thread_info files (0) per thread basic info fs (1) tty (0) mm kernel stack signals (1)
task_struct thread_info (1) per thread basic info (0) (1) (0) kernel stack (1) clone() • clone()do_fork()copy_process()dup_task_struct() • dup_task_struct() : • Creates new kernel stack,/thread_info/task_struct • Copy values from parent • Call get_pid() to get new PID • Check clone(flags) • Copy requested structs from parent • Return a pointer to the new child • On return from copy_process() • Run the child first • child shares the parent’s remaining time slice • child usually exec() immediately
How child is run first • Parent assigns high priority to child process • wake_up_new_task() /* set priority & state of child */ • set_need_resched() /* “someone is waiting for CPU”*/ • parent concludes system call • Before returning to parent’s user code • Kernel checks if higher priority process is waiting • Kernel preempts CPU (parent is forced to sleep) • Kernel gives CPU to child • child starts – exec() – no longer shares memory
Parent’s code main() {int pid; pid =fork(); if (pid = = 0) /* this is child */ { execlp(“/bin/date” ……); } else /* this is parent */ if (pid > 0) { wait();then parent’s remaining code } }
Lions code main() { pid = fork(); if (child) exec(/bin/ls); else /* parent */ { wait() work after creating child } main() { pid = fork(); if (child) exec(/bin/ls); else /* parent */ { wait() work after creating child } user kernel mode mode kernel dispatches parent wait() is done sh (parent) sh fork sh wait sh parent: blocked ready ls (child) exec ls exit sh exec ls Child Creation in Lion’s Code
Paging System main() { pid = fork(); if (child) exec(/bin/ls); else /* parent */ { work after creating child } COW Copy On Write user kernel mode mode kernel dispatches parent wait() is done “memory write” causes COW sh (parent) sh fork sh wait sh parent: blocked ready ls (child) exec ls exit sh exec ls Child Creation in Lion’s Code
Every “memory write” by parent (after return from fork()) causes COW page faults Such COW pages are rarely used by child kernel dispatches parent wait() is done sh (parent) sh fork sh wait sh parent: blocked ready ls (child) sh exec ls exit exec ls Child Creation in Linux
(1) When fork() returned to parent parent caused unnecessary COW pages sh (parent) sh fork sh wait sh ls (child) sh ls exit exec exec ls (2) Postpone returning to parent’s user code sh (parent) sh fork sh sh (3) Let child run first ie fork() returns to child’s a.out • parent resumes later • this time, • “memory write” by parent • does not cause COW ls (child) sh ls exit exec exec ls
main() { pid = fork(); if (child) exec(/bin/ls); else /* parent */ { work after creating child } main() { pid = fork(); if (child) exec(/bin/ls); else /* parent */ { work after creating child } Why run child first • If parent continues on return from copy_process() • parent may write to his memory (address space) (parent can be shell, mail, make … parent may do a lot of things after creating child) • whereas child usually exec immediately after fork (no write to memory before exec) • What happens if parent writes to memory? • write causes COW inefficient! (child doesn’t need this copy) • So why not let child run first, and let child exec ASAP? • This prevents unnecessary COW incurred by parent. • After child performs exec(), • child sends signal to parent • mm_release() – “a.out is no longer shared” - no more COW • Parent wakes up and returns
PID • Provided for backward compatibility • Store inside PCB • get_pid() assigns a new PID “Thread of Execution” • Describes any executing code • (user) task running in kernel mode • interrupt handler • kernel thread
P0 kernel thread (KT) P1 (sh) P th • Created when kernel process calls clone() • accesses kernel’s address space • executes kernel code • No private address space (mm pointer is NULL) • Exist solely in kernel space • some daemons (sleep until request) are KT (vi) P
Process State • Process state • TASK_RUNNING ready • TASK_INTERRUPTIBLE wakeup if signal arrives • TASK_UNINTERRUPTIBLE ignore signal • TASK_ZOMBIE • TASK_STOPPED • Set current process state • set_task_state(task, state) • Every process has one parent & a list of children • Pointer to parent, children, sibling P P P P P
Process Termination • Regardless of how a process terminates, • bulk of the work is handled by do_exit() • release the mm_struct __exit__mm() • dequeue from IPC semaphore (if any) exit_sem() • decrement usage count of objects __exit_files(), __exit_fs(), … eg file, file system,.. remove object if count = zero • Set task’s exit code • send signal to the task’s parent exit_notify() (also set task’s state to TASK_ZOMBIE) (retains minimal kernel information) • switch to the new process schedule()
P0 Process Termination P1 (sh) P • If the process was created by nohup command • If a parent exits before its children, must reparent the child task • Reparent a task’s children on exit to either another process in the current thread group, or init (P1) process • do_exit() calls notify_parent() • notify_parent() calls forget_original_parent() (sim) P