0x80483c4

advertisement
리눅스 커널 분석
강사명 : 김정인
email : love1770@ioacademy.co.kr
수업자료 ( 소스 / ppt 자료 )
ftp server : 156.147.178.179
id/passwd : linux / linux
강의 배포자료 : 이동식 디스크 ( 커널수업자료.egg )
리눅스 커널 분석
1. 완벽한 C 언어
2. 커널 고급 자료구조 ( generic linked list, hash, RB Tree )
3. 리눅스 시스템 프로그램 ( R. stevens )
4. 네크워크 프로그램 ( R. stevens )
5. 가상 파일 시스템 ( file system, driver , inode, file, ... )
6. 프로세스 ( schedule , context switching , fork, exit, wait..
7. 메모리 ( paging , buddy system, slab allocator )
;
Multi tasking
3. 시간 만료시 양보됨 (2
2.4GHz
2.4Gbit
0.3Gbyte
0.3*1000*1000*1000 Byte
1000000 명령
PC
SP
CPU
PC
SP
load
ready queue
player
IRQ=3
ls
PC
SP
schedule();
context_switch();
0x23
vi
PC
SP
PIC
store
wait queue
0x27
HZ 10
x80483c4
TEXT
DATA
STACK
int main()
{
printf("after\n");
}
0x80483c4
4
TEXT
DATA
STACK
TEXT
int main()
{
fork();
printf("after\n");
}
DATA
STACK
4
TEXT
DATA
STACK
int main()
{
char *argv[3] = { "ls", "-l", 0 };
execve( "/bin/ls", argv, 0 );
printf("after\n");
return 0;
}
31ed5e89
68b0ae05
fff49090
5589e553
8b15cc02
c1f8028d
8d4201a3
e183e4f0
08515668
90909090
83ec0480
0608b8fc
58ff39da
cc020608
50545268
20f70408
90909090
3dc80206
fe05082d
731f8db6
ff1485f8
a0ae0508
e887fbff
90909090
08007540
f8fe0508
00000000
fe05088b
0x80483c4
4
TEXT
DATA
TEXT
int main()
{
char *argv[3] = { "ls", "-l", 0 };
DATA
if( fork() == 0 )
execve( "/bin/ls", argv, 0 );
printf("after\n");
return 0;
}
31ed5e89
68b0ae05
fff49090
5589e553
8b15cc02
c1f8028d
8d4201a3
STACK
e183e4f0
08515668
90909090
83ec0480
0608b8fc
58ff39da
cc020608
50545268
20f70408
90909090
3dc80206
fe05082d
731f8db6
ff1485f8
a0ae0508
e887fbff
90909090
08007540
f8fe0508
00000000
fe05088b
STACK
bash
fork();
wait();
bash
ls
execve();
wait(&status)=>sys_wai
a.out
fork();
SIGCHLD
exit(3);
my_sig(
a.out
exit_code=3
17
TASK_ZOMBIE
wait(&status)=>sys_wai
exit(7);
CORE DUMP
1 1 1
kill(2);
0
1 0
root@ubuntu:~# sleep 1000
^\Quit
root@ubuntu:~# ulimit
unlimited
root@ubuntu:~# ulimit -c
0
root@ubuntu:~# ulimit -c 1000
root@ubuntu:~# ulimit -c
1000
root@ubuntu:~# sleep 1000
^\Quit (core dumped)
O( n )
list_for_each(tmp, &runqueue_head) {
p = list_entry(tmp, struct task_struct, run_l
if (can_schedule(p, this_cpu)) {
int weight = goodness(p, this_cpu, pr
if (weight > c)
c = weight, next = p;
}
}
if (p->policy == SCHED_OTHER) {
weight = p->counter;
if (!weight)
goto out;
if (p->mm == this_mm || !p->mm)
weight += 1;
weight += 20 - p->nice;
goto out;
O(1)
struct prio_array {
unsigned int nr_active;
unsigned long bitmap[BITMAP_SIZE];
struct list_head queue[MAX_PRIO];
};
O(1) , active , expire
idx = sched_find_first_bit(array->bitmap);
queue = array->queue + idx;
next = list_entry(queue->next, task_t, run_list);
31
[0]
[1]
[2]
[3]
[4]
1
static inline int sched_find_first_bit(const unsign
{
if (unlikely(b[0]))
return __ffs(b[0]);
if (unlikely(b[1]))
return __ffs(b[1]) + 32;
if (unlikely(b[2]))
return __ffs(b[2]) + 64;
if (b[3])
return __ffs(b[3]) + 96;
return __ffs(b[4]) + 128;
}
CFS : 완전 공평 스케줄링
schedule();
struct cfs_rq {
struct load_weight load;
unsigned int nr_running, h_nr_running;
u64 exec_clock;
u64 min_vruntime;
struct rb_root tasks_timeline;
struct rb_node *rb_leftmost;
};
next = pick_next_task(rq);
pick_next_task(struct rq *rq)
{
const struct sched_class *class;
struct task_struct *p;
if (likely(rq->nr_running == rq->cfs.h_nr_ru
p = fair_sched_class.pick_next_task(
if (likely(p))
return p;
}
}
pick_next_task_fair(rq);
do {
se = pick_next_entity(cfs_rq);
set_next_entity(cfs_rq, se);
cfs_rq = group_cfs_rq(se);
} while (cfs_rq);
__pick_first_entity(cfs_rq);
struct sched_entity *__pick_first_entity(struct cfs_
{
struct rb_node *left = cfs_rq->rb_leftmost;
if (!left)
return NULL;
return rb_entry(left, struct sched_entity, r
}
struct task_struct
{
struct sched_entity se;
};
struct sched_entity {
struct rb_node
u64
};
run_node;
vruntime;
40
20
10
50
30
60
1.
-1 => 105ms , 0 => 100ms
, 1 => 95ms , 20 => 5m
nice : 0 2개의 process ( IO 전용 프로세스 )
100ms 한번씩 switching
nice : 20 2개의 process ( 계산 전용 프로세스 )
5 ms 한번씩 switching
2.
nice : -1 1개의 process
105 ms ( 51.2% )
nice : 0 1개의 process
100 ms ( 48.7% )
nice : 19 1개의 process
10 ms ( 66.6 % )
nice : 20 1개의 process
5 ms ( 33.3 % )
3.
nice : -19 5개의 ( IO 전용프로세스 )
nice : 20 1개의 ( 계산 전용 프로세스 )
nice
weight
Wp/Wt
time
W0/Wp
vruntime
-10
9548
0.675
6.75
0.107
0.72
-5
3121
0.221
2.21
0.328
0.72
0
1024
0.072
0.72
1
0.72
5
335
0.024
0.24
3.057
0.72
10
110
0.008
0.08
9.309
0.72
합계
14138
1.000
100 ms
W0/Wp
((2^32)/1024) >> 32
(2^32)/9548
tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
static const int prio_to_weight[40] = {
/* -20 */
88761,
71755,
56483,
/* -15 */
29154,
23254,
18705,
/* -10 */
9548,
7620,
6100,
/* -5 */
3121,
2501,
1991,
/*
0 */
1024,
820,
655,
/*
5 */
335,
272,
215,
/* 10 */
110,
87,
70,
/* 15 */
36,
29,
23,
};
46273,
14949,
4904,
1586,
526,
172,
56,
18,
static const u32 prio_to_wmult[40] = {
/* -20 */
48388,
59856,
76040,
92818,
/* -15 */
147320,
184698,
229616,
287308,
/* -10 */
449829,
563644,
704093,
875809,
/* -5 */
1376151,
1717300,
2157191,
2708050,
/*
0 */
4194304,
5237765,
6557202,
8165337,
/*
5 */ 12820798, 15790321, 19976592, 24970740,
/* 10 */ 39045157, 49367440, 61356676, 76695844,
/* 15 */ 119304647, 148102320, 186737708, 238609294,
};
static inline struct thread_info *current_thread_inf
{
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~(THREAD_
}
static inline struct task_struct *get_current(void)
{
return current_thread_info()->task;
}
#define current (get_current())
struct task_struct *prev = current;
task_struct
0x1234000
thread_info
CPU
0x1234120
8192 => 10000000000000
8191 => 1111111111111
static inline struct thread_info *current_thread_inf
{
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~(THREAD_
}
/etc/init.d/nfs
/tftpboot/zImage-S5PC100
tftp
/nfsroot/Ro
nfs
69
192.168.10.5
com1 <= putty
192.168.10.3
NT-S5PC100 # print
vmware 에서 edit >> virtual network editor
# vi app.c
#include <stdio.h>
int main()
{
printf("hello target\n");
return 0;
}
#
#
#
#
arm-s5pc1xx-linux-gnueabi-gcc -o app app.c
arm-s5pc1xx-linux-gnueabi-objdump -S app
file app
cp app /nfsroot/RootFS-S5PC100
타겟 보드에서
# cd /
# ./app
커널 컴파일
# cd /usr/src/linux
# cat .cross_compile
arm-s5pc1xx-linux-gnueabi# make ntc100_xwindows_defconfig
# make zImage
타겟 보드 재부팅 ( 새로운 커널 이미지 적용 )
system call 추가
# cd /usr/src/linux
# cd arch/arm/kernel
# vi calls.S
/* 335 */
CALL(sys_ni_syscall)
/* 335 */
CALL(sys_mycall)
# cd /usr/src/linux/kernel
# vi mycall.c
#include <linux/kernel.h>
asmlinkage void sys_mycall(void)
{
printk("hello kernel\n");
}
system call 추가
# vi Makefile
obj-y
= ... mycall.o
# cd /usr/src/linux
# make zImage
타겟 보드 부팅 후 확인
system call 호출 app 구현
# vi app.c
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
int main()
{
// fork();
// swi 90005
syscall(335);
}
# arm-s5pc1xx-linux-gnueabi-gcc -o app app.c
# cp app /nfsroot/RootFS-S5PC100/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/list.h>
asmlinkage void sys_mycall(void)
{
struct task_struct *p;
struct list_head *temp;
for( temp = current->tasks.next;
temp != &current->tasks;
temp=temp->next)
{
p = list_entry( temp, struct task_struct , task
printk("pid=%5d, comm=[%s]\n", p->pid, p->comm
}
p = list_entry( temp, struct task_struct , tasks )
printk("pid=%5d, comm=[%s]\n", p->pid, p->comm );
Download