system call 구현 기초 (since 2004) ( 교재에는 7 th 2006 에 포함 )

16
unix/ linux 6.1 System Call 구구 구구 (since 2004) ( 구구구구 7 th 2006 구 구구 ) Linux 커커커 커커커 커커커 커커 커커커 커커 커 커커 커커커커 커커 » 커커 커커 커커커 커커 커커 커커 커커커 커커 커커커 커커 커커커 커커 커커 커커 커커 커커 커커커 커 커커커 » 커커커 커커커 커커커 커커커커 커커커 커커 커커 커커커 커커커 커커커커 커커커커 커커 커커커커커 커커 ( 커 커커커 커커 커커 ) 커커커 커커커커 커커커커 커커 커커 커커 » Fedora 13 커커커 커커 커커 커커 커커커 커 커커커커 /usr/src/kernels 커커커커 커커 커커커 ( 커커 커커 2.6.38.6) » 커커커커 http://www.kernel.org $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux- 2.6.38.6.tar.gz $ ftp ftp.kernel.org Name: anonymous Password: [Enter] cd /pub/linux/kernel » 커커 커커커 커커커 /usr/src/kernels 커커커커 커커 커커 $ tar xvfz linux-2.6.38.6.tar.gz 커커 $ tar xvfj linux- 2.6.38.6.tar.bz2 » 커커커 커커 커커커커커 mylinux 커 커커커 커커 $ ln –s linux-2.6.38.6 mylinux $ ftp ftp.kernel.org id: anonymous password: [Enter] ftp> binary ftp> cd pub/linux/kernel/v2.6 ftp> get linux- 2.6.38.6.tar.gz ( 커커 bz2 커커 ) ppt reader 커커 : $ yum install @libreoffi

Upload: gay-berry

Post on 02-Jan-2016

79 views

Category:

Documents


7 download

DESCRIPTION

System Call 구현 기초 (since 2004) ( 교재에는 7 th 2006 에 포함 ). Linux 커널의 새로운 시스템 호출 구현은 아래 두 가지 작업으로 구성 커널 수정 시스템 호출 번호 할당 시스템 호출 테이블 등록 시스템 호출 처리 함수 구현 커널 컴파일 및 리부팅 새로운 시스템 호출을 이용하는 사용자 수준 응용 시스템 호출을 사용하는 프로그램 작성 라이브러리 작성 ( 꼭 필요한 것은 아님 ) 커널을 수정하기 위해서는 커널 소스 필요 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.1

System Call 구현 기초 (since 2004) ( 교재에는 7th 2006에 포함 )

• Linux 커널의 새로운 시스템 호출 구현은 아래 두 가지 작업으로 구성» 커널 수정

• 시스템 호출 번호 할당• 시스템 호출 테이블 등록• 시스템 호출 처리 함수 구현• 커널 컴파일 및 리부팅

» 새로운 시스템 호출을 이용하는 사용자 수준 응용• 시스템 호출을 사용하는 프로그램 작성• 라이브러리 작성 ( 꼭 필요한 것은 아님 )

• 커널을 수정하기 위해서는 커널 소스 필요» Fedora 13 이상의 경우 커널 개발 패키지를 설치하면 /usr/src/kernels 디렉토리 밑에

설치됨 ( 커널 버전 2.6.38.6)» 다운로드 http://www.kernel.org

$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.38.6.tar.gz

$ ftp ftp.kernel.org Name: anonymous Password: [Enter] cd /pub/linux/kernel

» 커널 소스를 구해서 /usr/src/kernels 디렉토리 밑에 설치$ tar xvfz linux-2.6.38.6.tar.gz 또는 $ tar xvfj linux-2.6.38.6.tar.bz2

» 설치한 소스 디렉토리를 mylinux 로 심볼릭 링크$ ln –s linux-2.6.38.6 mylinux

$ ftp ftp.kernel.orgid: anonymouspassword: [Enter]ftp> binaryftp> cd pub/linux/kernel/v2.6ftp> get linux-2.6.38.6.tar.gz ( 또는 bz2 파일 )

ppt reader 설치 : $ yum install @libreoffice

Page 2: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

2. 프로그램과 기타를 클릭한다

3. 네트워크 연결을 클릭한다

1. 윈도우 환경에서 컴퓨터 네트워크 설정 값을 확인한다Windows: C:\WINDOWS\system32\ipconfig.exeLinux: $ ifconfig

Page 3: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

4. 유선 탭에서 자신의 네트워크 장치클릭하고 IPV4 탭 선택 후 편집을 누른다 .

5. 네트워크 설정 값들을 입력한 후 저장한다 .

IP : 10.80.77.84 ~ 131 넷마스크 : 255.255.255.0게이트웨이 : 10.80.77.254DNS 서버 : 117.16.191.6

