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

Slides:



Advertisements
Similar presentations
YES C 제 1 장 C 언어의 개요 1/34 제 1 장 C 언어의 개요 문봉근. YES C 제 1 장 C 언어의 개요 2/34 제 1 장 C 언어의 개요 1.1 프로그램과 C 언어의 특징 1.2 C 언어의 프로그램 구성 1.3 비주얼 C++ 통합 환경 들어가기.
Advertisements

SYSTEM CALL (Syscall) CSLAB SEWON PARK.
FTP 09 SPARCS 박철웅 [dothack].
개발 환경 개발 환경 개요 PXA270과 타겟 시스템 툴체인 환경 구축 JTAG 유틸리티 미니컴 Make 유틸리티
C 프로그래밍.
Linux System Programming
Kernel Programming Kernel
Kernel Porting Lecture #7.
System Call Linux Kernel 수업 3번째.
제4장 Cross Compiler 설치.
Signal & Inter-Process Communication
FUSING.
임베디드 프로그래밍 Lecture #
디바이스 드라이버 기초 디바이스 드라이버의 개요 파일 연산 디바이스 드라이버 등록 디바이스 드라이버 구성
디바이스 드라이버.
이식성과 데이터형 서로 다른 프로세서 상에서의 이식성을 위해 가급적 리눅스 커널이 제공하는 데이터형을 사용하는 것이 좋다.
디바이스 드라이버 개요 가상 디바이스드라이버 실습
Department of Computer Engineering
1 유닉스 시스템 프로그래밍 개요.
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
목차 커널의 개념 및 기능 커널 포팅 램디스크.
6 프로세스 생성과 실행.
Linux System Programming
인터넷 주소 변환 School of Electronics and Information. Kyung Hee University.
System Call 구현 기초 (since 2004) (교재에는 7th 2006에 포함)
임베디드 시스템 개론 3주차 Embedded System..
FND (Flexible Numeric Display)
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express.
Department of Computer Engineering
리눅스 명령어 실습 임베디드 시스템 I.
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 02. 프로그램의 기본구성.
Linux Kernel Programming newsyscall (since 2004~ textbook 7th 2006~)
Linux Kernel Programming newsyscall (since 2004~ textbook 7th 2006~)
fork로 생성한 자식 프로세스에서 exec 함수군을 호출
멀티쓰레드 기반의 서버구현 School of Electronics and Information.
제15장 전처리 및 비트연산.
Internet Protocol and Programming
Term Project Team Member
Operating System 5주차 - System Call Analysis -
6장 파일 및 레코드 잠금.
커널 모듈 프로그래밍 (Kernel Module Programming)
HBE-SMIII-SV210 리눅스 커널과 디바이스 드라이버
실시간 자원 량 정보 제공을 결합한 Heartbeat
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
5 프로세스 정보.
HW 1 : 운영체제 기본 이해 (3월 30일 금까지) 1장 창틀 채우기 (텍스트 파일에 설명하거나 그림 파일로 제출)
제 11 장 전처리기.
adopted from KNK C Programming : A Modern Approach
문자 디바이스 드라이버 임베디드 시스템.
Signal & Inter-Process Communication
Linux Kernel Programming newsyscall (since 2004~ textbook 7th 2006~)
C언어 프로그래밍의 이해 Ch13. 선행처리기와 주석문.
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
컴퓨터 프로그래밍 기초 - 4th : 수식과 연산자 -
쉽게 풀어쓴 C언어 Express 제15장 전처리 및 비트연산 C Express Slide 1 (of 29)
함수와 변수 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
Internet Protocol and Programming
제어문 & 반복문 C스터디 2주차.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
Stepper Motor 디바이스 드라이버
Department of Computer Engineering
Kernel Programming Kernel
GDB - GNU Debugger 김진용.
Internet Protocol and Programming
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
2015 OS Linux Kernel Programming
argc, argv 의 사용방법 #include <stdio.h>
Signal & Inter-Process Communication
C 13장. 입출력 라이브러리 #include <stdio.h> int main(void) { int num;
이성준 Library 만들기 이성준
Presentation transcript:

System Call 구현 기초 Linux 커널의 새로운 시스템 호출 구현은 아래 두 가지 작업으로 구성 커널 수정 시스템 호출 번호 할당 시스템 호출 테이블 등록 시스템 호출 처리 함수 구현 커널 컴파일 및 리부팅 새로운 시스템 호출을 이용하는 사용자 수준 응용 시스템 호출을 사용하는 프로그램 작성 라이브러리 작성(꼭 필요한 것은 아님) 커널을 수정하기 위해서는 커널 소스 필요 Fedora 13 이상의 경우 커널 개발 패키지를 설치하면 /usr/src/kernels 디렉토리 밑에 설치됨 (커널 버전 2.6.35.6) 다운로드 http://www.kernel.org $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.35.6.tar.gz $ ftp ftp.kernel.org 커널 소스를 구해서 /usr/src/kernels 디렉토리 밑에 설치 $ tar xvfz linux-2.6.35.6.tar.gz 또는 $ tar xvfj linux-2.6.35.6.tar.bz2 설치한 소스 디렉토리를 mylinux로 심볼릭 링크 $ ln –s linux-2.6.35.6 mylinux $ ftp ftp.kernel.org id: anonymous password: [Enter] ftp> binary ftp> cd pub/linux/kernel/v2.6 ftp> get linux-2.6.35.6.tar.gz (또는 bz2 파일)

시스템 호출 과정 ENTRY(system_call) /*arch/x86/kernel/entry_32.S SAVE_ALL …. call *SYMBOL_NAME(sys_call_table)(,%eax,4) ret_from_sys_call(schedule, signal, bh_active, nested interrupt handling) main { … syscall (__NR_newsyscall); } IDT(IVT) 0x0 divide_error() degug() nmi() sys_call_table … … newsyscall() { movl 338, %eax int $0x80 } 0x80 system_call() 1 2 3 4 sys_exit() /*real handler*/ sys_newsyscall() { printk(…); } … sys_fork() sys_read() sys_write() 338 sys_newsyscall() IDT: Interrupt Descriptor Table = IVT: Interrrupt Vector Table

커널 수정 (1) 시스템 호출 번호 할당 Linux 커널이 제공하는 시스템 호출은 각각 고유한 번호를 갖는다 /usr/src/kernels/mylinux/arch/x86/include/asm/unistd_32.h 파일에 구현되어 있다 #define __NR_newsyscall 338 을 추가한다 시스템 호출 개수를 0~338 즉 339로 수정한다 /* 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_recvmmsg 337 #define __NR_newsyscall 338 #ifdef __KERNEL__ #define NR_syscalls 339 /usr/include/asm/unistd_32.h 파일도 똑같이 수정해 준다.

커널 수정 (2) 시스템 호출 테이블 등록 시스템 호출처리 함수는 sys_call_table이라는 테이블에 등록이 되어 있어야 한다 sys_call_table 정보는 /usr/src/kernels/mylinux/arch/x86/kernel/syscall_table_32.S 파일에 구현되어 있다 /*335*/ 찾은 다음 /*338*/ 라인에 .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_rt_tgsigqueueinfo /* 335 */ .long sys_perf_event_open .long sys_recvmmsg .long sys_newsyscall

커널 수정 (3) 시스템 호출 처리 함수 구현 일반 적으로 태스크 관리자 관련 함수는 /usr/src/kernels/mylinux/kernel/ 파일 시스템 관련 함수는 /usr/src/kernels/mylinux/fs/ 밑에 구현 되어 있다. 구현할 함수를 /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, 7777777 SUNG MeeYoung is in Kernel\n"); return 0; } /usr/src/kernels/mylinux/kernel/Makefile 수정 obj -y = 라인에 newsyscall.o 추가

