알고리즘

OS - Kernel Compile, kernel Message, System Call, Kernel Module

이온시옥 2019. 1. 11. 02:42
반응형

OS (운영체제)

“Kernel Compile, kernel Message, System Call, Kernel Module”


리눅스의 대표적인 우분투를 가상머신 환경에서 설치하여 커널을 분석하고 어떤 식으로 작동하는 지 이해하는 데 목적을 둔다.

기본적인 리눅스 코멘드를 사용하여 커널을 직접 컴파일해 보고 커널의 로그 메세지를 분석하고 로그를 생성해 본다. 커널을 통하여 System Call을 어떻게 작동하는 지 원리를 이해하고 System Call을 생성해 보는 것을 목적으로 둔다.



______________________________________________________________________________________________________________________________



1-1, Linux Installation

맥 OS를 메인 운영체제로 사용하여 페러럴즈 툴을 사용하여 우분투를 설치하였다.

우분투 가상머신의 리소스를 프로세서는 옥타코어, 메모리는 2048로 설정하였다.


계정의 이름은 os2013722015와 컴퓨터 이름은 우분투로 설정하였다.


설치가 완료가 된 우분투 가상머신의 모습이다.



______________________________________________________________________________________________________________________________



1-1, Kernel Compile

page4image32271040

**개인적으로 기존에 설정된 사용환경이 있는 우분투 가상머신을 통해 과제를 수행. (‘os학번’ 우분투 계정은 위의 ‘1-1, Linux Installation’에서만 사용하여 진행)

**mac os x에서 ssh를 사용하여 우분투에 접근 & kernel 3.2.28로 부팅할 경우 가상머신의 인터넷이 불가하여 ssh 가 아닌 우분투에서 수행.

슈퍼권한 $sudo su를 사용하여 모든 명령을 진행하였다. kernel 3.2.28 압축 파일을 wget을 통하여 다운로드를 받았다. 그리고 /usr/src/ 디렉토리로 옮겨주고 압축을 풀었다.


커널 환경설정을 하기 위해서 ncurses를 설치하고 커널 환경설정을 해주었다. Staging drives는 체크를 해제하고 Forced module laoding은 체크를 설정해 주었다. 


그리고 $make 명령어로 8개 프로세서를 사용하여 컴파일을 실행하였다. 컴파일을 하는데 다소 시간이 많이 걸렸다.


커널 컴파일을 완료하고 난 후에 $make modules_install, $make install을 사용하여 컴파일이 된 커널을 리눅스 시스템에 설치를 하고 Boot loader에 설치를 해준다. 그리고 시스템을 리부팅 시켰다.


GRUB을 $vim을 통하여 설정을 해주었다. “GRUB_HIDDEN_TIMEOUT=0”을 주석처리하고 “GRUB +HIDDEN_TIMEOUT_QUIET=false”로 바꾸었다. 시스템을 처음에 켜면 by passing으로 기본 우분트 버전과 커널로 작동이 되지만 선택을 하여 커널과 OS를 고를 수 있게 해줄 수 있게 설정을 바꾸었다. 그리고 재부팅을 하였다.



재부팅을 하고 GNU GRUB에 들어와 졌다. 그리고 Previous Linux versions를 선택하고 아까 전에 컴파 일한 3.2.28 버전으로 부팅을 하였다. 부팅 후에 $uname -r을 사용하여 시스템 버전 3.2.28을 볼 수 있 었다.



______________________________________________________________________________________________________________________________



1-2, kernel messages

첫번째 스크린샷과 같이 cscope 프로그램을 이용하여 version.c 파일을 찾았다. 커널의 맨 처음 initialize 될때 log 기록이 시작되는 파일인 version.c를 vim으로 열어서 리눅스 커널의 버전을 출력해주 는 스트링을 찾아 추가적으로 학번을 뒤에 붙혀넣고 파일을 저장을 하였다.