※ 할당된 IP 확인 Windows: ipconfig 또는 Linux:

ifconfig

Page 4: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.4

시스템 호출 과정

main{ …syscall(__NR_newsyscall);}

…syscall(){ … movl 338, %eax int $0x80 …} …

ENTRY(system_call) /*arch/x86/kernel/entry_32.S 496*/

SAVE_ALL …. call *sys_call_table(,%eax,4) ….

/*real handler*/asmlinkage int sys_newsyscall(){ printk(…);}

divide_error()

degug()

0x0

nmi()

system_call()0x80

IDT(IVT)

ENTRY(sys_call_table) /*arch/x86/kernel/syscall_table_32.S*/

sys_exit()

sys_fork()

sys_read()

sys_write()

0

1

2

3

4

341 sys_newsyscall()

IDT: Interrupt Descriptor Table= IVT: Interrrupt Vector Table /usr/include/asm/unistd_32.h

/usr/src/kernels/linux-2.6.38.6/arch/x86/include/asm/unistd_32.h

sys_restart_syscall()

Page 5: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.5

syscall

/usr/include/unistd.h 라인 1078

extern long int syscall (long int __sysno, ...) __THROW;

/usr/src/kernels/linux-2.6.38.6/arch/x86/include/asm/unistd_32.h

#define _syscall0(type,name) \

type name(void) \

