Transcript PowerPoint

init/main.c
Sched_clock_init() 함수
monotonic time을 얻어와서 nanosec으로 변경한 후 각 cpu별 sched_clock_data에 얻어온 nanosec을 tick_gtod, clock 멤버에
세팅한다 마지막으로 sched_clock_running을 1로 세팅한다 c
Sched_clock_init
monotonic time을 얻어서 nanosec단위로 변환해 리턴
Ktime_to_ns()
for_each_possible_cpu()
각 cpu별로 sched_clock_data형 포인터를 가져와서
tick_gtod, clock을 ktime_now로 세팅한다
cpu_sdc()
Profile_init() 함수
코드영역(_etext - _stext)을 profiling 하기 위한 profiling counter의 메모리를 할당받고 prof_cpu_mask를 cpu_possible_mask로
세팅한다
Slab 할당자를 사용할 수 없다면 bootmem 할당자를 사용한다.
Profile_init()
if Slab is unavailable
alloc_bootmem(buffer_bytes)
부트멤할당자를 이용해서 buffer_bytes만큼 메모리를 할당받는다
alloc_bootmem_cpumask_var
(&prof_cpu_mask)
prof_cpu_mask에 cpumask_size()만큼을 할당받는다
Cpumask_copy(prof_cpu_mas
k,cpu_possible_mask)
prof_cpu_mask를 cpu_possible_mask로 mask시킨다
slab allocator가 enable되어있을 경우 prof_cpu_mask를
GFP_KERNEL타입으로 할당한다
alloc_cpumask_var(&prof_cpu
_mask, GFP_KERNEL))
prof_cpu_mask를 cpu_possible_mask로 mask시킨다
cpumask_copy(prof_cpu_mask,
cpu_possible_mask)
kzalloc(buffer_bytes,
GFP_KERNEL)
alloc_pages_exact(buffer_byte
s, GFP_KERNEL|__GFP_ZERO)
slab 할당자를 이용해서 buffer_bytes만큼 메모리 (물리적으로 연
속적인)를 할당받는다
slab할당자를 이용한 할당이 실패할 경우에 어떻게든지 할당하기
위해 다양한 방법으로 여러번 시도 요청한 buffer_bytes만큼(물리
적으로 연속적인)을 할당요청한다 5k 요청시 alloc_pages()는 2의
배수단위로 할당(8k), alloc_pages_exact()는 5k를 정확히 할당한다
vmalloc(buffer_bytes)
위와 달리 virtually continuous한 페이지를 할당요청한다
free_cpumask_var(prof_cpu_m
ask)
할당시도가 전부 실패했다면 prof_cpu_mask를 해제한다
if (!irqs_disabled())
인터럽트가 활성화 되어있는지 검사
early_boot_irqs_on()
ONFIG_TRACE_IRQFLAGS가 정의되어 있으면 early_boot_irqs_enabled = 1;
early_boot_irqs_on()
local_irq_enable() 함수
irq를 enable한다
local_irq_enable()
trace_hardirqs_on()
1. CONFIG_TRACE_IRQFLAGS가 설정되어 있을 경우
hardirq가 on/off되는 이벤트를 trace하는 기능을 on한다
2. __LINUX_ARM_ARCH__에 의해 어셈블러가 달라지지만
결국은 local irq를 enable시킨다. 예를 들어
__LINUX_ARM_ARCH__ >= 6일 경우
__asm__("cpsie i @ __sti" : : : "memory", "cc")
raw_local_irq_enable();
Console_init() 함수
tty_ldisc[]배열에 tty(teletypewriter or teletype)에 대한 line discipline function 구조체를 등록한다 __con_initcall_start 부터
__con_initcall_end에 위치한 함수들을 전부 다 호출
console_init()
tty_ldisc_begin()
tty_ldisc[]배열의 해당 line discipline function 구조체를 등록한다
tty_register_ldisc(N_TTY,
&tty_ldisc_N_TTY)
while( __con_initcall_start ~
__con_initcall_end )
(*call)()
panic() 함수
panic_later가 NULL이 아니라면 system을 정지시킨다
panic(panic_later,
panic_param)
tty_ldisc[]배열의 해당 line discipline function 구조체를 등록한다
#define N_TTY
0
struct tty_ldisc_ops tty_ldisc_N_TTY = {
.magic
= TTY_LDISC_MAGIC,
.name
= "n_tty",
.open
= n_tty_open,
.close
= n_tty_close,
.flush_buffer = n_tty_flush_buffer,
.chars_in_buffer = n_tty_chars_in_buffer,
.read
= n_tty_read,
.write
= n_tty_write,
.ioctl
= n_tty_ioctl,
.set_termios
= n_tty_set_termios,
.poll
= n_tty_poll,
.receive_buf
= n_tty_receive_buf,
.write_wakeup = n_tty_write_wakeup
};
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
섹션안에 있는 함수들을 전부 다 호출
Lockdep_info() 함수
Lock dependency 정보를 출력
lockdep_info()
퀄컴 boot message example
\Lock dependency validator: Copyright (c) 2006 Red Hat, Inc.,
Ingo Molnar
... MAX_LOCKDEP_SUBCLASSES: 8
... MAX_LOCK_DEPTH:
48
... MAX_LOCKDEP_KEYS:
2048
... CLASSHASH_SIZE:
1024
... MAX_LOCKDEP_ENTRIES:
8192
... MAX_LOCKDEP_CHAINS:
16384
... CHAINHASH_SIZE:
8192
memory used by lock dependency info: 992 kB
per task-struct memory footprint: 1920 bytes
Locking_selftest() 함수
Locking mechanism 을 자체 테스트한다.
locking_selftest()
#ifdef CONFIG_BLK_DEV_INITRD
initrd_start = 0
2.6 부터는 initrd대신 initramfs를 사용한다
initrd_start < memory_start이면 initrd가 존재할 때
initrd_start < memory_start이고
initrd_start의 pfn < min_low_pfn 이면
initrd가 overwrite된 경우로 간주하고 initrd_start=0으로 설정해
서 initrd를 disable한다
Vmalloc_init() 함수
per-cpu 데이터인 vmap_block_queue의 spin_lock, free list, dirty list, nr_dirty 초기화 vmalloc_init이 호출되기 전에 생성된
vmlist가 존재한다면 vmlist의 element들을 순회하면서 vmap_area를 생성하여, vmlist의 element들로 세팅해주고 vmap_area를
vmap_area_root를 root로 하는 rb-tree에 insert한다 .
Vmalloc_init()
struct vm_struct
커널영역에서는, 전체 vm_struct는 vmlist가 연결리스트로 관리를 하고 있
다 vm_struct전체를 참고할 때 vmlist가 사용된다. 그리고 개별
vm_struct의 빠른 접근을 위해서 vm_struct들은 rb-tree로 유지되는데 각
노드는 vmap_area로 관리된다 사용자영역에서는, mm_struct가
vm_area_struct를 관리하기 위해 mmap과 mm_rb를 이용하는것도 흡사
한 구조이다
vmalloc 함수 수행시 할당되는 불연속적인 공간을 나타내는 구조
체 vmlist변수로 연결리스트가 구현되어 있다 vm_area_struct는
사용자영역에 있는 프로세스의 가상메모리관리를 위한것이다
(각 섹션의 메타데이터) vm_struct와 vm_area_struct는 관계가 없
다
per-cpu 데이터인 vmap_block_queue의 spin_lock, free list, dirty
list, nr_dirty 초기화
for_each_possible_cpu(i)
struct vmap_block_queue
*vbq;
…
vmalloc_init이 호출되기 전에 생성된 vmlist가 존재한다면 vmlist
의 element들을 순회하면서 vmap_area를 생성하여, vmlist의
element들로 세팅해주고 vmap_area를 vmap_area_root를 root로
하는 rb-tree에 insert한다
for loop ( all vmlist )
alloc_bootmem(sizeof(struct
vmap_area))
…
__insert_vmap_area(va)
Vfs_caches_init_early () 함수
Dentry Cache & Inode Cache를 위한 해시테이블을 만들고 해시테이블의 엔트리들을 초기화한다
Dentry Cache 해시테이블을 만들고 해시테이블의 엔트리들을 초
기화함 만약 할당이 어려울 경우, 해시 엔트리의 개수를 계속 반
으로 줄여가면서 할당 시도함.
NUMA 노드에 해시들이 분산되어 있다면, vmalloc이 가용한 후에
시도
vfs_caches_init_early()
dcache_init_early()
hashdist
#if defined(CONFIG_NUMA) && defined(CONFIG_64BIT)
#define HASHDIST_DEFAULT 1
#else
#define HASHDIST_DEFAULT 0
#endif
hashdis = HASHDIS_DEFAULT
64비트 NUMA 시스템에서는 hash들이 distribution되어 있다
hash allocation을 vmalloc이 가용한 후에 함
dentry_hashtable
1. numentries를 2의 지수승으로 만든다
2. bootmem, vmalloc, get_free_pages()중 하나를 사용해서
Dentry cache 해쉬테이블을 위한 메모리를 할당하려 시도한다.
메모리할당이 실패할 경우 dhash_entries를 반으로 줄여가며
할당을 시도한다
node-cachee 해시테이블을 만들고 해시테이블의 엔트리들을 초
기화함 만약 할당이 어려울 경우, 해시 엔트리의 개수를 계속 반
으로 줄여가면서 할당 시도함. NUMA 노드에 해시들이 분산되어
있다면, vmalloc이 가용한 후에 시도
inode_init_early()
dentry_hashtable
dentry_hashtable
#if defined(CONFIG_NUMA) && defined(CONFIG_64BIT)
#define HASHDIST_DEFAULT 1
#else
#define HASHDIST_DEFAULT 0
#endif
hashdis = HASHDIS_DEFAULT
64비트 NUMA 시스템에서는 hash들이 distribution되어 있다
hash allocation을 vmalloc이 가용한 후에 함
1. numentries를 2의 지수승으로 만든다
2. bootmem, vmalloc, get_free_pages()중 하나를 사용해서
Dentry cache 해쉬테이블을 위한 메모리를 할당하려 시도한다.
메모리할당이 실패할 경우 dhash_entries를 반으로 줄여가며
할당을 시도한다