version.c를 수정 후에 커널을 다시 컴파일을 하고 bootloader에 적재를 하였다. 그리고 $dmesg | less 를 통하여 printk의 log 출력문을 위와 같이 볼 수가 있었다.












1-3, System Call Implementation

/usr/src/linux-3.2.28/arch/x86/kernel/syscall_table_32.S을 vim으로 열어서 add와 multiple을 system call table에 등록하였다.


/usr/src/linux-3.2.28/kernel/ 디렉토리에서 add.c와 multiple.c를 추가하였다. 각각의 파일은 아래와 같이 간단하게 시스템 콜 함수를 구현을 하였다.

그리고 컴파일을 위하여 아래와 같이 kernel 디렉토리 안의 make 파일에 add.o, multiple.o를 추가하였 다. 그리고 make로 커널을 다시 컴파일하고 bootloader에 적재를 하고 시스템을 리부팅하였다.




구현한 커널로 부팅을 하여 add, multiple system call을 사용하여 c언어를 아래와 같이 구현하였다.


그리고 gcc를 통하여 컴파일하고 바이너리를 실행시킨 결과는 아래와 같다.



______________________________________________________________________________________________________________________________



1-4, Modules Implementation


System call 테이블에 sys_my_init, sys_my_exit를 설정해주었다.

위의 스크린샷과 같이 System call 두 함수를 만들어 주었다. 그리고 Kernel 디렉토리 안에 Makefile에 도 위의 두 C파일로 출력이되는 Object 파일도 추가를 해주었다. 그리고 컴파일하고 두 System call이 포함이 된 커널로 리부팅하였다.


System call을 커널 모듈에서 사용하기 위해서는 wrapping을 통한 커널 모듈을 아래와 같이 코드를 구현하였다.



아래의 코드는 wrapping을 통한 커널 모듈을 컴파일하기 위한 Makefile을 작성하였다.


컴파일을 완료하고 hooking.ko kernel binary가 출력이 되었다. insmod를 사용하여 hooking을 커널에 적재하였다. 그리고 rmmod를 사용하여 hooking을 커널에서 할당 해제를 하였다. 결과는 아래의 학번 dmesg처럼 제대로 나타났다.


wrapping kernel module을 위해 수정한 파일은 아래와 같다.

/usr/include/i386-linux-gnu/asm/unistd_32.h
/usr/src/linux-3.2.28/arch/x86/kernel/syscall_table_32.S
/usr/src/linux-3.2.28/kernel/my_init.c
/usr/src/linux-3.2.28/kernel/my_exit.c
/usr/src/linux-3.2.28/kernel/Makefile
/home/eon/Desktop/_module/hooking.c
/home/eon/Desktop/_module/Makefile


리눅스 커널의 전반적인 부분을 알 수 있었다. 과제 1-1에서 리눅스를 가상머신에 설치하여 커널이 오픈 소스로 되어 모든 코드를 공개적으로 볼 수 있는 것이 신기하였다. 또한 make를 통한 커널 컴파일이 처 음에 너무 오래걸렸다. 그리고 가상머신의 프로세서 코어를 원래 듀얼코어였지만 컴퓨터의 자원 모두 사 용하기위하여 옥타코어로 바꿔서 컴파일을 진행하였다. 1-2는 검색툴인 scope를 사용하여 쉽게 함수나 특정 테그 문자를 찾을 수 있었다. 파일의 테그를 처음에 찾는 것이 문제였지 문자를 입력하고 dmesg로 보는 것은 간단하였다. 시스템 콜의 구조를 알 수 있었다. 테이블의 숫자를 참조하여 프로그래머가 직접 시스템콜을 추가하는 것도 알 수 있었다. 1-4는 좀 이해하고 기존의 커널 모듈 프로그래밍이 아닌 wrapping을 통한 커널 모듈이라서 hooking과 복잡한 Makefile로 인해서 처음에 구현하는 데 많은 시간 이 걸렸다. 전반적으로 리눅스 커널의 내부 구조를 이해할 수 있는 계기가 되었다.



반응형