본문 바로가기
코스웨어/12년 내장형하드웨어

10월 10일 - 리눅스 커널 프로그래밍 chater[3] -(4), 공유폴더에 kernel 옮기기

by 알 수 없는 사용자 2012. 10. 11.
728x90
반응형

 

함수의 메모리 주소를 알고 싶으면 System.map 파일을 확인해보면된다 // 일종의 심볼테이블

 

====================================================================================================================================================

 

리눅스 시스템 호출

 

read, write, open 등의 함수들을 호출했을 때 인터럽트 0x80번이 호출되는데..이렇게 되면 구분을 할수 없다

그래서 호출 전에 함수에 대응되는 인식 번호 를 먼저 읽어 들여서 찾아간다.

 

 

시스템 호출 흐름의 예

 

1. 사용자 프로세스에서 시스템 호출 사용(open())

 

2. C 언어 라이브러리(libc)에서 시스템 호출 준비

시스템 호출에 필요한 인자를 register stack에 넣음

시스템 호출 번호 저장

인터럽트 발생(0x80)

 

3. system_call()

IDT에 의해 인터럽트 시작

sys_call_table 사용

인터럽트 서비스 루틴 실행

 

4. 결과값 사용자에게 반환

 

 

ex) fork()함수 호출 흐름 - fork() 함수는 자기 호출 할때 마다 자기자신을 복사한다

--> user task(fork() 호출)

--> libc.c(호출된 함수의 번호를 저장(fork()는 2번), 0x80인터럽트 발생)

--> IDT(system_call() 실행) // 어셈블리에서 ENTRY(system_call) 로 정의

--> systme_call_table(2.4커널에선 arch/i386/kernel/entry.S에 정의, libc.c에서 저장한 호출번호를 참고로 함수 호출)

 

 

어셈블리와 C 언어로 바라본 시스템 호출

 

C - 이건 별로 설명할게 없으니 패스~

#include <unistd.h>

int main(void)

{

write(1, "Hello, Kernel\n", 14);

return 0;

}

======================================================================================================================

어셈블리

section .data

hello: db 'Hello, Kernel', 10 // 어셈블리에서는 \n를 사용할수 없기 때문에 '문자열' 후에 엔터의 아스키코드 10을 직접입력

helloLen: equ $-hello // $는 현재 메모리 주소, 즉 현재위치 - 문자열 시작 주소 = 문자열의 길이

                               // 바로 문자열의 길이를 넣어줘도 되지만 문자열이 변경됬을때 따로 수정할 필요가 없다.

section .text

global_start

_start:

// 지금부터 write 함수

mov eax, 4 // writ(sys_write) 의 시스템 호출 번호 저장

mov ebx, 1 // stdout을 의미하는 1

mov ecx, hello // 문자열

mov edx, helloLen // 문자열 길이

int 80h // 인터럽트 0x80 발생 -> IDT(Interrupt Descriptor Table) 의 system_call() 에 의해 함수 호출

mov eax, 1 // exit(sys_exit)의 시스템 호출 번호

mov ebx, 0 // exit(0), 종료코드를 0으로 설정

int 80h ; 0x80발생

tip) 시스템 호출 테이블은 sys_call_table에 정의 되어 있으며

2.4.32 커널 - [arch/i386/kernel/entry.S]

2.6.32 커널 - [arch/i386/kernel/syscall_table.S]

에 서 찾아 볼수 있다.

 

======================================================================================================================

 

링크 거는법

[ln -s/(경로)/(파일) (링크이름)] - [ln -s /mnt/hgfs/src/linux-2.* linux-2.*]

 

======================================================================================================================

 

공유 폴더에서 커널(2.4) 컴파일 하기

linux-2.4.32 를 공유폴더에 옮긴다음

공유폴더의 linux-2.4.32 에서 make clean 한다음(기존에 link 되있는것을 삭제)

공유폴더의 linux-2.4.32 - include 폴더에서 asm-i386 을 asm 으로 복사해놓고 [cp -r asm-i386/ asm]

그리고 다시 linux-2.4.32 폴더로 돌아와서 Make file 을 수정한다 (300, 301 line을 주석처리해준다)

그다음 다시 make menuconfig 등 커널 빌드...

 

======================================================================================================================

 

공유 폴더에서 커널(2.6) 컴파일 하기

기존에 있던것을 mv명령으로 옮겼더니 오류가 생기네요 그래서 커널 압축파일을 바로 공유폴더에 넣어서 새로 컴파일 했습니다.

1. make mrproper

2. make menuconfig

3. makefile 을 수정

865 line 을 주석 처리 하고

866 line 에 [@cp -r include/asm-$(ARCH) include/asm] 을 추가 시켜준다.

1293 line 에 있는 rm -r[rm -rf]로 수정

 

make 를 수정한후에 실행 해도 에러가 나는데

이유는 asm-i386은 100개라고 가정하면 menuconfig후엔 2개의 파일이 추가되어 102개가 된다

make에선 asm 파일을 참조하기 때문에 2개의 추가된 헤더 파일을 찾지 못한다 그래서

include 경로에 가서 asm을 지우고 102개가된 asm-i386으로 다시 바꿔주면 된다.

[rm -rf asm]

[cp -r asm-i386 asm]

 

그리고 다시 make & 무한 대기~

 

728x90