커널 수정 (4) 커널 구성 $ cd /usr/src/kernels/mylinux (커널 소스의 상위 디렉토리로 이동) $ make mrproper (기존의 커널 설정 제거) 커널 버전 2.6부터 make dep 과 make clean 불필요 아래 3 가지 중 한 가지만 실행 (재구성할 때는 .config 파일 삭제하고 구성) $ make menuconfig (범용적 커널 설정 스크립트 실행) -*- Networking supprot - - - > (Select) WiMax, RF switch subsystem 체크 해제 (또는 $ make xconfig (그래픽 환경) (또는 $ cp ../2.6.35.6-45.fc14.i686.PAE /.config ./ $ make oldconfig (실행후 선택문 모두 엔터)

커널 수정 (5) 커널 컴파일 커널 인스톨 생성된 커널을 /boot 디렉토리에 복사 부트로더 설정 옵션은 아래 사이트 참고 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.35.6 $ cp System.map /boot/System.map-2.6.35.6 (새 System.map으로 대치 ) 부트로더 설정 $ vi /etc/grub.conf default=0 title Fedora (2.6.35.6) 수정 $ reboot 부팅시에 F5로 커널 선택화면 전환 후 부트로드에서 새로 컴파일 한 커널 선택 후 부팅

사용자 수준 응용 작성 #include <linux/unistd.h> 사용자 프로그램 test.c 작성 #include <errno.h> #include <stdio.h> main() { int i; i=syscall(__NR_newsyscall); printf(“%d\n”, i); } $ gcc –o test test.c 컴파일 $ ./test 실행 Control-Alt F5 consol 모드 전환 Control-Alt F1 graphic 모드 복귀 $ dmesg | tail 결과 확인 라이브러리 작성(선택사항) $ 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(); /* /usr/unistd.h : line 1025 */ extern long int syscall (long int __sysno, ...) __THROW; /* /usr/src/mylinux/include/asm-i386/unistd.h (old version)*/ #define _syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ /* eax register */ : "0" (__NR_##name)); \ __syscall_return(type,__res); \ }

실습 1: sys_gettaskinfo() current(/usr/src/kernels/mylinux/arch/x86/include/asm/current.h : 17행)라는 전역 변수가 task_struct (/usr/src/mylinux/include/linux/sched.h : 1167행) 자료구조를 포인팅 #include <linux/linkage.h> #include <linux/unistd.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/sched.h> //#include <linux/file.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); } 사용자 응용 test1.c 작성 #include <linux/unistd.h> #include <errno.h> #include <sys/syscall.h> main() { int i; i=syscall(__NR_gettaskinfo); }

태스크 리스트 init_task prev_task next_task … task_struct

실습 2: getstat() sys_getstat(int id, struct mystat *user_buf) 시스템 호출(340번) 구현 [참고서적] 리눅스 매니아를 위한 커널 프로그래밍 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;};

실습 2 사용자 응용 test2.c 시스템 호출 처리 함수 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) 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"); 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;

커널 컴파일과 커널 교체 기존의 컴파일된 커널을 수정된 커널로 교체할 때 사용한다 생성된 커널을 /boot 디렉토리에 복사 모듈 컴파일이 완료 된 상태에서 모듈 설정 없이 커널만 수정할 경우 모듈 컴파일은 하지 않고 커널 컴파일과 커널 교체 작업만 한다 $ pwd /usr/src/kernels/mylinux $ make mrproper (기존의 커널 설정 제거) $ cp ../2.6.35.6-45.fc14.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으로 대치 ) 새 커널 버전 생성 원하지 않으면 커널 이미지만 복사 부트로더 설정 $ vi /etc/grub.conf default=0 title Fedora (2.6.35.6) mylinux $ reboot (부팅시에 F5로 커널 선택화면 전환 후 부트로드에서 새로 컴파일 한 커널 선택 후 부팅)

Vi 편집기에서 한글이 깨져서 나올시 접속한 원격 호스트에서 아래 시행하여 지원 폰트 확인 $ unset LANG $ LANG=C $ locale –a /* locale: locale specific information */ 로컬 linux 호스트의 /etc/sysconfig/i18n 설정을 다음과 같이 변경 LANG=“ko_KR” (또는 “ko_KR.eucKR”, “ko_KR.EUC”, “ko_KR.euckr” 등 $ locale 결과) SUPPORTED="en_US.iso885915:en_US:en:ko_KR.eucKR:ko_KR:ko" SYSFONT="lat0-sun16" SYSFONTACM="iso15" 관리자가 바꿔주지 않는다면 ~/.bashrc 에 다음을 추가 LANG=“ko_KR” SUPPORTED=“en_US:en_US.iso885915:en:ko_KR.eucKR:ko_KR:ko” SYSFONT=“latarcyrheb-sun16” export LANG SUPPORTED SYSFONT Desktop GUI 메뉴에서도 터미널 설정 메뉴 한글 코딩 방식을 “eucKR” 로 설정

네트워크 설정방법 netconfig 또는 redhat-config-network명령을 실행하거나 메뉴에서 시스템 설정에 네트워크를 실행 후 eth0 선택 후 편집을 누른다 (위와 같이 장치가 잡혀있지 않으면 커널 컴파일 후 모듈설치)

네트워크 설정 그림과 같이 설정한다 (ip주소에는 해당 컴퓨터의 주소 입력) 입력이 완료 되면 확인을 누른후 DNS설정을 한다

네트워크 설정 호스트명에는 해당 자리의 컴퓨터 이름을 넣는다 (예)stu01 설정 완료 후 재부팅하거나 장치를 비활성화 시켰다가 다시 활성화 시킨다 ping 117.16.244.56 실행 후 응답이 제대로 오면 성공