Neuromancer : 145 주차
일시 : 2016.05.28 (145주차 스터디 진행)
모임명 : Neuromancer_ARM
장소 : 토즈 서현점
장소지원 : 공개 소프트웨어 개발자 커뮤니티 지원 프로그램
참여인원 : 2명
============
145주차 진도
- 145차 시작 위치
- start_kernel 1 ~/init/main.c
- vfs_caches_init 925 ~/init/main.c
- chrdev_init 6005 ~/fs/dcache.c
145주차 함수 호출 구조
- calll: start_kernel()-> vfs_caches_init()
- kmem_cache_create(): names_cache
- dcache_init()
- inode_init()
- files_init()
- mnt_init()
- bdev_cache_init()
- chrdev_init()
main.c::start_kernel()
- call: start_kernel()->vfs_caches_init()
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
// ATAG,DTB 정보로 사용
...
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);
## dcache.c::vfs_caches_init() * call: start_kernel() - vfs_caches_init() - kmem_cache_create(): names_cache - dcache_init() - inode_init() - files_init() - mnt_init() - bdev_cache_init() - chrdev_init()
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
unsigned long reserve;
/* Base hash sizes on available memory, with a reserve equal to
150% of current kernel size */
// NOTE:
// mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
// 계산된 reserve의 값을 XXX 로 함
// mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
// reserve: XXX
// mempages: 총 free된 page 수, reserve: XXX
mempages -= reserve;
// mempages: 총 free된 page 수 - XXX
// PATH_MAX: 4096
// SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
// kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
// names_cachep: kmem_cache#6
dcache_init();
inode_init();
// mempages: 총 free된 page 수 - XXX
files_init(mempages);
mnt_init();
...
bdev_cache_init();
// bdev_cache_init 에서 한일:
// struct bdev_inode를 위한 bdev_cache 용 kmem_cache 를 생성함 bdev_cachep: kmem_cache#n#30
chrdev_init();
}
## char_dev.c::chrdev_init() * call: start_kernel() - vfs_caches_init() - kmem_cache_create(): names_cache - dcache_init() - inode_init() - files_init() - mnt_init() - bdev_cache_init() - chrdev_init()
// ARM10C 20160521
void __init chrdev_init(void)
{
// kobj_map_init(base_probe, &chrdevs_lock): kmem_cache#26-oX (struct kobj_map)
cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
// cdev_map: kmem_cache#26-oX (struct kobj_map)
// kobj_map_init 에서 한일:
// struct kobj_map 만큼의 메로리를 할당 받음 kmem_cache#26-oX (struct kobj_map)
// struct probe 만큼의 메로리를 할당 받음 kmem_cache#30-oX (struct probe)
//
// (kmem_cache#30-oX (struct probe))->dev: 1
// (kmem_cache#30-oX (struct probe))->range: 0xFFFFFFFF
// (kmem_cache#30-oX (struct probe))->get: base_probe
//
// (kmem_cache#26-oX (struct kobj_map))->probes[0...255]: kmem_cache#30-oX (struct probe)
// (kmem_cache#26-oX (struct kobj_map))->lock: &chrdevs_lock
// 2016/05/21 종료
if (bdi_init(&directly_mappable_cdev_bdi))
panic("Failed to init directly mappable cdev bdi");
}
## backing-dev.c::bdi_init() * call: start_kernel() - vfs_caches_init() - kmem_cache_create(): names_cache - dcache_init() - inode_init() - files_init() - mnt_init() - bdev_cache_init() - chrdev_init() * call: chrdev_init() - bdi_init() ## main.c::start_kernel() * call: start_kernel()->vfs_caches_init()
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
// ATAG,DTB 정보로 사용
...
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);
signals_init();
## signal.c::signals_init() * call: start_kernel() - vfs_caches_init() - signals_init() * struct sigque
struct sigqueue {
struct list_head list;
int flags;
siginfo_t info;
struct user_struct *user;
};
* struct siginfo_t
// ARM10C 20150919
typedef struct siginfo {
int si_signo;
int si_errno;
int si_code;
union {
int _pad[SI_PAD_SIZE];
/* kill() */
struct {
__kernel_pid_t _pid; /* sender's pid */
__ARCH_SI_UID_T _uid; /* sender's uid */
} _kill;
/* POSIX.1b timers */
struct {
__kernel_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
/* POSIX.1b signals */
struct {
__kernel_pid_t _pid; /* sender's pid */
__ARCH_SI_UID_T _uid; /* sender's uid */
sigval_t _sigval;
} _rt;
/* SIGCHLD */
struct {
__kernel_pid_t _pid; /* which child */
__ARCH_SI_UID_T _uid; /* sender's uid */
int _status; /* exit code */
__ARCH_SI_CLOCK_T _utime;
__ARCH_SI_CLOCK_T _stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
void __user *_addr; /* faulting insn/memory ref. */
#ifdef __ARCH_SI_TRAPNO
int _trapno; /* TRAP # which caused the signal */
#endif
short _addr_lsb; /* LSB of the reported address */
} _sigfault;
/* SIGPOLL */
struct {
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
/* SIGSYS */
struct {
void __user *_call_addr; /* calling user insn */
int _syscall; /* triggering system call number */
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
} _sigsys;
} _sifields;
} __ARCH_SI_ATTRIBUTES siginfo_t;
* code
void __init signals_init(void)
{
sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
}
## main.c::start_kernel() * call: start_kernel()
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
// ATAG,DTB 정보로 사용
...
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);
signals_init();
page_writeback_init();
## page-writeback.c::page_writeback_init() * call: start_kernel() - vfs_caches_init() - signals_init() - page_writeback_init()
void __init page_writeback_init(void)
{
writeback_set_ratelimit();
register_cpu_notifier(&ratelimit_nb);
fprop_global_init(&writeout_completions);
}
## page-writeback.c::write_set_rate_limit() * call: start_kernel() - vfs_caches_init() - signals_init() - page_writeback_init() * call: page_writeback_init() - write_set_rate_limit()
void writeback_set_ratelimit(void)
{
unsigned long background_thresh;
unsigned long dirty_thresh;
global_dirty_limits(&background_thresh, &dirty_thresh);
global_dirty_limit = dirty_thresh;
ratelimit_pages = dirty_thresh / (num_online_cpus() * 32);
if (ratelimit_pages < 16)
ratelimit_pages = 16;
}
## page-writeback.c::global_dirty_limits() * call: start_kernel() - vfs_caches_init() - signals_init() - page_writeback_init() * call: page_writeback_init() - write_set_rate_limit() * call: write_set_rate_limit() - global_dirty_limits()
void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty)
{
unsigned long background;
unsigned long dirty;
unsigned long uninitialized_var(available_memory);
struct task_struct *tsk;
if (!vm_dirty_bytes || !dirty_background_bytes)
available_memory = global_dirtyable_memory();
if (vm_dirty_bytes)
dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE);
else
dirty = (vm_dirty_ratio * available_memory) / 100;
if (dirty_background_bytes)
background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE);
else
background = (dirty_background_ratio * available_memory) / 100;
if (background >= dirty)
background = dirty / 2;
tsk = current;
if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) {
background += background / 4;
dirty += dirty / 4;
}
*pbackground = background;
*pdirty = dirty;
trace_global_dirty_state(background, dirty);
}
## page-writeback.c::global_dirtyable_memory() * call: start_kernel() - vfs_caches_init() - signals_init() - page_writeback_init() * call: page_writeback_init() - write_set_rate_limit() * call: write_set_rate_limit() - global_dirty_limits() * call: global_dirty_limits() - global_dirtyable_memory()
static unsigned long global_dirtyable_memory(void)
{
unsigned long x;
x = global_page_state(NR_FREE_PAGES);
x -= min(x, dirty_balance_reserve);
x += global_page_state(NR_INACTIVE_FILE);
x += global_page_state(NR_ACTIVE_FILE);
if (!vm_highmem_is_dirtyable)
x -= highmem_dirtyable_memory(x);
return x + 1; /* Ensure that we never return 0 */
}
## highmem_dirtyable_memory() * call: start_kernel() - vfs_caches_init() - signals_init() - page_writeback_init() * call: page_writeback_init() - write_set_rate_limit() * call: write_set_rate_limit() - global_dirty_limits() * call: global_dirty_limits() - global_dirtyable_memory() * call: highmem_dirtyable_memory()
static unsigned long highmem_dirtyable_memory(unsigned long total)
{
#ifdef CONFIG_HIGHMEM
int node;
unsigned long x = 0;
for_each_node_state(node, N_HIGH_MEMORY) {
struct zone *z = &NODE_DATA(node)->node_zones[ZONE_HIGHMEM];
x += zone_dirtyable_memory(z);
}
/*
* Unreclaimable memory (kernel memory or anonymous memory
* without swap) can bring down the dirtyable pages below
* the zone's dirty balance reserve and the above calculation
* will underflow. However we still want to add in nodes
* which are below threshold (negative values) to get a more
* accurate calculation but make sure that the total never
* underflows.
*/
if ((long)x < 0)
x = 0;
/*
* Make sure that the number of highmem pages is never larger
* than the number of the total dirtyable memory. This can only
* occur in very strange VM situations but we want to make sure
* that this does not occur.
*/
return min(x, total);
#else
return 0;
#endif
}
# log
2518303..f8ce6b6 master -> origin/master
Updating 2518303..f8ce6b6
Fast-forward
fs/char_dev.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
fs/dcache.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/backing-dev.h | 1 +
include/linux/compiler-gcc.h | 1 +
include/linux/mmzone.h | 6 ++++++
include/linux/nodemask.h | 2 ++
include/linux/sched.h | 1 +
include/linux/signal.h | 2 ++
include/linux/slab.h | 4 ++++
include/linux/slub_def.h | 1 +
include/linux/vmstat.h | 6 ++++++
include/linux/writeback.h | 2 ++
include/uapi/asm-generic/siginfo.h | 11 +++++++++++
init/main.c | 5 +++++
kernel/signal.c | 12 ++++++++++++
mm/backing-dev.c | 2 ++
mm/page-writeback.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
mm/page_alloc.c | 1 +
mm/slab_common.c | 5 +++++
19 files changed, 260 insertions(+), 2 deletions(-)