============
- 163차 시작 위치
- start_kernel 1 ~/init/main.c
- rest_init 968 ~/init/main.c
- kernel_thread 453 ~/init/main.c
- do_fork 2067 ~/kernel/fork.c
- copy_process 2020 ~/kernel/fork.c
- sched_fork 1734 ~/kernel/fork.c
- call: start_kernel()
- lockdep_init()
- smp_setup_processor_id()
- debug_objects_early_init()
- boot_init_stack_canary()
- cgroup_init_early()
- local_irq_disable()
- boot_cpu_init()
- page_address_init()
- pr_notice()
- setup_arch()
- mm_init_owner()
- mm_init_cpumask()
- setup_command_line
- build_all_zonelists()
- page_alloc_init()
- pr_notice()
- parse_early_param()
- parse_args()
- jump_label_init()
- setup_log_buf()
- pidhash_init()
- vfs_caches_init_early()
- sort_main_extable()
- trap_init()
- mm_init()
- sched_init()
- preempt_disable()
- irqs_disabled()
- local_irq_disabled()
- idr_init_cache()
- rcu_init()
- tick_nohz_init()
- contect_tracking_init()
- radix_tree_init()
- early_irq_init()
- init_IRQ()
- tick_init()
- init_timers()
- hrtimers_init()
- softirq_init()
- timekeeping_init()
- time_init()
- sched_clock_postinit()
- pref_event_init()
- profile_init()
- call_function_init()
- irqs_disabled()
- local_irq_enabled()
- kmem_cache_init_late()
- console_init()
- lockdep_init()
- lockdep_info()
- locking_selftest()
- virt_to_page()
- page_to_pfn()
- page_cgroup_init()
- debug_objects_mem_init()
- kmemleak_init()
- setup_per_cpu_pageset()
- numa_policy_init()
- sched_clock_init()
- calibrate_delay()
- pidmap_init()
- anon_vma_init()
- thread_info_cache_init()
- cred_init()
- fork_init()
- proc_caches_init()
- buffer_init()
- key_init()
- security_init()
- dbg_late_init()
- vfs_caches_init()
- signals_init()
- page_writeback_init()
- proc_root_init()
- cgroup_init()
- cpuset_init()
- taskstats_init_early()
- delayacct_init()
- check_bugs()
- acpi_early_init()
- sfi_init_late()
- efi_enabled(EFI_RUNTIME_SERVICES)
- ftrace_init()
- rest_init()
- call: rest_init()
- rcu_scheduler_starting()
- kernel_thread()
- call: kernel_thread()
- do_fork()
- call: do_fork()
- copy_process()
- call: copy_process()
- security_task_create()
- dup_task_struct()
- ftrace_graph_init_task(p); // null function
- get_seccomp_filter(p); // null function
- rt_mutex_init_task(p);
- copy_creds(p, clone_flags);
- try_module_get()
- delayacct_tsk_init(p)
- copy_flags()
- INIT_LIST_HEAD(&p->children);
- INIT_LIST_HEAD(&p->sibling);
- rcu_copy_process(p);
- spin_lock_init(&p->alloc_lock);
- init_sigpending(&p->pending);
- memset(&p->rss_stat, 0, sizeof(p->rss_stat));
- task_io_accounting_init(&p->ioac); // null function
- acct_clear_integrals(p); // null function
- posix_cpu_timers_init(p);
- do_posix_clock_monotonic_gettime(&p->start_time);
- monotonic_to_bootbased(&p->real_start_time);
- cgroup_fork(p);
- sched_fork(clone_flags, p);
- perf_event_init_task(p); // null function
- audit_alloc(p); // null function
- copy_semundo(clone_flags, p);
- copy_files(clone_flags, p);
- copy_fs(clone_flags, p);
- call: copy_fs(clone_flags, p);
- call: start_kernel()
- lockdep_init()
- smp_setup_processor_id()
- debug_objects_early_init()
- boot_init_stack_canary()
- cgroup_init_early()
- local_irq_disable()
- boot_cpu_init()
- page_address_init()
- pr_notice()
- setup_arch()
- mm_init_owner()
- mm_init_cpumask()
- setup_command_line
- build_all_zonelists()
- page_alloc_init()
- pr_notice()
- parse_early_param()
- parse_args()
- jump_label_init()
- setup_log_buf()
- pidhash_init()
- vfs_caches_init_early()
- sort_main_extable()
- trap_init()
- mm_init()
- sched_init()
- preempt_disable()
- irqs_disabled()
- local_irq_disabled()
- idr_init_cache()
- rcu_init()
- tick_nohz_init()
- contect_tracking_init()
- radix_tree_init()
- early_irq_init()
- init_IRQ()
- tick_init()
- init_timers()
- hrtimers_init()
- softirq_init()
- timekeeping_init()
- time_init()
- sched_clock_postinit()
- pref_event_init()
- profile_init()
- call_function_init()
- irqs_disabled()
- local_irq_enabled()
- kmem_cache_init_late()
- console_init()
- lockdep_init()
- lockdep_info()
- locking_selftest()
- virt_to_page()
- page_to_pfn()
- page_cgroup_init()
- debug_objects_mem_init()
- kmemleak_init()
- setup_per_cpu_pageset()
- numa_policy_init()
- sched_clock_init()
- calibrate_delay()
- pidmap_init()
- anon_vma_init()
- thread_info_cache_init()
- cred_init()
- fork_init()
- proc_caches_init()
- buffer_init()
- key_init()
- security_init()
- dbg_late_init()
- vfs_caches_init()
- signals_init()
- page_writeback_init()
- proc_root_init()
- cgroup_init()
- cpuset_init()
- taskstats_init_early()
- delayacct_init()
- check_bugs()
- acpi_early_init()
- sfi_init_late()
- efi_enabled()
- efi_late_init()
- efi_free_boot_services()
- ftrace_init()
- rest_init()
// ARM10C 20130824
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
// ATAG,DTB 정보로 사용
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
lockdep_init();
smp_setup_processor_id();
debug_objects_early_init();
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary();
cgroup_init_early();
// cgroup 를 사용하기 위한 cgroup_dummy_root, cgroup_subsys 의 구조체 초기화 수행
local_irq_disable();
// IRQ를 disable 함
early_boot_irqs_disabled = true;
// early_boot_irqs_disabled: true
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
boot_cpu_init();
// 현재 cpu(core id)를 얻어서 cpu_XXX_bits[] 의 cpu를 셋한다.
page_address_init();
// 128개의 page_address_htable 배열을 초기화
pr_notice("%s", linux_banner);
// 배너:
// Linux version 2.6.37_DM385_IPNC_3.50.00
// (a0875405@bangvideoapps01) (gcc version 4.5.3 20110311
// (prerelease) (GCC) ) #1 Fri Dec 21 17:27:08 IST 2012
setup_arch(&command_line);
mm_init_owner(&init_mm, &init_task); // null function
mm_init_cpumask(&init_mm); // null function
// command_line: exynos5420-smdk5420.dts 파일의 chosen node 의 bootarg 값
// "console=ttySAC2,115200 init=/linuxrc"
setup_command_line(command_line);
// saved_command_line 및 static_command_line 할당
setup_nr_cpu_ids();
setup_per_cpu_areas();
// pcpu 구조체를 만들어 줌 (mm/percpu.c)
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
// boot cpu 0의 pcpu 영역의 base주소를 core register에 설정해줌
build_all_zonelists(NULL, NULL);
page_alloc_init();
// cpu_chain에 page_alloc_cpu_notify를 연결함 (mutex lock/unlock 사용)
// boot_command_line: "console=ttySAC2,115200 init=/linuxrc"
pr_notice("Kernel command line: %s\n", boot_command_line);
// "Kernel command line: console=ttySAC2,115200 init=/linuxrc"
parse_early_param();
// setup_arch에서 수행했던 작업 다시 수행
// command arg에서 각 요소들을 파싱하여 early init section으로 설정된 디바이스 초기화.
// 우리는 serial device가 검색이 되지만 config설정은 없어서 아무것도 안함.
// static_command_line: "console=ttySAC2,115200 init=/linuxrc"
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
-1, -1, &unknown_bootoption);
// DTB에서 넘어온 bootargs를 파싱하여 param, val을 뽑아내고 그에 대응되는
// kernel_param 구조체에 값을 등록함.
jump_label_init();
// HAVE_JUMP_LABEL 이 undefined 이므로 NULL 함수
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
setup_log_buf(0);
// defalut log_buf의 크기는 __LOG_BUF_LEN: 0x20000 (128KB) 임
// early_param 에서 호출했던 log_buf_len 값이 있다면 log_buf의 크기를 넘어온 크기로 만듬
pidhash_init();
// pidhash의 크기를 16kB만큼 할당 받고 4096개의 hash list를 만듬
vfs_caches_init_early();
// Dentry cache, Inode-cache용 hash를 위한 메모리 공간을 각각 512kB, 256kB만큼 할당 받고,
// 131072, 65536개 만큼 hash table을 각각 만듬
sort_main_extable();
// extable 을 cmp_ex를 이용하여 sort수행
trap_init(); // null function
mm_init();
// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
// pcpu 메모리, vmlist 는 slab으로 이관
/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
sched_init();
// scheduler가 사용하는 자료 구조 초기화, idle_threads를 init_task로 세팅
/*
* Disable preemption - early bootup scheduling is extremely
* fragile until we cpu_idle() for the first time.
*/
preempt_disable();
// preempt count를 증가시켜 preemption 못하도록 막음
// irqs_disabled(): 1
if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))
local_irq_disable();
idr_init_cache();
// integer ID management로 사용하는 idr_layer_cache에 kmem_cache#21 을 생성 및 초기화 후 할당
rcu_init();
// rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
tick_nohz_init(); // null function
context_tracking_init(); // null function
radix_tree_init();
// radix tree로 사용하는 radix_tree_node_cachep에 kmem_cache#20을 생성 및 초기화 후 할당하고
// height_to_maxindex을 초기화 수행
/* init some links before init_ISA_irqs() */
early_irq_init();
// irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
// allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가
init_IRQ();
// gic, combiner이 사용할 메모리 할당과 자료 구조 설정,
// gic irq (0~15), combiner irq (32~63) interrupt 를 enable 시킴
tick_init();
// tick 관련 mask 변수를 0으로 초기화 수행
init_timers();
// boot_tvec_bases의 맴버 값을 초기화하고 timers_nb를 cpu_notifier 에 등록,
// softirq_vec[1] 에 run_timer_softirq 등록하여 초기화 수행
hrtimers_init();
// hrtimer_bases의 맴버 값을 초기화하고 hrtimers_nb를 cpu_notifier 에 등록,
// softirq_vec[8] 에 run_hrtimer_softirq 등록하여 초기화 수행
softirq_init();
// tasklet_vec, tasklet_hi_vec 맴버 값을 초기화하고,
// softirq_vec[6]에 tasklet_action, softirq_vec[0]에 tasklet_hi_action 등록하여 초기화 수행
timekeeping_init();
// ntp 관련 전역변수 초기화, timekeeper, shadow_timekeeper의 맴버값 초기화 수행
time_init();
// timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
// timer event를 위한 timer irq (MCT) 초기화 수행
sched_clock_postinit();
// sched_clock_timer을 초기화 수행
perf_event_init(); // null function
profile_init(); // null function
call_function_init();
// 각 cpu core에서 사용할 call_single_queue를 맴버값 초기화
// cfd_data 맴버값을 초기화하고 pcp에서 사용할 메모리 공간 할당
// cpu_chain에 hotplug_cfd_notifier 를 등록함
// irqs_disabled(): 1
WARN(!irqs_disabled(), "Interrupts were enabled early\n");
// early_boot_irqs_disabled: true
early_boot_irqs_disabled = false;
// early_boot_irqs_disabled: false
local_irq_enable();
// IRQ를 enable 함
kmem_cache_init_late(); // null function
/*
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
*/
console_init();
// panic_later: NULL
if (panic_later)
panic(panic_later, panic_param);
lockdep_info(); // null function
/*
* Need to run this when irqs are enabled, because it wants
* to self-test [hard/soft]-irqs on/off lock inversion bugs
* too:
*/
locking_selftest(); // null function
#ifdef CONFIG_BLK_DEV_INITRD // CONFIG_BLK_DEV_INITRD=y
// initrd_start: NULL, initrd_below_start_ok: 0
if (initrd_start && !initrd_below_start_ok &&
page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
page_to_pfn(virt_to_page((void *)initrd_start)),
min_low_pfn);
initrd_start = 0;
}
#endif
page_cgroup_init(); // null function
debug_objects_mem_init(); // null function
kmemleak_init(); // null function
setup_per_cpu_pageset();
// per cpu가 사용하는 pageset의 각각의 zone 맴버값 초기화 수행
numa_policy_init(); // null function
// late_time_init: NULL
if (late_time_init)
late_time_init();
sched_clock_init();
// sched_clock_running 값을 1 로 초기화 수행
calibrate_delay();
// BogoMIPS값을 결정하기위한 계산을 수행하고 결과를 출력함
pidmap_init();
// pidmap 을 사용하기 위한 초기화 수행
anon_vma_init();
// anon vma 를 사용하기 위한 kmem_cache 할당자 초기화 수행
#ifdef CONFIG_X86 // CONFIG_X86=n
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_enter_virtual_mode();
#endif
thread_info_cache_init(); // null function
cred_init();
// credentials 를 사용하기 위한 kmem_cache 할당자 초기화 수행
// totalram_pages: 총 free된 page 수
fork_init(totalram_pages);
// task_struct 를 사용하기 위한 kmem_cache 할당자 초기화 수행
// max_threads값을 계산하여 init_task에 threads값의 limit 값 설정함
proc_caches_init();
// sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
// 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행
buffer_init();
// buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행
key_init(); // null funtion
security_init(); // null funtion
dbg_late_init(); // null funtion
// totalram_pages: 총 free된 page 수
vfs_caches_init(totalram_pages);
// virtual file system을 위한 names, dentry, inode, filp, mount cache 생성 후
// file system 을 위한 초기화 수행 및 mount 수행, block, char dev 사용을 위한 초기화 수행
signals_init();
// signal을 사용하기 위한 kmem_cache 를 생성
/* rootfs populating might need page-writeback */
page_writeback_init();
// page writeback을 위한 global_dirty_limit, ratelimit_pages 값을 초기화 수행
#ifdef CONFIG_PROC_FS // CONFIG_PROC_FS=y
proc_root_init();
// proc filesystem을 등록 하고 proc을 사용하기 위한 dentry, inode 생성 후
// sysctl_base_table 에 등록된 kernel, vm, fs, debug, dev의 dir, files 를 recursive 하게 RB Tree 를 구성함
#endif
cgroup_init();
// cgroup에서 사용하는 sub system 인 debug_subsys, cpu_cgroup_subsys, cpuacct_subsys, freezer_subsys 를 등록 하고
// init_css_set.subsys 를 이용하여 hash key 값 생성, cgroup 을 위한 kobject 를 생성, cgroup용 fils system type을 추가 하여
// filesystem 에 등록함, cgroup 을 위한 proc 생성.
cpuset_init(); // null function
taskstats_init_early(); // null function
delayacct_init(); // null function
check_bugs();
// page 2개를 할당 받고 할당 받은 메모리에값을 쓰고 비교하여
// 메모리 동작을 테스트 수행한 이후 다시 메모리를 반환함
acpi_early_init(); /* before LAPIC and SMP init */ // null function
sfi_init_late(); // null function
// efi_enabled(EFI_RUNTIME_SERVICES): 1
if (efi_enabled(EFI_RUNTIME_SERVICES)) {
efi_late_init(); // null function
efi_free_boot_services(); // null function
}
ftrace_init(); // null function
/* Do the rest non-__init'ed, we're now alive */
rest_init();
}
- start_kernel()
- rest_init()
- call: rest_init()
// ARM10C 20160827
static noinline void __init_refok rest_init(void)
{
int pid;
rcu_scheduler_starting(); // null function
/*
* We need to spawn init first so that it obtains pid 1, however
* the init task will end up wanting to create kthreads, which, if
* we schedule it before we create kthreadd, will OOPS.
*/
// CLONE_FS: 0x00000200, CLONE_SIGHAND: 0x00000800
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
- start_kernel()
- rest_init()
- call: rest_init()
- rcu_scheduler_starting()
- kernel_thread()
// ARM10C 20160827
// kernel_init, NULL, 0x00000A00
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
// flags: 0x00000A00, CLONE_VM: 0x00000100, CLONE_UNTRACED: 0x00800000,
// fn: kernel_init, arg: NULL
return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
(unsigned long)arg, NULL, NULL);
}
- start_kernel()
- rest_init()
- call: rest_init()
- rcu_scheduler_starring()
- kernel_thread()
- call: kernel_thread()
- do_fork()
- call: do_fork()
// ARM10C 20160827
// flags: 0x00800B00, fn: kernel_init, arg: NULL, NULL, NULL
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
{
struct task_struct *p;
int trace = 0;
// trace: 0
long nr;
/*
* Determine whether and which event to report to ptracer. When
* called from kernel_thread or CLONE_UNTRACED is explicitly
* requested, no event is reported; otherwise, report if the event
* for the type of forking is enabled.
*/
// clone_flags: 0x00800B00, CLONE_UNTRACED: 0x00800000
if (!(clone_flags & CLONE_UNTRACED)) {
if (clone_flags & CLONE_VFORK)
trace = PTRACE_EVENT_VFORK;
else if ((clone_flags & CSIGNAL) != SIGCHLD)
trace = PTRACE_EVENT_CLONE;
else
trace = PTRACE_EVENT_FORK;
if (likely(!ptrace_event_enabled(current, trace)))
trace = 0;
}
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, trace: 0
p = copy_process(clone_flags, stack_start, stack_size,
child_tidptr, NULL, trace);
- start_kernel()
- rest_init()
- call: rest_init()
- rcu_scheduler_starring()
- kernel_thread()
- call: kernel_thread()
- do_fork()
- call: do_fork()
- copy_process()
- call: copy_process()
// ARM10C 20160827
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, NULL, trace: 0
static struct task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start,
unsigned long stack_size,
int __user *child_tidptr,
struct pid *pid,
int trace)
{
int retval;
struct task_struct *p;
// clone_flags: 0x00800B00, CLONE_NEWNS: 0x00020000, CLONE_FS: 0x00000200
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL);
// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_FS: 0x00000200
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
return ERR_PTR(-EINVAL);
/*
* Thread groups must share signals as well, and detached threads
* can only be started up within the thread group.
*/
// clone_flags: 0x00800B00, CLONE_THREAD: 0x00010000, CLONE_SIGHAND: 0x00000800
if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
return ERR_PTR(-EINVAL);
/*
* Shared signal handlers imply shared VM. By way of the above,
* thread groups also imply shared VM. Blocking this case allows
* for various simplifications in other code.
*/
// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800, CLONE_VM: 0x00000100
if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
return ERR_PTR(-EINVAL);
// 2016/08/27 종료
// 2016/09/03 시작
/*
* Siblings of global init remain as zombies on exit since they are
* not reaped by their parent (swapper). To solve this and to avoid
* multi-rooted process trees, prevent global and container-inits
* from creating siblings.
*/
// clone_flags: 0x00800B00, CLONE_PARENT: 0x00008000, SIGNAL_UNKILLABLE: 0x00000040
// current: &init_task, current->signal: &init_signals
// current->signal->flags: (&init_signals)->flags: 0
if ((clone_flags & CLONE_PARENT) &&
current->signal->flags & SIGNAL_UNKILLABLE)
return ERR_PTR(-EINVAL);
/*
* If the new process will be in a different pid or user namespace
* do not allow it to share a thread group or signal handlers or
* parent with the forking task.
*/
// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800
if (clone_flags & CLONE_SIGHAND) {
// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_NEWPID: 0x20000000
// current: &init_task, task_active_pid_ns(&init_task): &init_pid_ns,
// current->nsproxy: (&init_task)->nsproxy: &init_nsproxy,
// current->nsproxy->pid_ns_for_children: (&init_nsproxy)->pid_ns_for_children: &init_pid_ns
if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
(task_active_pid_ns(current) !=
current->nsproxy->pid_ns_for_children))
return ERR_PTR(-EINVAL);
}
// clone_flags: 0x00800B00, security_task_create(0x00800B00): 0
retval = security_task_create(clone_flags);
// retval: 0
// retval: 0
if (retval)
goto fork_out;
// ENOMEM: 12
retval = -ENOMEM;
// retval: -12
// current: &init_task
// dup_task_struct(&init_task): kmem_cache#15-oX (struct task_struct)
p = dup_task_struct(current);
// p: kmem_cache#15-oX (struct task_struct)
// dup_task_struct 에서 한일:
// struct task_struct 만큼의 메모리를 할당 받음
// kmem_cache#15-oX (struct task_struct)
//
// struct thread_info 를 구성 하기 위한 메모리를 할당 받음 (8K)
// 할당 받은 page 2개의 메로리의 가상 주소
//
// 할당 받은 kmem_cache#15-oX (struct task_struct) 메모리에 init_task 값을 전부 할당함
//
// (kmem_cache#15-oX (struct task_struct))->stack: 할당 받은 page 2개의 메로리의 가상 주소
//
// 할당 받은 kmem_cache#15-oX (struct task_struct) 의 stack의 값을 init_task 의 stack 값에서 전부 복사함
// 복사된 struct thread_info 의 task 주소값을 할당 받은 kmem_cache#15-oX (struct task_struct)로 변경함
// *(할당 받은 page 2개의 메로리의 가상 주소): init_thread_info
// ((struct thread_info *) 할당 받은 page 2개의 메로리의 가상 주소)->task: kmem_cache#15-oX (struct task_struct)
//
// (((struct thread_info *)(할당 받은 page 2개의 메로리의 가상 주소))->flags 의 1 bit 값을 clear 수행
//
// *((unsigned long *)(할당 받은 page 2개의 메로리의 가상 주소 + 1)): 0x57AC6E9D
//
// (&(kmem_cache#15-oX (struct task_struct))->usage)->counter: 2
// (kmem_cache#15-oX (struct task_struct))->splice_pipe: NULL
// (kmem_cache#15-oX (struct task_struct))->task_frag.page: NULL
//
// (&contig_page_data)->node_zones[0].vm_stat[16]: 1 을 더함
// vmstat.c의 vm_stat[16] 전역 변수에도 1을 더함
// p: kmem_cache#15-oX (struct task_struct)
if (!p)
goto fork_out;
// p: kmem_cache#15-oX (struct task_struct)
ftrace_graph_init_task(p); // null function
// p: kmem_cache#15-oX (struct task_struct)
get_seccomp_filter(p); // null function
// p: kmem_cache#15-oX (struct task_struct)
rt_mutex_init_task(p);
// rt_mutex_init_task 한일:
// &(kmem_cache#15-oX (struct task_struct))->pi_lock을 사용한 spinlock 초기화
// &(kmem_cache#15-oX (struct task_struct))->pi_waiters 리스트 초기화
// (kmem_cache#15-oX (struct task_struct))->pi_blocked_on: NULL
#ifdef CONFIG_PROVE_LOCKING // CONFIG_PROVE_LOCKING=n
DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif
// EAGAIN: 11
retval = -EAGAIN;
// retval: -11
// p: kmem_cache#15-oX (struct task_struct)
// p->real_cred: (kmem_cache#15-oX (struct task_struct))->real_cred: &init_cred,
// p->real_cred->user: (&init_cred)->user: &root_user,
// &p->real_cred->user->processes: &(&root_user)->processes, atomic_read(&(&root_user)->processes): 1
// RLIMIT_NPROC: 6, task_rlimit(kmem_cache#15-oX (struct task_struct), 6): 0
if (atomic_read(&p->real_cred->user->processes) >=
task_rlimit(p, RLIMIT_NPROC)) {
// p->real_cred->user: (&init_cred)->user: &root_user, INIT_USER: (&root_user)
// CAP_SYS_RESOURCE: 24, capable(24): true, CAP_SYS_ADMIN: 21, capable(21): true
if (p->real_cred->user != INIT_USER &&
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
goto bad_fork_free;
// capable 에서 한일:
// (&init_task)->flags: 0x00200100
}
// current->flags: (&init_task)->flags: 0x00200100, PF_NPROC_EXCEEDED: 0x00001000
current->flags &= ~PF_NPROC_EXCEEDED;
// current->flags: (&init_task)->flags: 0x00200100
// retval: -11, p: kmem_cache#15-oX (struct task_struct), clone_flags: 0x00800B00
// copy_creds(kmem_cache#15-oX (struct task_struct), 0x00800B00): 0
retval = copy_creds(p, clone_flags);
// retval: 0
// copy_creds 에서 한일:
// struct cred 만큼의 메모리를 할당 받음
// kmem_cache#16-oX (struct cred)
//
// kmem_cache#16-oX (struct cred) 에 init_cred 에 있는 맴버값 전부를 복사함
// (&(kmem_cache#16-oX (struct cred))->usage)->counter: 1
// (&(&init_groups)->usage)->counter: 3
// (&(&root_user)->__count)->counter: 2
// (&(&root_user)->processes)->counter: 2
//
// (&(kmem_cache#16-oX (struct cred))->usage)->counter: 2
//
// (kmem_cache#15-oX (struct task_struct))->cred: kmem_cache#16-oX (struct cred)
// (kmem_cache#15-oX (struct task_struct))->real_cred: kmem_cache#16-oX (struct cred)
// retval: 0
if (retval < 0)
goto bad_fork_free;
/*
* If multiple threads are within copy_process(), then this check
* triggers too late. This doesn't hurt, the check is only there
* to stop root fork bombs.
*/
// EAGAIN: 11
retval = -EAGAIN;
// retval: -11
// nr_threads: 0, max_threads: 총 free된 page 수 / 16
if (nr_threads >= max_threads)
goto bad_fork_cleanup_count;
// p: kmem_cache#15-oX (struct task_struct),
// task_thread_info(kmem_cache#15-oX (struct task_struct)):
// (kmem_cache#15-oX (struct task_struct))->stack: 할당 받은 page 2개의 메로리의 가상 주소,
// task_thread_info(kmem_cache#15-oX (struct task_struct)->exec_domain:
// ((struct thread_info *) 할당 받은 page 2개의 메로리의 가상 주소)->exec_domain: &default_exec_domain,
// task_thread_info(kmem_cache#15-oX (struct task_struct)->exec_domain->module:
// (&default_exec_domain)->module: NULL,
// try_module_get(NULL): true
if (!try_module_get(task_thread_info(p)->exec_domain->module))
goto bad_fork_cleanup_count;
// p->did_exec: (kmem_cache#15-oX (struct task_struct))->did_exec
p->did_exec = 0;
// p->did_exec: (kmem_cache#15-oX (struct task_struct))->did_exec: 0
// p: kmem_cache#15-oX (struct task_struct)
delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ // null function
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
copy_flags(clone_flags, p);
// copy_flags 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->flags: 0x00200040
// &p->children: &(kmem_cache#15-oX (struct task_struct))->children
INIT_LIST_HEAD(&p->children);
// INIT_LIST_HEAD 에서 한일:
// (&(kmem_cache#15-oX (struct task_struct))->children)->next: &(kmem_cache#15-oX (struct task_struct))->children
// (&(kmem_cache#15-oX (struct task_struct))->children)->prev: &(kmem_cache#15-oX (struct task_struct))->children
// &p->sibling: &(kmem_cache#15-oX (struct task_struct))->sibling
INIT_LIST_HEAD(&p->sibling);
// INIT_LIST_HEAD 에서 한일:
// (&(kmem_cache#15-oX (struct task_struct))->sibling)->next: &(kmem_cache#15-oX (struct task_struct))->sibling
// (&(kmem_cache#15-oX (struct task_struct))->sibling)->prev: &(kmem_cache#15-oX (struct task_struct))->sibling
// p: kmem_cache#15-oX (struct task_struct)
rcu_copy_process(p);
// rcu_copy_process 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->rcu_read_lock_nesting: 0
// (kmem_cache#15-oX (struct task_struct))->rcu_read_unlock_special: 0
// (kmem_cache#15-oX (struct task_struct))->rcu_blocked_node: NULL
// (&(kmem_cache#15-oX (struct task_struct))->rcu_node_entry)->next: &(kmem_cache#15-oX (struct task_struct))->rcu_node_entry
// (&(kmem_cache#15-oX (struct task_struct))->rcu_node_entry)->prev: &(kmem_cache#15-oX (struct task_struct))->rcu_node_entry
// p->vfork_done: (kmem_cache#15-oX (struct task_struct))->vfork_done
p->vfork_done = NULL;
// p->vfork_done: (kmem_cache#15-oX (struct task_struct))->vfork_done: NULL
// &p->alloc_lock: &(kmem_cache#15-oX (struct task_struct))->alloc_lock
spin_lock_init(&p->alloc_lock);
// spin_lock_init에서 한일:
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->raw_lock: { { 0 } }
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->magic: 0xdead4ead
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->owner: 0xffffffff
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->owner_cpu: 0xffffffff
// &p->pending: &(kmem_cache#15-oX (struct task_struct))->pending
init_sigpending(&p->pending);
// init_sigpending 에서 한일:
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->signal)->sig[0]: 0
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->signal)->sig[1]: 0
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->list)->next: &(&(kmem_cache#15-oX (struct task_struct))->pending)->list
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->list)->prev: &(&(kmem_cache#15-oX (struct task_struct))->pending)->list
// p->utime: (kmem_cache#15-oX (struct task_struct))->utime,
// p->stime: (kmem_cache#15-oX (struct task_struct))->stime,
// p->gtime: (kmem_cache#15-oX (struct task_struct))->gtime
p->utime = p->stime = p->gtime = 0;
// p->utime: (kmem_cache#15-oX (struct task_struct))->utime: 0
// p->stime: (kmem_cache#15-oX (struct task_struct))->stime: 0
// p->gtime: (kmem_cache#15-oX (struct task_struct))->gtime: 0
// p->utimescaled: (kmem_cache#15-oX (struct task_struct))->utimescaled,
// p->stimescaled: (kmem_cache#15-oX (struct task_struct))->stimescaled
p->utimescaled = p->stimescaled = 0;
// p->utimescaled: (kmem_cache#15-oX (struct task_struct))->utimescaled: 0
// p->stimescaled: (kmem_cache#15-oX (struct task_struct))->stimescaled: 0
#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE // CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=n
p->prev_cputime.utime = p->prev_cputime.stime = 0;
#endif
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN // CONFIG_VIRT_CPU_ACCOUNTING_GEN=n
seqlock_init(&p->vtime_seqlock);
p->vtime_snap = 0;
p->vtime_snap_whence = VTIME_SLEEPING;
#endif
#if defined(SPLIT_RSS_COUNTING)
// &p->rss_stat: &(kmem_cache#15-oX (struct task_struct))->rss_stat
memset(&p->rss_stat, 0, sizeof(p->rss_stat));
// memset 에서 한일:
// &(kmem_cache#15-oX (struct task_struct))->rss_stat 값을 0 으로 초기화 수행
#endif
// p->default_timer_slack_ns: (kmem_cache#15-oX (struct task_struct))->default_timer_slack_ns,
// current->timer_slack_ns: (&init_task)->timer_slack_ns: 50000
p->default_timer_slack_ns = current->timer_slack_ns;
// p->default_timer_slack_ns: (kmem_cache#15-oX (struct task_struct))->default_timer_slack_ns: 50000
// p->ioac: (kmem_cache#15-oX (struct task_struct))->ioac
task_io_accounting_init(&p->ioac); // null function
// p: kmem_cache#15-oX (struct task_struct)
acct_clear_integrals(p); // null function
// p: kmem_cache#15-oX (struct task_struct)
posix_cpu_timers_init(p);
// posix_cpu_timers_init 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->cputime_expires.prof_exp: 0
// (kmem_cache#15-oX (struct task_struct))->cputime_expires.virt_exp: 0
// (kmem_cache#15-oX (struct task_struct))->cputime_expires.sched_exp: 0
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[0])->next: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[0]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[0])->prev: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[0]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[1])->next: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[1]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[1])->prev: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[1]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[2])->next: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[2]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[2])->prev: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[2]
// &p->start_time: &(kmem_cache#15-oX (struct task_struct))->start_time
do_posix_clock_monotonic_gettime(&p->start_time);
// do_posix_clock_monotonic_gettime 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->start_time 에 현재 시간 값을 가져옴
//
// (&(kmem_cache#15-oX (struct task_struct))->start_time)->tv_sec: 현재의 sec 값 + 현재의 nsec 값 / 1000000000L
// (&(kmem_cache#15-oX (struct task_struct))->start_time)->tv_nsec: 현재의 nsec 값 % 1000000000L
// p->real_start_time: (kmem_cache#15-oX (struct task_struct))->real_start_time,
// p->start_time: (kmem_cache#15-oX (struct task_struct))->start_time
p->real_start_time = p->start_time;
// (&(kmem_cache#15-oX (struct task_struct))->real_start_time)->tv_sec: 현재의 sec 값 + 현재의 nsec 값 / 1000000000L
// (&(kmem_cache#15-oX (struct task_struct))->real_start_time)->tv_nsec: 현재의 nsec 값 % 1000000000L
// &p->real_start_time: &(kmem_cache#15-oX (struct task_struct))->real_start_time
monotonic_to_bootbased(&p->real_start_time);
// monotonic_to_bootbased 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->real_start_time.tv_sec: normalized 된 sec 값
// (kmem_cache#15-oX (struct task_struct))->real_start_time.tv_nsec: normalized 된 nsec 값
// p->io_context: (kmem_cache#15-oX (struct task_struct))->io_context
p->io_context = NULL;
// p->io_context: (kmem_cache#15-oX (struct task_struct))->io_context: NULL
// p->audit_context: (kmem_cache#15-oX (struct task_struct))->audit_context
p->audit_context = NULL;
// p->audit_context: (kmem_cache#15-oX (struct task_struct))->audit_context: NULL
if (clone_flags & CLONE_THREAD)
threadgroup_change_begin(current);
cgroup_fork(p);
- start_kernel()
- rest_init()
- call: rest_init()
- rcu_scheduler_starting()
- kernel_thread()
- call: kernel_thread()
- do_fork()
- call: do_fork()
- copy_process()
// ARM10C 20160827
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, NULL, trace: 0
static struct task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start,
unsigned long stack_size,
int __user *child_tidptr,
struct pid *pid,
int trace)
{
int retval;
struct task_struct *p;
// clone_flags: 0x00800B00, CLONE_NEWNS: 0x00020000, CLONE_FS: 0x00000200
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL);
// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_FS: 0x00000200
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
return ERR_PTR(-EINVAL);
/*
* Thread groups must share signals as well, and detached threads
* can only be started up within the thread group.
*/
// clone_flags: 0x00800B00, CLONE_THREAD: 0x00010000, CLONE_SIGHAND: 0x00000800
if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
return ERR_PTR(-EINVAL);
/*
* Shared signal handlers imply shared VM. By way of the above,
* thread groups also imply shared VM. Blocking this case allows
* for various simplifications in other code.
*/
// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800, CLONE_VM: 0x00000100
if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
return ERR_PTR(-EINVAL);
// 2016/08/27 종료
// 2016/09/03 시작
/*
* Siblings of global init remain as zombies on exit since they are
* not reaped by their parent (swapper). To solve this and to avoid
* multi-rooted process trees, prevent global and container-inits
* from creating siblings.
*/
// clone_flags: 0x00800B00, CLONE_PARENT: 0x00008000, SIGNAL_UNKILLABLE: 0x00000040
// current: &init_task, current->signal: &init_signals
// current->signal->flags: (&init_signals)->flags: 0
if ((clone_flags & CLONE_PARENT) &&
current->signal->flags & SIGNAL_UNKILLABLE)
return ERR_PTR(-EINVAL);
/*
* If the new process will be in a different pid or user namespace
* do not allow it to share a thread group or signal handlers or
* parent with the forking task.
*/
// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800
if (clone_flags & CLONE_SIGHAND) {
// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_NEWPID: 0x20000000
// current: &init_task, task_active_pid_ns(&init_task): &init_pid_ns,
// current->nsproxy: (&init_task)->nsproxy: &init_nsproxy,
// current->nsproxy->pid_ns_for_children: (&init_nsproxy)->pid_ns_for_children: &init_pid_ns
if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
(task_active_pid_ns(current) !=
current->nsproxy->pid_ns_for_children))
return ERR_PTR(-EINVAL);
}
// clone_flags: 0x00800B00, security_task_create(0x00800B00): 0
retval = security_task_create(clone_flags);
// retval: 0
// retval: 0
if (retval)
goto fork_out;
// ENOMEM: 12
retval = -ENOMEM;
// retval: -12
// current: &init_task
// dup_task_struct(&init_task): kmem_cache#15-oX (struct task_struct)
p = dup_task_struct(current);
// p: kmem_cache#15-oX (struct task_struct)
// dup_task_struct 에서 한일:
// struct task_struct 만큼의 메모리를 할당 받음
// kmem_cache#15-oX (struct task_struct)
//
// struct thread_info 를 구성 하기 위한 메모리를 할당 받음 (8K)
// 할당 받은 page 2개의 메로리의 가상 주소
//
// 할당 받은 kmem_cache#15-oX (struct task_struct) 메모리에 init_task 값을 전부 할당함
//
// (kmem_cache#15-oX (struct task_struct))->stack: 할당 받은 page 2개의 메로리의 가상 주소
//
// 할당 받은 kmem_cache#15-oX (struct task_struct) 의 stack의 값을 init_task 의 stack 값에서 전부 복사함
// 복사된 struct thread_info 의 task 주소값을 할당 받은 kmem_cache#15-oX (struct task_struct)로 변경함
// *(할당 받은 page 2개의 메로리의 가상 주소): init_thread_info
// ((struct thread_info *) 할당 받은 page 2개의 메로리의 가상 주소)->task: kmem_cache#15-oX (struct task_struct)
//
// (((struct thread_info *)(할당 받은 page 2개의 메로리의 가상 주소))->flags 의 1 bit 값을 clear 수행
//
// *((unsigned long *)(할당 받은 page 2개의 메로리의 가상 주소 + 1)): 0x57AC6E9D
//
// (&(kmem_cache#15-oX (struct task_struct))->usage)->counter: 2
// (kmem_cache#15-oX (struct task_struct))->splice_pipe: NULL
// (kmem_cache#15-oX (struct task_struct))->task_frag.page: NULL
//
// (&contig_page_data)->node_zones[0].vm_stat[16]: 1 을 더함
// vmstat.c의 vm_stat[16] 전역 변수에도 1을 더함
// p: kmem_cache#15-oX (struct task_struct)
if (!p)
goto fork_out;
// p: kmem_cache#15-oX (struct task_struct)
ftrace_graph_init_task(p); // null function
// p: kmem_cache#15-oX (struct task_struct)
get_seccomp_filter(p); // null function
// p: kmem_cache#15-oX (struct task_struct)
rt_mutex_init_task(p);
// rt_mutex_init_task 한일:
// &(kmem_cache#15-oX (struct task_struct))->pi_lock을 사용한 spinlock 초기화
// &(kmem_cache#15-oX (struct task_struct))->pi_waiters 리스트 초기화
// (kmem_cache#15-oX (struct task_struct))->pi_blocked_on: NULL
#ifdef CONFIG_PROVE_LOCKING // CONFIG_PROVE_LOCKING=n
DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif
// EAGAIN: 11
retval = -EAGAIN;
// retval: -11
// p: kmem_cache#15-oX (struct task_struct)
// p->real_cred: (kmem_cache#15-oX (struct task_struct))->real_cred: &init_cred,
// p->real_cred->user: (&init_cred)->user: &root_user,
// &p->real_cred->user->processes: &(&root_user)->processes, atomic_read(&(&root_user)->processes): 1
// RLIMIT_NPROC: 6, task_rlimit(kmem_cache#15-oX (struct task_struct), 6): 0
if (atomic_read(&p->real_cred->user->processes) >=
task_rlimit(p, RLIMIT_NPROC)) {
// p->real_cred->user: (&init_cred)->user: &root_user, INIT_USER: (&root_user)
// CAP_SYS_RESOURCE: 24, capable(24): true, CAP_SYS_ADMIN: 21, capable(21): true
if (p->real_cred->user != INIT_USER &&
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
goto bad_fork_free;
// capable 에서 한일:
// (&init_task)->flags: 0x00200100
}
// current->flags: (&init_task)->flags: 0x00200100, PF_NPROC_EXCEEDED: 0x00001000
current->flags &= ~PF_NPROC_EXCEEDED;
// current->flags: (&init_task)->flags: 0x00200100
// retval: -11, p: kmem_cache#15-oX (struct task_struct), clone_flags: 0x00800B00
// copy_creds(kmem_cache#15-oX (struct task_struct), 0x00800B00): 0
retval = copy_creds(p, clone_flags);
// retval: 0
// copy_creds 에서 한일:
// struct cred 만큼의 메모리를 할당 받음
// kmem_cache#16-oX (struct cred)
//
// kmem_cache#16-oX (struct cred) 에 init_cred 에 있는 맴버값 전부를 복사함
// (&(kmem_cache#16-oX (struct cred))->usage)->counter: 1
// (&(&init_groups)->usage)->counter: 3
// (&(&root_user)->__count)->counter: 2
// (&(&root_user)->processes)->counter: 2
//
// (&(kmem_cache#16-oX (struct cred))->usage)->counter: 2
//
// (kmem_cache#15-oX (struct task_struct))->cred: kmem_cache#16-oX (struct cred)
// (kmem_cache#15-oX (struct task_struct))->real_cred: kmem_cache#16-oX (struct cred)
// retval: 0
if (retval < 0)
goto bad_fork_free;
/*
* If multiple threads are within copy_process(), then this check
* triggers too late. This doesn't hurt, the check is only there
* to stop root fork bombs.
*/
// EAGAIN: 11
retval = -EAGAIN;
// retval: -11
// nr_threads: 0, max_threads: 총 free된 page 수 / 16
if (nr_threads >= max_threads)
goto bad_fork_cleanup_count;
// p: kmem_cache#15-oX (struct task_struct),
// task_thread_info(kmem_cache#15-oX (struct task_struct)):
// (kmem_cache#15-oX (struct task_struct))->stack: 할당 받은 page 2개의 메로리의 가상 주소,
// task_thread_info(kmem_cache#15-oX (struct task_struct)->exec_domain:
// ((struct thread_info *) 할당 받은 page 2개의 메로리의 가상 주소)->exec_domain: &default_exec_domain,
// task_thread_info(kmem_cache#15-oX (struct task_struct)->exec_domain->module:
// (&default_exec_domain)->module: NULL,
// try_module_get(NULL): true
if (!try_module_get(task_thread_info(p)->exec_domain->module))
goto bad_fork_cleanup_count;
// p->did_exec: (kmem_cache#15-oX (struct task_struct))->did_exec
p->did_exec = 0;
// p->did_exec: (kmem_cache#15-oX (struct task_struct))->did_exec: 0
// p: kmem_cache#15-oX (struct task_struct)
delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ // null function
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
copy_flags(clone_flags, p);
// copy_flags 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->flags: 0x00200040
// &p->children: &(kmem_cache#15-oX (struct task_struct))->children
INIT_LIST_HEAD(&p->children);
// INIT_LIST_HEAD 에서 한일:
// (&(kmem_cache#15-oX (struct task_struct))->children)->next: &(kmem_cache#15-oX (struct task_struct))->children
// (&(kmem_cache#15-oX (struct task_struct))->children)->prev: &(kmem_cache#15-oX (struct task_struct))->children
// &p->sibling: &(kmem_cache#15-oX (struct task_struct))->sibling
INIT_LIST_HEAD(&p->sibling);
// INIT_LIST_HEAD 에서 한일:
// (&(kmem_cache#15-oX (struct task_struct))->sibling)->next: &(kmem_cache#15-oX (struct task_struct))->sibling
// (&(kmem_cache#15-oX (struct task_struct))->sibling)->prev: &(kmem_cache#15-oX (struct task_struct))->sibling
// p: kmem_cache#15-oX (struct task_struct)
rcu_copy_process(p);
// rcu_copy_process 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->rcu_read_lock_nesting: 0
// (kmem_cache#15-oX (struct task_struct))->rcu_read_unlock_special: 0
// (kmem_cache#15-oX (struct task_struct))->rcu_blocked_node: NULL
// (&(kmem_cache#15-oX (struct task_struct))->rcu_node_entry)->next: &(kmem_cache#15-oX (struct task_struct))->rcu_node_entry
// (&(kmem_cache#15-oX (struct task_struct))->rcu_node_entry)->prev: &(kmem_cache#15-oX (struct task_struct))->rcu_node_entry
// p->vfork_done: (kmem_cache#15-oX (struct task_struct))->vfork_done
p->vfork_done = NULL;
// p->vfork_done: (kmem_cache#15-oX (struct task_struct))->vfork_done: NULL
// &p->alloc_lock: &(kmem_cache#15-oX (struct task_struct))->alloc_lock
spin_lock_init(&p->alloc_lock);
// spin_lock_init에서 한일:
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->raw_lock: { { 0 } }
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->magic: 0xdead4ead
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->owner: 0xffffffff
// (&(kmem_cache#15-oX (struct task_struct))->alloc_lock)->owner_cpu: 0xffffffff
// &p->pending: &(kmem_cache#15-oX (struct task_struct))->pending
init_sigpending(&p->pending);
// init_sigpending 에서 한일:
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->signal)->sig[0]: 0
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->signal)->sig[1]: 0
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->list)->next: &(&(kmem_cache#15-oX (struct task_struct))->pending)->list
// (&(&(kmem_cache#15-oX (struct task_struct))->pending)->list)->prev: &(&(kmem_cache#15-oX (struct task_struct))->pending)->list
// p->utime: (kmem_cache#15-oX (struct task_struct))->utime,
// p->stime: (kmem_cache#15-oX (struct task_struct))->stime,
// p->gtime: (kmem_cache#15-oX (struct task_struct))->gtime
p->utime = p->stime = p->gtime = 0;
// p->utime: (kmem_cache#15-oX (struct task_struct))->utime: 0
// p->stime: (kmem_cache#15-oX (struct task_struct))->stime: 0
// p->gtime: (kmem_cache#15-oX (struct task_struct))->gtime: 0
// p->utimescaled: (kmem_cache#15-oX (struct task_struct))->utimescaled,
// p->stimescaled: (kmem_cache#15-oX (struct task_struct))->stimescaled
p->utimescaled = p->stimescaled = 0;
// p->utimescaled: (kmem_cache#15-oX (struct task_struct))->utimescaled: 0
// p->stimescaled: (kmem_cache#15-oX (struct task_struct))->stimescaled: 0
#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE // CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=n
p->prev_cputime.utime = p->prev_cputime.stime = 0;
#endif
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN // CONFIG_VIRT_CPU_ACCOUNTING_GEN=n
seqlock_init(&p->vtime_seqlock);
p->vtime_snap = 0;
p->vtime_snap_whence = VTIME_SLEEPING;
#endif
#if defined(SPLIT_RSS_COUNTING)
// &p->rss_stat: &(kmem_cache#15-oX (struct task_struct))->rss_stat
memset(&p->rss_stat, 0, sizeof(p->rss_stat));
// memset 에서 한일:
// &(kmem_cache#15-oX (struct task_struct))->rss_stat 값을 0 으로 초기화 수행
#endif
// p->default_timer_slack_ns: (kmem_cache#15-oX (struct task_struct))->default_timer_slack_ns,
// current->timer_slack_ns: (&init_task)->timer_slack_ns: 50000
p->default_timer_slack_ns = current->timer_slack_ns;
// p->default_timer_slack_ns: (kmem_cache#15-oX (struct task_struct))->default_timer_slack_ns: 50000
// p->ioac: (kmem_cache#15-oX (struct task_struct))->ioac
task_io_accounting_init(&p->ioac); // null function
// p: kmem_cache#15-oX (struct task_struct)
acct_clear_integrals(p); // null function
// p: kmem_cache#15-oX (struct task_struct)
posix_cpu_timers_init(p);
// posix_cpu_timers_init 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->cputime_expires.prof_exp: 0
// (kmem_cache#15-oX (struct task_struct))->cputime_expires.virt_exp: 0
// (kmem_cache#15-oX (struct task_struct))->cputime_expires.sched_exp: 0
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[0])->next: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[0]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[0])->prev: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[0]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[1])->next: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[1]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[1])->prev: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[1]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[2])->next: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[2]
// (&(kmem_cache#15-oX (struct task_struct))->cpu_timers[2])->prev: &(kmem_cache#15-oX (struct task_struct))->cpu_timers[2]
// &p->start_time: &(kmem_cache#15-oX (struct task_struct))->start_time
do_posix_clock_monotonic_gettime(&p->start_time);
// do_posix_clock_monotonic_gettime 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->start_time 에 현재 시간 값을 가져옴
//
// (&(kmem_cache#15-oX (struct task_struct))->start_time)->tv_sec: 현재의 sec 값 + 현재의 nsec 값 / 1000000000L
// (&(kmem_cache#15-oX (struct task_struct))->start_time)->tv_nsec: 현재의 nsec 값 % 1000000000L
// p->real_start_time: (kmem_cache#15-oX (struct task_struct))->real_start_time,
// p->start_time: (kmem_cache#15-oX (struct task_struct))->start_time
p->real_start_time = p->start_time;
// (&(kmem_cache#15-oX (struct task_struct))->real_start_time)->tv_sec: 현재의 sec 값 + 현재의 nsec 값 / 1000000000L
// (&(kmem_cache#15-oX (struct task_struct))->real_start_time)->tv_nsec: 현재의 nsec 값 % 1000000000L
// &p->real_start_time: &(kmem_cache#15-oX (struct task_struct))->real_start_time
monotonic_to_bootbased(&p->real_start_time);
// monotonic_to_bootbased 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->real_start_time.tv_sec: normalized 된 sec 값
// (kmem_cache#15-oX (struct task_struct))->real_start_time.tv_nsec: normalized 된 nsec 값
// p->io_context: (kmem_cache#15-oX (struct task_struct))->io_context
p->io_context = NULL;
// p->io_context: (kmem_cache#15-oX (struct task_struct))->io_context: NULL
// p->audit_context: (kmem_cache#15-oX (struct task_struct))->audit_context
p->audit_context = NULL;
// p->audit_context: (kmem_cache#15-oX (struct task_struct))->audit_context: NULL
// 2016/09/10 종료
// 2016/10/08 시작
// clone_flags: 0x00800B00, CLONE_THREAD: 0x00010000
if (clone_flags & CLONE_THREAD)
threadgroup_change_begin(current);
// p: kmem_cache#15-oX (struct task_struct)
cgroup_fork(p);
// cgroup_fork 에서 한일:
// rcu reference의 값 (&init_task)->cgroups 이 유요한지 체크하고 그 값을 리턴함
// ((&init_task)->cgroups)->refcount: 1
// (kmem_cache#15-oX (struct task_struct))->cgroups: (&init_task)->cgroups
//
// (&(kmem_cache#15-oX (struct task_struct))->cg_list)->next: &(kmem_cache#15-oX (struct task_struct))->cg_list
// (&(kmem_cache#15-oX (struct task_struct))->cg_list)->prev: &(kmem_cache#15-oX (struct task_struct))->cg_list
#ifdef CONFIG_NUMA // CONFIG_NUMA=n
p->mempolicy = mpol_dup(p->mempolicy);
if (IS_ERR(p->mempolicy)) {
retval = PTR_ERR(p->mempolicy);
p->mempolicy = NULL;
goto bad_fork_cleanup_cgroup;
}
mpol_fix_fork_child_flag(p);
#endif
#ifdef CONFIG_CPUSETS // CONFIG_CPUSETS=n
p->cpuset_mem_spread_rotor = NUMA_NO_NODE;
p->cpuset_slab_spread_rotor = NUMA_NO_NODE;
seqcount_init(&p->mems_allowed_seq);
#endif
#ifdef CONFIG_TRACE_IRQFLAGS // CONFIG_TRACE_IRQFLAGS=n
p->irq_events = 0;
p->hardirqs_enabled = 0;
p->hardirq_enable_ip = 0;
p->hardirq_enable_event = 0;
p->hardirq_disable_ip = _THIS_IP_;
p->hardirq_disable_event = 0;
p->softirqs_enabled = 1;
p->softirq_enable_ip = _THIS_IP_;
p->softirq_enable_event = 0;
p->softirq_disable_ip = 0;
p->softirq_disable_event = 0;
p->hardirq_context = 0;
p->softirq_context = 0;
#endif
#ifdef CONFIG_LOCKDEP // CONFIG_LOCKDEP=n
p->lockdep_depth = 0; /* no locks held yet */
p->curr_chain_key = 0;
p->lockdep_recursion = 0;
#endif
#ifdef CONFIG_DEBUG_MUTEXES // CONFIG_DEBUG_MUTEXES=y
// p->blocked_on: (kmem_cache#15-oX (struct task_struct))->blocked_on
p->blocked_on = NULL; /* not blocked yet */
// p->blocked_on: (kmem_cache#15-oX (struct task_struct))->blocked_on: NULL
#endif
#ifdef CONFIG_MEMCG // CONFIG_MEMCG=n
p->memcg_batch.do_batch = 0;
p->memcg_batch.memcg = NULL;
#endif
#ifdef CONFIG_BCACHE // CONFIG_BCACHE=n
p->sequential_io = 0;
p->sequential_io_avg = 0;
#endif
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
sched_fork(clone_flags, p);
// sched_fork 에서 한일:
// (&kmem_cache#15-oX (struct task_struct))->on_rq: 0
// (&kmem_cache#15-oX (struct task_struct))->se.on_rq: 0
// (&kmem_cache#15-oX (struct task_struct))->se.exec_start: 0
// (&kmem_cache#15-oX (struct task_struct))->se.sum_exec_runtime: 0
// (&kmem_cache#15-oX (struct task_struct))->se.prev_sum_exec_runtime: 0
// (&kmem_cache#15-oX (struct task_struct))->se.nr_migrations: 0
// (&kmem_cache#15-oX (struct task_struct))->se.vruntime: 0
// &(&kmem_cache#15-oX (struct task_struct))->se.group_node의 리스트 초기화
// &(&kmem_cache#15-oX (struct task_struct))->rt.run_list의 리스트 초기화
//
// (kmem_cache#15-oX (struct task_struct))->state: 0
// (kmem_cache#15-oX (struct task_struct))->prio: 120
// (kmem_cache#15-oX (struct task_struct))->sched_class: &fair_sched_class
//
// 현재의 schedule 시간값과 기존의 (&runqueues)->clock 의 값의 차이값을
// [pcp0] (&runqueues)->clock, [pcp0] (&runqueues)->clock_task 의 값에 더해 갱신함
//
// [pcp0] (&runqueues)->clock: schedule 시간 차이값
// [pcp0] (&runqueues)->clock_task: schedule 시간 차이값
//
// (kmem_cache#15-oX (struct task_struct))->se.cfs_rq: [pcp0] &(&runqueues)->cfs
// (kmem_cache#15-oX (struct task_struct))->se.parent: NULL
// (kmem_cache#15-oX (struct task_struct))->rt.rt_rq: [pcp0] &(&runqueues)->rt
// (kmem_cache#15-oX (struct task_struct))->rt.parent: NULL
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu: 0
// (kmem_cache#15-oX (struct task_struct))->wake_cpu: 0
// (&(kmem_cache#15-oX (struct task_struct))->se)->vruntime: 0x5B8D7E
// (kmem_cache#15-oX (struct task_struct))->se.cfs_rq: [pcp0] &(&runqueues)->cfs
// (kmem_cache#15-oX (struct task_struct))->se.parent: NULL
// (kmem_cache#15-oX (struct task_struct))->rt.rt_rq: [pcp0] &(&runqueues)->rt
// (kmem_cache#15-oX (struct task_struct))->rt.parent: NULL
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu: 0
// (kmem_cache#15-oX (struct task_struct))->wake_cpu: 0
// (kmem_cache#15-oX (struct task_struct))->on_cpu: 0
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->preempt_count: 1
// (&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->prio: 140
// (&(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->prio_list)->next: &(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->prio_list
// (&(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->prio_list)->prev: &(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->prio_list
// (&(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->node_list)->next: &(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->node_list
// (&(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->node_list)->prev: &(&(kmem_cache#15-oX (struct task_struct))->pushable_tasks)->node_list
// p: kmem_cache#15-oX (struct task_struct)
// perf_event_init_task(kmem_cache#15-oX (struct task_struct)): 0
retval = perf_event_init_task(p); // null function
// retval: 0
// retval: 0
if (retval)
goto bad_fork_cleanup_policy;
// p: kmem_cache#15-oX (struct task_struct)
// audit_alloc(kmem_cache#15-oX (struct task_struct)): 0
retval = audit_alloc(p); // null function
// retval: 0
// retval: 0
if (retval)
goto bad_fork_cleanup_policy;
/* copy all the process information */
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_semundo(kmem_cache#15-oX (struct task_struct)): 0
retval = copy_semundo(clone_flags, p);
// retval: 0
// copy_semundo 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->sysvsem.undo_list: NULL
// retval: 0
if (retval)
goto bad_fork_cleanup_audit;
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_files(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_files(clone_flags, p);
// retval: 0
// copy_files 에서 한일:
// files_cachep: kmem_cache#12 을 사용하여 struct files_struct 을 위한 메모리를 할당함
// kmem_cache#12-oX (struct files_struct)
//
// (kmem_cache#12-oX (struct files_struct))->count: 1
//
// &(kmem_cache#12-oX (struct files_struct))->file_lock을 이용한 spin lock 초기화 수행
// ((&(kmem_cache#12-oX (struct files_struct))->file_lock)->rlock)->raw_lock: { { 0 } }
// ((&(kmem_cache#12-oX (struct files_struct))->file_lock)->rlock)->magic: 0xdead4ead
// ((&(kmem_cache#12-oX (struct files_struct))->file_lock)->rlock)->owner: 0xffffffff
// ((&(kmem_cache#12-oX (struct files_struct))->file_lock)->rlock)->owner_cpu: 0xffffffff
//
// (kmem_cache#12-oX (struct files_struct))->next_fd: 0
// (&(kmem_cache#12-oX (struct files_struct))->fdtab)->max_fds: 32
// (&(kmem_cache#12-oX (struct files_struct))->fdtab)->close_on_exec: (kmem_cache#12-oX (struct files_struct))->close_on_exec_init
// (&(kmem_cache#12-oX (struct files_struct))->fdtab)->open_fds: (kmem_cache#12-oX (struct files_struct))->open_fds_init
// (&(kmem_cache#12-oX (struct files_struct))->fdtab)->fd: &(kmem_cache#12-oX (struct files_struct))->fd_array[0]
//
// &(&init_files)->file_lock 을 사용하여 spin lock 수행
//
// (kmem_cache#12-oX (struct files_struct))->open_fds_init 에 init_files.open_fds_init 값을 복사
// (kmem_cache#12-oX (struct files_struct))->open_fds_init: NULL
// (kmem_cache#12-oX (struct files_struct))->close_on_exec_init 에 init_files.close_on_exec_init 값을 복사
// (kmem_cache#12-oX (struct files_struct))->close_on_exec_init: NULL
//
// (&(kmem_cache#12-oX (struct files_struct))->fdtab)->open_fds 의 0~31 bit 를 clear 함
// (kmem_cache#12-oX (struct files_struct))->fd_array[0...31]: NULL
// &(kmem_cache#12-oX (struct files_struct))->fd_array[0] 에 값을 size 0 만큼 0 으로 set 함
//
// (kmem_cache#12-oX (struct files_struct))->fdt: &(kmem_cache#12-oX (struct files_struct))->fdtab
//
// (kmem_cache#15-oX (struct task_struct))->files: kmem_cache#12-oX (struct files_struct)
// retval: 0
if (retval)
goto bad_fork_cleanup_semundo;
// 2016/10/29 종료
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_fs(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_fs(clone_flags, p);
// retval: 0
// copy_fs 에서 한일:
// (&init_fs)->users: 2
// retval: 0
if (retval)
goto bad_fork_cleanup_files;
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_sighand(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_sighand(clone_flags, p);
// retval: 0
// copy_sighand 에서 한일:
// (&init_sighand)->count: { (2) }
// retval: 0
if (retval)
goto bad_fork_cleanup_fs;
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_signal(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_signal(clone_flags, p);
// retval: 0
// copy_signal 에서 한일:
// struct signal_struct 크기 만큼의 메모리를 할당함
// kmem_cache#13-oX (struct signal_struct)
//
// (kmem_cache#15-oX (struct task_struct))->signal: kmem_cache#13-oX (struct signal_struct)
//
// (kmem_cache#13-oX (struct signal_struct))->nr_threads: 1
// (kmem_cache#13-oX (struct signal_struct))->live: { (1) }
// (kmem_cache#13-oX (struct signal_struct))->sigcnt: { (1) }
// &(&(kmem_cache#13-oX (struct signal_struct))->wait_chldexit)->lock을 사용한 spinlock 초기화
// &(&(kmem_cache#13-oX (struct signal_struct))->wait_chldexit)->task_list를 사용한 list 초기화
//
// (kmem_cache#13-oX (struct signal_struct))->curr_target: kmem_cache#15-oX (struct task_struct)
//
// (&(&(kmem_cache#13-oX (struct signal_struct))->shared_pending)->signal)->sig[0]: 0
// (&(&(kmem_cache#13-oX (struct signal_struct))->shared_pending)->signal)->sig[1]: 0
// (&(&(kmem_cache#13-oX (struct signal_struct))->shared_pending)->list)->next: &(&(kmem_cache#13-oX (struct signal_struct))->shared_pending)->list
// (&(&(kmem_cache#13-oX (struct signal_struct))->shared_pending)->list)->prev: &(&(kmem_cache#13-oX (struct signal_struct))->shared_pending)->list
// (&(kmem_cache#13-oX (struct signal_struct))->posix_timers)->next: &(kmem_cache#13-oX (struct signal_struct))->posix_timers
// (&(kmem_cache#13-oX (struct signal_struct))->posix_timers)->prev: &(kmem_cache#13-oX (struct signal_struct))->posix_timers
//
// (kmem_cache#13-oX (struct signal_struct))->real_timer의 값을 0으로 초기화
// (&(kmem_cache#13-oX (struct signal_struct))->real_timer)->base: [pcp0] &(&hrtimer_bases)->clock_base[0]
// RB Tree의 &(&(kmem_cache#13-oX (struct signal_struct))->real_timer)->node 를 초기화
//
// (kmem_cache#13-oX (struct signal_struct))->real_timer.function: it_real_fn
// (kmem_cache#13-oX (struct signal_struct))->rlim 에 (&init_signals)->rlim 값을 전부 복사함
// &(kmem_cache#13-oX (struct signal_struct))->cputimer.lock 을 사용한 spinlock 초기화 수행
// (&(kmem_cache#13-oX (struct signal_struct))->cpu_timers[0])->next: &(kmem_cache#13-oX (struct signal_struct))->cpu_timers[0]
// (&(kmem_cache#13-oX (struct signal_struct))->cpu_timers[0])->prev: &(kmem_cache#13-oX (struct signal_struct))->cpu_timers[0]
// (&(kmem_cache#13-oX (struct signal_struct))->cpu_timers[1])->next: &(kmem_cache#13-oX (struct signal_struct))->cpu_timers[1]
// (&(kmem_cache#13-oX (struct signal_struct))->cpu_timers[1])->prev: &(kmem_cache#13-oX (struct signal_struct))->cpu_timers[1]
// (&(kmem_cache#13-oX (struct signal_struct))->cpu_timers[2])->next: &(kmem_cache#13-oX (struct signal_struct))->cpu_timers[2]
// (&(kmem_cache#13-oX (struct signal_struct))->cpu_timers[2])->prev: &(kmem_cache#13-oX (struct signal_struct))->cpu_timers[2]
// (&(kmem_cache#13-oX (struct signal_struct))->group_rwsem)->activity: 0
// &(&(kmem_cache#13-oX (struct signal_struct))->group_rwsem)->wait_lock을 사용한 spinlock 초기화
// (&(&(kmem_cache#13-oX (struct signal_struct))->group_rwsem)->wait_list)->next: &(&(kmem_cache#13-oX (struct signal_struct))->group_rwsem)->wait_list
// (&(&(kmem_cache#13-oX (struct signal_struct))->group_rwsem)->wait_list)->prev: &(&(kmem_cache#13-oX (struct signal_struct))->group_rwsem)->wait_list
// (kmem_cache#13-oX (struct signal_struct))->oom_score_adj: 0
// (kmem_cache#13-oX (struct signal_struct))->oom_score_adj_min: 0
// (kmem_cache#13-oX (struct signal_struct))->has_child_subreaper: 0
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->count: 1
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_lock)->rlock)->raw_lock: { { 0 } }
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_lock)->rlock)->magic: 0xdead4ead
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_lock)->rlock)->owner: 0xffffffff
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_lock)->rlock)->owner_cpu: 0xffffffff
// (&(&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_list)->next: &(&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_list
// (&(&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_list)->prev: &(&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->wait_list
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->onwer: NULL
// (&(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex)->magic: &(kmem_cache#13-oX (struct signal_struct))->cred_guard_mutex
// retval: 0
if (retval)
goto bad_fork_cleanup_sighand;
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_mm(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_mm(clone_flags, p);
// retval: 0
// copy_mm 에서 한일:
// (kmem_cache#15-oX (struct task_struct))->min_flt: 0
// (kmem_cache#15-oX (struct task_struct))->maj_flt: 0
// (kmem_cache#15-oX (struct task_struct))->nvcsw: 0
// (kmem_cache#15-oX (struct task_struct))->nivcsw: 0
// (kmem_cache#15-oX (struct task_struct))->last_switch_count: 0
// (kmem_cache#15-oX (struct task_struct))->mm: NULL
// (kmem_cache#15-oX (struct task_struct))->active_mm: NULL
// retval: 0
if (retval)
goto bad_fork_cleanup_signal;
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_namespaces(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_namespaces(clone_flags, p);
// retval: 0
// copy_namespaces 에서 한일:
// (&init_nsproxy)->count: { (2) }
// retval: 0
if (retval)
goto bad_fork_cleanup_mm;
// clone_flags: 0x00800B00, p: kmem_cache#15-oX (struct task_struct)
// copy_io(0x00800B00, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_io(clone_flags, p);
// retval: 0
// retval: 0
if (retval)
goto bad_fork_cleanup_namespaces;
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, p: kmem_cache#15-oX (struct task_struct)
// copy_thread(0x00800B00, kernel_init, 0, kmem_cache#15-oX (struct task_struct)): 0
retval = copy_thread(clone_flags, stack_start, stack_size, p);
// retval: 0
// copy_thread 에서 한일:
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu_context 의 값을 0으로 초기화 함
// ((struct pt_regs *)(kmem_cache#15-oX (struct task_struct))->stack + 8183) 의 값을 0으로 초기화 함
//
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu_context.r4: 0
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu_context.r5: kernel_init
// ((struct pt_regs *)(kmem_cache#15-oX (struct task_struct))->stack + 8183)->uregs[16]: 0x00000013
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu_context.pc: ret_from_fork
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->cpu_context.sp: ((struct pt_regs *)(kmem_cache#15-oX (struct task_struct))->stack + 8183)
// ((struct thread_info *)(kmem_cache#15-oX (struct task_struct))->stack)->tp_value[1]: TPIDRURW의 읽은 값
// retval: 0
if (retval)
goto bad_fork_cleanup_io;
// pid: NULL
if (pid != &init_struct_pid) {
// ENOMEM: 12
retval = -ENOMEM;
// retval: -12
// p->nsproxy: (kmem_cache#15-oX (struct task_struct))->nsproxy: &init_nsproxy
// p->nsproxy->pid_ns_for_children: (&init_nsproxy)->pid_ns_for_children: &init_pid_ns
pid = alloc_pid(p->nsproxy->pid_ns_for_children);
- start_kernel()
- rest_init()
- call: rest_init()
- rcu_scheduler_starting()
- kernel_thread()
- call: kernel_thread()
- do_fork()
- call: do_fork()
- copy_process()
- call: copy_process()
- security_task_create()
- dup_task_struct()
- ftrace_graph_init_task(p); // null function
- get_seccomp_filter(p); // null function
- rt_mutex_init_task(p);
- copy_creds(p, clone_flags);
- try_module_get()
- delayacct_tsk_init(p)
- copy_flags()
- INIT_LIST_HEAD(&p->children);
- INIT_LIST_HEAD(&p->sibling);
- rcu_copy_process(p);
- spin_lock_init(&p->alloc_lock);
- init_sigpending(&p->pending);
- memset(&p->rss_stat, 0, sizeof(p->rss_stat));
- task_io_accounting_init(&p->ioac); // null function
- acct_clear_integrals(p); // null function
- posix_cpu_timers_init(p);
- do_posix_clock_monotonic_gettime(&p->start_time);
- monotonic_to_bootbased(&p->real_start_time);
- cgroup_fork(p);
- sched_fork(clone_flags, p);
- perf_event_init_task(p); // null function
- audit_alloc(p); // null function
- copy_semundo(clone_flags, p);
- copy_files(clone_flags, p);
- copy_fs(clone_flags, p);
- copy_sighand()
- copy_signal()
- copy_mm()
- copy_namespaces()
- copy_io()
- copy_thread()
- alloc_pid()
- call: alloc_pid()
// ARM10C 20161105
// p->nsproxy->pid_ns_for_children: (&init_nsproxy)->pid_ns_for_children: &init_pid_ns
struct pid *alloc_pid(struct pid_namespace *ns)
{
struct pid *pid;
enum pid_type type;
int i, nr;
struct pid_namespace *tmp;
struct upid *upid;
// ns->pid_cachep: (&init_pid_ns)->pid_cachep: kmem_cache#19, GFP_KERNEL: 0xD0
// kmem_cache_alloc(kmem_cache#19, 0xD0): kmem_cache#19-oX (struct pid)
pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
// pid: kmem_cache#19-oX (struct pid)
// pid: kmem_cache#19-oX (struct pid)
if (!pid)
goto out;
// ns: &init_pid_ns
tmp = ns;
// tmp: &init_pid_ns
// pid->level: (kmem_cache#19-oX (struct pid))->level, ns->level: (&init_pid_ns)->level: 0
pid->level = ns->level;
// pid->level: (kmem_cache#19-oX (struct pid))->level: 0
// ns->level: (&init_pid_ns)->level: 0
for (i = ns->level; i >= 0; i--) {
// tmp: &init_pid_ns
nr = alloc_pidmap(tmp);
- alloc_pidmap()
// ARM10C 20161105
// tmp: &init_pid_ns
static int alloc_pidmap(struct pid_namespace *pid_ns)
{
// pid_ns->last_pid: (&init_pid_ns)->last_pid: 0
int i, offset, max_scan, pid, last = pid_ns->last_pid;
// last: 0
struct pidmap *map;
// last: 0
pid = last + 1;
// pid: 1
// pid: 1, pid_max: 0x8000
if (pid >= pid_max)
pid = RESERVED_PIDS;
// pid: 1, PID_MAX_DEFAULT: 0x8000, BITS_PER_PAGE_MASK: 0x7FFF
offset = pid & BITS_PER_PAGE_MASK;
// offset: 1
// pid: 1, BITS_PER_PAGE: 0x8000
// &pid_ns->pidmap[0]: &(&init_pid_ns)->pidmap[0]
map = &pid_ns->pidmap[pid/BITS_PER_PAGE];
// map: &(&init_pid_ns)->pidmap[0]
/*
* If last_pid points into the middle of the map->page we
* want to scan this bitmap block twice, the second time
* we start with offset == 0 (or RESERVED_PIDS).
*/
// pid_max: 0x8000, BITS_PER_PAGE: 0x8000, DIV_ROUND_UP(0x8000, 0x8000): 1, offset: 1
max_scan = DIV_ROUND_UP(pid_max, BITS_PER_PAGE) - !offset;
// max_scan: 1
// 2016/11/05 종료
502b720..71aec8e master -> origin/master
Updating 502b720..71aec8e
Fast-forward
arch/arm/include/asm/atomic.h | 5 +
arch/arm/include/asm/barrier.h | 1 +
arch/arm/include/asm/bitops.h | 6 +-
arch/arm/include/asm/cmpxchg.h | 40 +++++-
arch/arm/include/asm/page.h | 1 +
arch/arm/lib/bitops.h | 1 +
arch/arm/lib/testsetbit.S | 1 +
fs/filesystems.c | 6 +
fs/inode.c | 8 ++
fs/mount.h | 1 +
fs/namespace.c | 167 ++++++++++++++++++++++
fs/proc/inode.c | 225 ++++++++++++++++++++++++++++-
fs/proc/internal.h | 14 ++
fs/proc/root.c | 229 ++++++++++++++++++++++++++++-
fs/super.c | 317 +++++++++++++++++++++++++++++++++++++++--
include/linux/dcache.h | 1 +
include/linux/err.h | 2 +
include/linux/fs.h | 4 +
include/linux/gfp.h | 1 +
include/linux/list.h | 4 +
include/linux/mount.h | 1 +
include/linux/parser.h | 3 +
include/linux/percpu.h | 4 +
include/linux/pid.h | 5 +
include/linux/pid_namespace.h | 8 +-
include/linux/proc_ns.h | 3 +
include/linux/security.h | 3 +
include/linux/slab.h | 4 +
include/linux/spinlock.h | 4 +
include/linux/spinlock_types.h | 12 ++
include/linux/stat.h | 2 +
include/linux/time.h | 1 +
include/uapi/linux/fs.h | 7 +
include/uapi/linux/magic.h | 2 +
include/uapi/linux/stat.h | 2 +
kernel/pid.c | 100 +++++++++++++
kernel/time/timekeeping.c | 1 +
lib/idr.c | 4 +
mm/slub.c | 2 +
mm/util.c | 2 +
40 files changed, 1185 insertions(+), 19 deletions(-)