슬라이드 1

Download Report

Transcript 슬라이드 1

리눅스 커널 분석
강사명 : 김정인
email : [email protected]
수업자료 ( 소스 / 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 )
실습 환경 구축
vmplayer 삭제후
vmworkstation 설치(VMware-workstation-full-7.0.0-2037
key.txt에 있는 serial key 입력
linux login
일반계정 : linux/linux
루트권한으로 변경
$ su password : linux
#
( vmware 에서 login )
루트계정 : root/linux ( putty 에서 login )
#
windows
alftp putty
linux
ftp
21
vmnet8 : 192.168.100.1
ssh
22
eth0 : 192.168.100.133
네트워크 설정
vmware 에서
edit >> virtual network editor
네트워크 test
windows에서 cmd 실행
C:\Documents and Settings\user>ipconfig
VMnet8:
. : 192.168.100.1
C:\Documents and Settings\user> ping 192.168.100.
linux에서 터미널 실행 ( vmware )
root@ubuntu:~# ifconfig
eth1
Link encap:Ethernet HWaddr 00:0c:29:2a
inet addr:192.168.100.133
root@ubuntu:~# ping 192.168.100.1
네트워크 test
linux의 데몬 확인
tcp 데몬 확인
root@ubuntu:~# netstat -at
tcp
0
0 *:ssh
tcp
0
0 *:ftp
LISTEN
LISTEN
root@ubuntu:~# netstat -atn
tcp
0
0 0.0.0.0:22 LISTEN
tcp
0
0 0.0.0.0:21 LISTEN
원격 접속을 위한 putty 설정
ftp 설정
재부팅 후 network 설정 방법 I
ifconfig 시 eth2, eth3으로 나올경우
다음 조치 수행
# vi /etc/network/interfaces
auto eth2
iface eth2 inet static
address 192.168.10.3
netmask 255.255.255.0
network 192.168.10.0
broadcast 192.168.10.255
gateway 192.168.10.1
auto eth3
iface eth3 inet dhcp
위와 같이 수정후 네트워크 재기동
# /etc/init.d/networking restart
재부팅 후 network 설정 방법 II
ifconfig 시 eth2, eth3으로 나올경우
1. /etc/udev/rules.d/70-persistent-net.rules 파일에서 랜
MAC 어드레스에 해당하는 라인을 지우거나 주석처리한다.
#SUBSYSTEM=="net", ATTR{address}=="00:0c:29:2a:f1:69"
#SUBSYSTEM=="net", ATTR{address}=="00:0c:29:2a:f1:73"
2. 현재 MAC 어드레스로 /etc/udev/rules.d/70-persistent-n
파일을 업데이트하기 위해 아래 명령들을 시작한다
# /etc/init.d/udev restart
# modprobe -r pcnet32
# modprobe pcnet32
위 명령 실행시 /etc/udev/rules.d/70_persistent-net.rules
파일의 MAC 어드레스 부분은 아래처럼 새로운 값으로 변경됨
3. 네트워크 재기동
# /etc/init.d/networking restart
소스 분석을 위한 환경설정 ( ctags )
설치
# apt-get install ctags
tag 파일 생성
# cd /usr/src/linux
# ctags -R *
# ls -l tags
검색
# vi a.c
task_struct
ctrl + ] : 정의로 이동
g + ]
: 여러개의 정의
ctrl + t : 돌아오기
No write since last change
위 에러가 났을경우 반드시 저장후 이동
:w
소스 분석을 위한 환경설정 ( ctags )
모든 디렉토리에서 검색 가능하게 하기
# cd
# pwd
/root
# vi ~/.vimrc
set
set
set
set
sw=4
ts=4
cindent
tags+=/usr/src/linux/tags
자동들여 쓰기
{
int i;
}
=%
: 블럭 들여쓰기
gg=G : 파일 전체 들여쓰기
명령모드
편집모드
int main()
i,o,O
a,I,A
ESC
EX 모드
:
-- INSERT --
ESC
:w 파일의 저장
:q 파일을 나감
:wq 저장 후 나감
:
명령모드
편집모드
int main()
i,o,O
a,I,A
ESC
EX 모드
:
:
ESC
-- INSERT -x
: 한글자 지우기
cw : 한단어 치환
r
: 한글자 치환
2s : 두글자 치환
.
: 이전 명령의 반복
yy
p
dd
u
: 한줄 복사
: 붙혀 넣기
: 한줄 잘라내기
: undo
linked list 구현 step1
typedef struct _node
{
int data;
struct _node *next;
} NODE;
2
head
NODE *head;
void insert_data( int data )
{
NODE *temp = (NODE*)malloc( sizeof(NODE) );
temp->data = data;
temp->next = head;
head = temp;
}
1
0
linked list 구현 step1
2
[head]->[2]->[1]
1
0
head
void display(void)
{
NODE *temp;
system("clear");
printf("[head]");
for( temp = head; temp != 0 ; temp = temp->next )
printf("->[%d]", temp->data );
printf("\n");
getchar();
}
linked list 구현 step1
head
s
3
2
0
1
void insert_data( int data )
{
NODE *temp = (NODE*)malloc( sizeof(NODE) );
temp->data = data;
temp->next = s->next;
s->next = temp;
}
문제점 : 삽입/삭제시 일반성이 없다.
이유 : head가 node 가 아니기 때문
해결책 : head도 node를 갖게 하자
linked list 구현 step2
head
temp
void init( void )
0
{
head = (NODE*)malloc( sizeof(NODE) );
head->next = 0;
}
void insert_data( int data )
{
NODE *temp = (NODE*)malloc( sizeof(NODE) );
temp->data = data;
temp->next = head->next;
head->next = temp;
}
linked list 구현 step2
void display(void)
{
NODE *temp;
head
0
system("clear");
printf("[head]");
for( temp = head->next; ; temp = temp->next )
printf("->[%d]", temp->data ); // (*temp).dat
printf("\n");
getchar();
}
문제점 : NULL 로 끝나는 것이 문제
이유
: NULL을 역참조할 수 있는 위험성이 있다.
해결책 : NULL 대신 tail로 끝나게 하자
linked list 구현 step3
head
tail
NODE *head, *tail;
void init( void )
{
head = (NODE*)malloc( sizeof(NODE) );
tail = (NODE*)malloc( sizeof(NODE) );
head->next = tail;
tail->next = tail;
}
linked list 구현 step3
head
tail
void insert_data( int data )
{
NODE *temp = (NODE*)malloc( sizeof(NODE) );
temp->data = data;
temp->next = head->next;
head->next = temp;
}
문제점 : list가 메모리에 의존적이다. ( heap )
이유 : memory pooling 기법 사용 못함
해결책 : malloc 을 삽입코드에서 제거 하자.
linked list 구현 step4
void insert_data( NODE *temp )
{
temp->next = head->next;
head->next = temp;
}
NODE a[7];
a[i].data = i+1;
insert_data( a+i );
head
tail
linked list 구현 step4
void insert_data( NODE *temp )
{
temp->next = head2->next;
head2->next = temp;
}
문제점 : 프로세스내에 list가 하나만 존재 가능 하다.
이유 : head와 tail이 코드내에 있다.
해결책 : head와 tail을 인자로 처리 해야 함
linked list 구현 step5
void insert_data( NODE *head, NODE *temp )
{
temp->next = head->next;
head->next = temp;
}
// --------------------------insert_data( head1, temp );
insert_data( head2, temp );
문제점 : 프로세스내에 list가 하나만 존재 가능 하다.
이유 : head와 tail이 코드내에 있다.
해결책 : head와 tail을 인자로 처리 해야 함
linked list 구현 step5
void init( NODE **head, NODE **tail )
{
*head = (NODE*)malloc( sizeof(NODE) );
*tail = (NODE*)malloc( sizeof(NODE) );
(*head)->next = *tail;
(*tail)->next = *tail;
}
init( &head, &tail );
문제점 : 프로세스내에 list가 하나만 존재 가능 하다.
이유 : head와 tail이 코드내에 있다.
해결책 : head와 tail을 인자로 처리 해야 함
linked list 구현 step5-1
void init( NODE *head, NODE *tail )
{
head->next = tail;
tail->next = tail;
}
init( &head, &tail );
display( &head, &tail );
insert_data( &head, );
NODE head, tail;
문제점 : 프로세스내에 list가 하나만 존재 가능 하다.
이유 : head와 tail이 코드내에 있다.
해결책 : head와 tail을 인자로 처리 해야 함
linked list 구현 step5-1
void init( NODE *head, NODE *tail )
{
head->next = tail;
tail->next = tail;
}
init( &head, &tail );
display( &head, &tail );
insert_data( &head, );
NODE head, tail;
문제점 : tail 이 과연 필요 한가?
이유 : head와tail을 둘다 관리하기가 불편
해결책 : head가 tail 역할을 하면 된다.
linked list 구현 step6
head
void init( NODE *head)
{
head->next = head;
}
void insert_data( NODE *head, NODE *temp )
{
temp->next = head->next;
head->next = temp;
}
문제점 : tail 이 과연 필요 한가?
이유 : head와tail을 둘다 관리하기가 불편
해결책 : head가 tail 역할을 하면 된다.
2
1
linked list 구현 step6
head
void init( NODE *head)
{
head->next = head;
}
void insert_data( NODE *head, NODE *temp )
{
temp->next = head->next;
head->next = temp;
}
문제점 : 역순 검색이 가능한가?
이유 : 검색의 성능이 떨어진다.
해결책 : reverse함수를 구현 하면 된다.
2
1
linked list 구현 step7
head
3
2
1
next
curr
prev
reverse( NODE *head ){
NODE *prev =head;
NODE *curr = prev->next;
NODE *next;
while( curr != head ) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head->next = prev;
}
linked list 구현 step1
typedef struct _node
{
int data;
struct _node *next, *prev;
} NODE;
head
NODE head;
void insert_data( NODE *head, NODE *temp )
{
temp->next = head->next;
head->next = temp;
temp->prev = temp->next->prev;
temp->next->prev = temp;
}
1
prev
temp
1
next
void __insert_data( NODE *prev, NODE *next,
NODE *temp ){
temp->next = next;
prev->next = temp;
temp->prev = prev;
next->prev = temp;
}
void insert_front( NODE *temp ){
__insert_data( head, head->next, temp );
}
void insert_back( NODE *temp ){
__insert_data( head->prev, head, temp );
}
prev
temp
typedef struct _node
{
void *data;
struct _node *next, *prev;
} NODE;
void __insert_data( NODE *prev, NODE *next ,
NODE *temp )
{
temp->next = next;
prev->next = temp;
temp->prev = prev;
next->prev = temp;
}
문제점 : list가 data type에 의존적이다.
이유 : NODE 안에 data가 있기 때문
해결책 : void *를 이용하여 일반화 하라
ne
prev
temp
"홍길동"
"이순신"
next
"임꺽정"
typedef struct _node
{
void *data;
struct _node *next, *prev;
} NODE;
//------------------------------------------typedef struct
{
char name[20];
} SAWON;
prev
"홍길동"
temp
next
"임꺽정"
문제점 : loose coupling 문제
이유
: 메모리 할당/해지 시기가 다를수 있다.
해결책 : list에 data를 넣지 말고 data에 list를 넣
어라.
typedef struct _node
{
struct _node *next;
struct _node *prev;
} NODE;
//--------------------typedef struct
{
char name[20];
NODE list;
} SAWON;
SAWON*
NODE*
NODE*
980
NODE*
1000
"홍길동"
"이순신"
NODE*
NODE*
NODE*
NODE*
(SAWON*)((char*)temp - ( sizeof(SAWON) - sizeof(NODE
문제점 : 하나의 노드가 여러개의 list에 포함 될수 없다.
이유 : list가 가장 마지막 멤버일 경우에만 유효 한다.
해결책 : 구조체의 멤버 오프셋 포인터를 이용하면 된다.
0
1000
20
1020
28
1028
"홍길동"
NODE*
NODE*
#define
list_entry(ptr,type,member)
\
((type*)((char*)ptr - (int)&((type*)0)->member ))
문제점 : 하나의 노드가 여러개의 list에 포함 될수 없다.
이유 : list가 가장 마지막 멤버일 경우에만 유효 한다.
해결책 : 구조체의 멤버 오프셋 포인터를 이용하면 된다.
struct list_head {
struct list_head *next, *prev;
};
void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next){
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
void list_add(struct list_head *new, struct list_hea
__list_add(new, head, head->next);
}
void list_add_tail(struct list_head *new, struct lis
__list_add(new, head->prev, head);
}
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr =
(type *)( (char *)__mptr - offsetof(type,memb
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
struct task_struct {
...
struct list_head tasks;
...
struct list_head children;
...
struct list_head sibling;
...
};
struct inode {
...
struct list_head
i_list;
struct list_head
i_sb_list;
struct list_head
i_dentry;
...
};
struct hlist_head
{
struct hlist_node *first;
};
struct hlist_node
{
struct hlist_node *next, **pprev;
};
struct hlist_head head[5] = { 0, };
head
[0]
[1]
[2]
[3]
[4]
10
.next
.pprev
13
.next
.pprev
pid%10
struct hlist_head head[8] = { 0, };
static unsigned int pidhash_shift = 3;
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
static inline u32 hash_32(u32 val=8987, unsigned int
{
u32 hash = val * GOLDEN_RATIO_PRIME_32;
return hash >> (32 - bits);
}
#define hash_long(val, bits) hash_32(val, bits)
#define pid_hashfn(pid)
\
hash_long( pid, pidhash_shift)
first
head
[0] 0
h [1]
[2] 0
[3] 0
n
2000
* .next
** .pprev
1000
0 .next
** .pprev
void hlist_add_head(struct hlist_node *n, struct hlis
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
typedef struct _node
{
int data;
struct _node *left;
struct _node *right;
} NODE;
NODE *root;
1
2
4
3
5
6
7
pedef enum { LEFT, RIGHT } FLAG ;
id insert_data( int data, NODE *s, FLAG flag )
root
NODE *temp;
temp=malloc(sizeof(NODE));
temp->data = data;
temp->left = 0;
temp->right = 0;
if( root == 0 )
{
root = temp;
return;
}
if( flag == LEFT )
s->left = temp;
else if( flag == RIGHT )
s->right = temp;
s
1
tem
2
0
0
3
0
0
in-order traverse
1
left - root - right
2
3
4
void in_order( NODE *temp )
{
4 2
if( temp == 0 )
return ;
in_order( temp->left );
printf("%4d", temp->data );
in_order( temp->right );
}
5
5
1
6
6
3
7
7
in-order traverse
right - root - left
1
void display( NODE *temp )
{
4
int i;
static int indent=-1;
if( temp == 0 )
return ;
indent++;
display( temp->right );
for(i=0; i<indent; i++ )
printf("%4c", ' ' );
printf("%4d\n", temp->data );
display( temp->left );
indent--;
}
2
3
5
6
7
7
3
6
1
5
2
4
void __display( NODE *temp, int (*a)[10],
int *row, int *col )
1
{
if( temp == 0 )
2
3
return ;
++*row;
4
5
6
__display( temp->left );
a[*row][*col] = temp->data;
1
++*col;
2
5
__display( temp->right );
4
5
6
7
--*row;
}
void display( NODE *temp )
{
int a[10][10], row=-1, col=0;
__display( temp , a, &row, &col);
...
O( n );
O( log2n );
int a[7] = { 4 , 2 , 1, 3, 6, 5, 7 };
4
2
1
6
3
5
7
root
if( root == 0 )
{
root = temp;
prev
return;
4
}
p=0
while( p )
0
{
temp
prev = p;
if( p->data > data )
2
p = p->left;
0
else if ( p->data < data )
0
p = p->right;
}
if( prev->data > data )
prev->left = temp;
else
prev->rigth = temp;
}
oid insert_data( int data )
p
**
NODE *temp;
NODE **p = &root;
temp=malloc(sizeof(NODE));
temp->data = data;
temp->left = 0;
temp->right = 0;
while( *p )
temp
{
if( (*p)->data > data )
p = &(*p)->left;
else if ( (*p)->data < data )
1
p = &(*p)->right;
0
}
0
*p = temp;
root
4
0
2
3
0
0
1
2
0 1 2 3 4 5 6
3
4
1 2 3 4 5 6 7
5
6
7
4
2
1
NODE *bal( int *a , int
{
int mid = n/2;
if( n<=0 )
return 0;
temp=malloc();
temp->data = a[mi
temp->left = bal(
temp->right= bal(
return temp;
6
3
5
7
}
AVL
2-3
2-3-4
B
B+
B*
....
RB tree
1
RB tree 공리
1. root 노드는 언제나 검정이다.
2. 새로운 노드는 빨강이다.
RB tree 공리
1
2
1. root 노드는 언제나 검정이다.
2. 새로운 노드는 빨강이다.
RB tree 공리
1
2
3
2
1
3
1. root 노드는 언제나 검정이다.
2. 새로운 노드는 빨강이다.
3. 부모노드가 빨강이면 회전한다.
RB tree 공리
2
1
3
4
2
1
3
4
2
1
3
4
1. root 노드는 언제나 검정이다.
2. 새로운 노드는 빨강이다.
3. 부모노드도 빨강이고 삼촌도
빨강이면 color flip
4. 부모노드가 빨강이면 회전한다.
RB tree 공리
2
0. 밸런스는 root 노드로 부터
모든 단말노드로 가는 경로의
검정 노드의 수가 같으면
맞는 것으로 간주 한다.
1. root 노드는 언제나 검정이다
2. 새로운 노드는 빨강이다.
3. 부모노드도 빨강이고 삼촌도
빨강이면 color flip
4. 부모노드가 빨강이면 회전한다
3
4
5
2
1
4
3
5
RB tree 공리
2
4
3
5
6
2
4
3
5
6
0. 밸런스는 root 노드로 부터
모든 단말노드로 가는 경로의
검정 노드의 수가 같으면
맞는 것으로 간주 한다.
1. root 노드는 언제나 검정이다
2. 새로운 노드는 빨강이다.
3. 부모노드도 빨강이고 삼촌도
빨강이면 color flip
4. 부모노드가 빨강이면 회전한다
RB tree 공리
2
4
3
5
6
2
7
4
3
6
5
7
0. 밸런스는 root 노드로 부터
모든 단말노드로 가는 경로의
검정 노드의 수가 같으면
맞는 것으로 간주 한다.
1. root 노드는 언제나 검정이다
2. 새로운 노드는 빨강이다.
3. 부모노드도 빨강이고 삼촌도
빨강이면 color flip
4. 부모노드가 빨강이면 회전한다
RB tree 공리
2
4
3
0. 밸런스는 root 노드로 부터
모든 단말노드로 가는 경로의
검정 노드의 수가 같으면
맞는 것으로 간주 한다.
1. root 노드는 언제나 검정이다
2. 새로운 노드는 빨강이다.
3. 부모노드도 빨강이고 삼촌도
빨강이면 color flip
4. 부모노드가 빨강이면 회전한다
6
7
5
2
8
4
3
6
7
5
8
4
2
[ 4]
< 2>
[ 1] [ 3]
6
3
5
7
8
< 6>
[ 5] [ 7]
< 8>
2 - 4 - 3
2
4
3
2 - 3 - 4
3 - 2 - 4
2
parent left rotate
3
4
gparent right rotate
color flip
3
2
4
4 - 2 - 3
4
2
4 - 3 - 2
3
3 - 2 - 4
4
3
parent left rotate
2
3
2
gparent right rotate
color flip
4
struct rb_node
{
unsigned long rb_parent_color;
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
struct rb_root
{
struct rb_node *rb_node;
};
struct rb_root root = { 0 } ;
01100100
01101001
rb_parent_color & ~3
rb_parent_color & 1
#define
#define
#define
#define
#define
#define
rb_parent(r)
((struct rb_node *)((r)->rb_pa
rb_color(r)
((r)->rb_parent_color & 1)
rb_is_red(r)
(!rb_color(r))
rb_is_black(r) rb_color(r)
rb_set_red(r) do { (r)->rb_parent_color &= ~
rb_set_black(r) do { (r)->rb_parent_color |=
static inline void rb_set_parent(struct rb_node *rb,
{
rb->rb_parent_color = (rb->rb_parent_color &
}
static inline void rb_set_color(struct rb_node *rb, i
{
rb->rb_parent_color = (rb->rb_parent_color &
}
void rb_link_node(struct rb_node * node, struct rb_no
struct rb_node ** rb_
{
node->rb_parent_color = (unsigned long )paren
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
rb_link
**
1
0 0
0
0
root
2
0 0
0
0
SAWON * __rb_insert_data(struct rb_root* root,
int data,
struct rb_node * node)
{
struct rb_node ** p = &root->rb_node;
struct rb_node * parent = NULL;
SAWON *s;
while (*p)
{
parent = *p;
s = rb_entry(parent, SAWON, tree);
if (data < s->data)
p = &(*p)->rb_left;
else if (data > s->data)
p = &(*p)->rb_right;
else
return s;