{ \

long __res; \vi unistd_32.h

__asm__ volatile ("int $0x80" \

: "=a" (__res) \ /* eax register */

: "0" (__NR_##name)); \

__syscall_return(type,__res); \

}

Page 6: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.6

커널 수정 (1)

• 시스템 호출 번호 할당 » Linux 커널이 제공하는 시스템 호출은 각각 고유한 번호를 갖는다

①$ vi /usr/src/kernels/mylinux/arch/x86/include/asm/unistd_32.h 파일 수정

#define __NR_newsyscall 341 ( 새로운 시스템 호출 번호 341 추가 )#define NR_syscalls 342 ( 시스템 호출 개수를 0~341 즉 342 로 수정 )

/* arch/x86/include/asm/unistd_32.h 파일의 내용 */#ifndef _ASM_I386_UNISTD_H_#define _ASM_I386_UNISTD_H_

#define __NR_exit 1#define __NR_fork 2#define __NR_read 3…#define __NR_prlimit64 340#define __NR_newsyscall 341#ifdef __KERNEL__#define NR_syscalls 342

②$ vi /usr/include/asm/unistd_32.h 파일도 똑같이 수정#define __NR_newsyscall 341 ( 새로운 시스템 호출 번호 341 추가 )#define NR_syscalls 342 ( 시스템 호출 개수를 0~341 즉 342 로 수정 )

Page 7: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.7

커널 수정 (2)

• 시스템 호출 테이블 등록» 시스템 호출처리 함수는 sys_call_table 테이블에 등록» sys_call_table 정보는③ $ vi /usr/src/kernels/mylinux/arch/x86/kernel/syscall_table_32.S

에 구현» /* 340 */ 찾은 다음 /* 341 */ 라인에 .long sys_newsyscall 라인을 추가

ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for

restarting */ .long sys_exit .long sys_fork .long sys_read .long sys_write .long sys_open /* 5 */

… .long sys_prlimit64 /* 340 */ .long sys_newsyscall

Page 8: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.8

커널 수정 (3)

• 시스템 호출 처리 함수 구현» 일반 적으로 태스크 관리자 관련 함수는 /usr/src/kernels/mylinux/kernel/ 파일 시스템

관련 함수는 /usr/src/kernels/mylinux/fs/ 밑에 구현» 구현할 함수를 /usr/src/kernels/mylinux/kernel/ 디렉토리 밑에 newsyscall.c 구현

④ $ vi /usr/src/kernels/mylinux/kernel/newsyscall.c 코딩

/* /usr/src/mylinux/kernel/newsyscall.c */#include <linux/linkage.h>#include <linux/unistd.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/sched.h>

asmlinkage int sys_newsyscall(){

printk("Hello Linux, 자기 학번 Sung MeeYoung is in Kernel\n"); return 0;}

⑤ $ vi /usr/src/kernels/mylinux/kernel/Makefile 수정 • obj -y = 라인에 newsyscall.o 추가

Page 9: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.9

커널 수정 (4)

•커널 구성⑥ $ cd /usr/src/kernels/mylinux ( 커널 소스의 상위 디렉토리로 이동 )⑦ $ make mrproper ( 기존의 커널 설정 제거 )

• 커널 버전 2.6 부터 make dep 과 make clean 불필요

⑧ $ cp ../2.6.38.6-26.rcl.fc15.i686.PAE/.config ./⑨ $ make oldconfig ( 실행후 선택문 모두 엔터 )

★ 아래 3 가지 중 한 가지만 실행 ( 재구성할 때는 .config 파일 삭제하고 구성 )1. $ cp ../2.6.38.6-45.fc14.i686.PAE /.config ./ $ make oldconfig ( 실행후 선택문 모두 엔터 )

2. 또는 $ make menuconfig ( 범용적 커널 설정 스크립트 실행 ) -*- Networking supprot - - - > (Select)WiMax, RF switch subsystem 체크 해제

3. 또는 $ make xconfig ( 그래픽 환경 )

Page 10: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.10

커널 수정 (5)

• 커널 컴파일» 옵션은 아래 사이트 참고

http://doc.kldp.org/KoreanDoc/html/Kernel24_Intro-KLDP/Kernel24_Intro-KLDP-2.html

$ make bzImage ( 컴파일 , 새 커널 생성 )

• 커널 인스톨» 모듈로 구성된 커널 내부 구성 요소를 알려주고 , 이후 구성 요소들이 사용될 때 자동으로

커널에 적재되게 함$ make modules ( 모듈 컴파일 )$ make modules_install ( 모듈 인스톨 )

• 생성된 커널을 /boot 디렉토리에 복사$ make install ( 아래 작업 자동 수행 )

[ $ cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.38.6 ][ $ cp System.map /boot/System.map-2.6.38.6 ( 새 System.map 으로 대치 ) ]

• 부트로더 설정

$ vi /etc/grub.conf default=0title Fedora (2.6.38.6) mylinux /* title 수정 */

$ reboot 부팅시에 F5 로 커널 선택화면 전환 후 부트로드에서 새로 컴파일 한 커널 선택 후 부팅

Page 11: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.11

실습 0: newsyscall()

• 사용자 수준 응용 test.c 작성

#include <linux/unistd.h>#include <errno.h>#include <stdio.h>main(){

int i; i=syscall(__NR_newsyscall);

printf(“%d\n”, i);}

$ gcc –o test test.c 컴파일$ ./test 실행

• 결과 확인 방법① $ dmesg | tail② Control-Alt F5 consol 모드 전환 login: root Password: u***l**** Control-Alt F1 graphic 모드 복귀

• 라이브러리 작성 ( 선택사항 )$ gcc –c newsys.c$ ar –r libnew.a newsys.o$ ranlib libnew.a$ vi test.c$ gcc test.c –L /root(libnew.a 있는 디렉토리 ) -

lnew$ ./a.out

/* contents of newsys.c */ … 독립된 파일 #include <linux/unistd.h> #include <errno.h>

call(){ return syscall(__NR_newsyscall);}

/* contents of test.c */ … 독립된 파일main(){

int i;i = call();

}

Page 12: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.12

• sys_gettaskinfo() 라는 커널 정보를 출력하는 새로운 시스템 호출 (342 번 ) 구현» current(/usr/src/kernels/mylinux/arch/x86/include/asm/current.h : 17 행 ) 라는 전역 변수가

task_struct (/usr/src/mylinux/include/linux/sched.h : 1167 행 ) 자료구조를 포인팅$ vi /usr/src/kernels/mylinux/kernel/gettaskinfo.c#include <linux/linkage.h>#include <linux/unistd.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/sched.h>asmlinkage int sys_gettaskinfo(){ int i,cnt =0; printk("PID: %d\n",current->pid); printk("PPID: %d\n",current->parent->pid); if(current->state == -1) printk("Unrunable state\n"); else if (current->state == 0) printk("Runable state\n"); else if (current->state == 1) printk("Interruptable state\n"); else if (current->state == 2) printk("Uninterruptable state\n"); else if (current->state == 4) printk("Stopped state\n"); else if (current->state == 8) printk("Zombie state\n"); else if (current->state == 16) printk("Dead state\n"); else printk("Unkown sate\n"); printk("Priority: %lu\n", current->rt_priority); printk("Scheduling Policy: %lu\n",current->policy); printk("User CPU time: %lu ticks\n", current->utime); printk("System CPU time: %lu ticks\n", current->stime); printk("Start time: %lu \n", current->start_time); printk("Number of major faults: %lu\n", current->maj_flt); printk("NUmber of minot faults: %lu\n", current->min_flt); return(0);}

실습 1: sys_gettaskinfo()

• 사용자 응용 test1.c 작성

#include <linux/unistd.h>

#include <errno.h>

#include <sys/syscall.h>

main()

{

int i;

i=syscall(__NR_gettaskinfo);

}

/* 커널 구성 하지 않고 시스템 호출만 추가 */$ make bzImage$ cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.38.6$ reboot

Page 13: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.13

태스크 리스트

init_task

prev_task next_task prev_task prev_task next_task

…task_struct task_struct

Page 14: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.14

실습 2: getstat()

• sys_getstat(int id, struct mystat *user_buf) 시스템 호출 (342 번 ) 구현 [ 참고서적 ] 리눅스 매니아를 위한 커널 프로그래밍 p70~74

/* 헤더 파일 mystat.h */

struct mystat {

int pid;

int ppid;

/*

* pid_t pid;

* pid_t ppid;

*/

int state;

int priority;

int policy;

long utime;

long stime;

long starttime;

unsigned long min_flt;

unsigned long maj_flt;

int open_files;};

Page 15: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.15

실습 2

• 시스템 호출 처리 함수 getstat.c /* getstat.c */#include <linux/unistd.h>#include <linux/errno.h>#include <linux/sched.h>#include <../arch/x86/include/asm/uaccess.h>#include "mystat.h"#include <linux/slab.h>#include <linux/file.h>asmlinkage int sys_getstat(int id, struct mystat *user_buf){ struct mystat *buf; int i = 0, cnt = 0; struct task_struct *search; search = &init_task; while(search->pid != id) { search = list_entry((search)->tasks.next, struct task_struct, tasks); if(search->pid == init_task.pid) return(-1); } buf = kmalloc(sizeof(struct mystat), GFP_KERNEL); if(buf == NULL) return(-1); buf->pid = search->pid; buf->ppid = search->parent->pid; buf->state = search->state; buf->priority = search->rt_priority; buf->policy = search->policy; buf->utime = search->utime; buf->stime = search->stime; buf->min_flt = search->min_flt; buf->maj_flt = search->maj_flt; copy_to_user((void *)user_buf, buf, sizeof(struct mystat)); return 0;}

• 사용자 응용 test2.c #include <linux/unistd.h> #include <stdio.h> #include <errno.h> #include "mystat.h" #include <stdlib.h> struct mystat *mybuf; int i; int main(int argc, char* argv[]) { int task_number; if(argc != 2) { printf("USAGE: a.out pid\n"); exit(1); } task_number = atoi(argv[1]); mybuf = (struct mystat *)malloc(sizeof(struct mystat)); if(mybuf == NULL) { printf("Out of Memory\n"); exit(1); } printf("PID %d\n",task_number); i = syscall(__NR_getstat, task_number, mybuf); printf("%d\n", i); printf("PID = %d\n", mybuf->pid); printf("PPID = %d\n", mybuf->ppid); if(mybuf->state == -1) printf("Unrunable state\n"); else if(mybuf->state == 0) printf("Running state\n"); else if(mybuf->state == 1) printf("Interruptable state\n"); else if(mybuf->state == 2) printf("Uninterruptable state\n"); else if(mybuf->state == 4) printf(" Stopped state\n"); else if(mybuf->state == 8) printf(" Zombie state\n"); else if(mybuf->state == 16) printf("Dead state\n"); else printf("Unknown state\n"); printf("Priority = %d\n", mybuf->priority); printf("Policy = %d\n", mybuf->policy); printf("Task.utime = %lu\n", mybuf->utime); printf("Task.stime = %lu\n", mybuf->stime); printf("Task.starttime = %lu\n", mybuf->starttime); printf("minor fault = %lu\n", mybuf->min_flt); printf("major fault = %lu\n", mybuf->maj_flt); printf("opened files = %lu\n", mybuf->open_files); return 0; }

Page 16: System Call  구현 기초  (since 2004) ( 교재에는  7 th  2006 에 포함 )

unix/linux

6.16

커널 컴파일과 커널 교체

• 기존의 컴파일된 커널을 수정된 커널로 교체할 때 사용한다» 모듈 컴파일이 완료 된 상태에서 모듈 설정 없이 커널만 수정할 경우 모듈 컴파일은 하지 않고 커널 컴파일과 커널

교체 작업만 한다$ pwd/usr/src/kernels/mylinux$ make mrproper ( 기존의 커널 설정 제거 ) $ cp ../2.6.38.6-26.rcl.fc15.i686.PAE/.config ./$ make oldconfig ( 실행 후 선택문 모두 [Enter])$ make bzImage

• 생성된 커널을 /boot 디렉토리에 복사

$ make install ( 아래 작업 자동 수행하고 새 커널 버전 생성 )

[ $ cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.35.6 ]

[ $ cp System.map /boot/System.map-2.6.35.6 ( 새 System.map 으로 대치 ) ]

새 커널 버전 생성 원하지 않으면 커널 이미지만 복사

$ cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.35.6

• 부트로더 설정

$ vi /etc/grub.conf

default=0

title Fedora (2.6.38.6) mylinux

$ reboot ( 부팅시에 F5 로 커널 선택화면 전환 후 부트로드에서 새로 컴파일 한 커널 선택 후 부팅 )