1.02k likes | 1.48k Views
임베디드 소프트웨어 프로그래밍 시스템 콜 프로그래밍. 임베디드 S/W 기술센터. 이 자료는 ETRI 에서 제공한 것이며 , 무단 수정이나 출판 등을 금합니다 . 시스템 콜 프로그래밍 System Call Programming. Linux 커널의 특징. 선점형 멀티테스킹 운영체제 소스 코드 및 이진 코드의 호환성 (UNIX, POSIX) 보호모드 지원 다양한 파일 시스템 사용 가능 EXT2, EXT3, ReiserFS, XFS,… 네트워킹 BSD 소켓 , System V IPC 다양한 플랫폼 지원
E N D
임베디드 소프트웨어 프로그래밍 시스템 콜 프로그래밍 임베디드 S/W 기술센터 이 자료는 ETRI에서 제공한 것이며, 무단 수정이나 출판 등을 금합니다.
시스템 콜 프로그래밍 System Call Programming ESP 교안 2부 4장
Linux 커널의 특징 • 선점형 멀티테스킹 운영체제 • 소스 코드 및 이진 코드의 호환성(UNIX, POSIX) • 보호모드 지원 • 다양한 파일 시스템 사용 가능 • EXT2, EXT3, ReiserFS, XFS,… • 네트워킹 • BSD소켓, System V IPC • 다양한 플랫폼 지원 • X86, ARM, PPC, MIPS, ALPHA,… • 모노리딕(Monolithic) 커널 • 구조적 단점을 보완하기 위한 모듈 방식 채용 • 모듈: 커널의 확장성을 증가 ESP 교안 2부 4장
User Program & Application Library User Level Kernel Level System Call Interface Memory Management Virtual File System Process Management Buffer Char Block Device Driver Kernel Level Hardware Control H/W Level Hardware Control Linux 커널 구조 ESP 교안 2부 4장
Linux 커널 구조(2) • 커널(kernel) 이란 ? • 메모리에 상주하여 시스템 구동에 필요한 환경을 만들고 관리하는 소프트웨어로써 H/W와 인터럽트 등을 통해 통신하고, 사용자 Application과 시스템 호출 인터페이스 등을 통해 통신하는 소프트웨어 • 작은 의미의 OS 자체 • 시스템 내의 모든 리소스(H/W, S/W) 관리 • 응용 프로그램에게 서비스 제공 • 다중 프로세스 생성 및 프로세스 사이의 스케줄링 • 모든 시스템 호출을 처리 • 내장형 시스템내의 주변 장치 제어 ESP 교안 2부 4장
Linux 커널 내부구조도 ESP 교안 2부 4장
커널의 상호작용 ESP 교안 2부 4장
사용자 모드 Vs. 커널 모드 • 보호 모드 및 가상 메모리 사용 가능 • 리얼 모드: 오래된 시스템에 대한 호환 유지, OS Bootstrap에서 이용 • 보호 모드: 물리 메모리를 매핑하는 가상 주소를 이용, 리눅스에서 커널 공간과 사용자 주소 공간을 분리 • 사용자 모드(User Mode) • 사용자 주소 공간에서 프로세스 코드를 실행 • 커널 주소 공간을 침범할 수 없음 • 커널 모드(Kernel Mode) • 커널 코드 실행 • CPU에서 제한된 명령 수행 • 예외 처리 및 인터럽트 처리 • 하드웨어에 대한 직접적인 접근이 가능 • 사용자 프로세스의 문맥에서 시스템 콜 처리 ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 • 프로세스 란? • 프로그램 실행을 위한 시스템 자원 • 메모리, 파일, 입출력장치, CPU 시간 등 • 자원들이 할당되어 수행 가능한 상태에 있는 프로그램 ->프로세스 • 프로세스는 시스템 내에서 처리될 수 있는 기본 단위, 수행되기 위한 문장들의 집합 • 한 프로세스를 구성하는 문장 내에는 동시 처리(concurrent processing)를 요구하는 특징들과 시스템에 도움을 요구하기 위한 시스템 호출과 같은 특징들을 포함 • 프로그램 세그먼트 외에 수행에 필요한 자료들을 유지하고 있는 데이터 세그먼트를 가지고 있음 • 프로세스 생성 • 프로세스를 위한 새로운 프로세스 인스턴스(instance)를 만들어야 함 • 프로세스 인스턴스는 한 PCB(Process Control Block)를 가짐 ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 (2) • 내장형 시스템을 지원하는 명령어 예 ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 (3) • 프로세스 관리 • 프로세스의 생성, 소멸 • TASK_STRUCT 구조체 – 실행중인 프로세스의 정보를 유지 • 프로세스간 관계 • 프로세스 스케줄링 • SCHED_RR, SCHED_FIFO 등의 실시간 스케줄링 알고리즘 제공 P0 p_cptr p_pptr p_ysptr P1 P2 P3 p_osptr P4 ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 (4) • 프로세스 상태 • 수행 중(Running) • 프로세스가 현재 CPU를 사용하고 있다는 것을 의미 • 수행가능(Runnable) • 프로세스가 CPU를 사용할 수 있게 되면, 바로 사용할 수 있음을 의미 • 잠듦(Sleeping) • 프로세스가 어떤 사건이 발생하기를 기다리는 것을 의미. • 만약 프로세스가 read() 시스템 호출을 실행하였다면, 입출력 요구를 마칠 때까지 잠듦 • 일시 중지(Suspended) • 프로세스가 SIGSTOP 같은 시그널에 의해서 “frozen" 되어 있다는 것을 의미. • 그 프로세스는 SIGCONT 신호가 보내졌을 때만 재개. • 키보드로부터의 Control-Z 입력은 전면작업(foreground job) 내에 있는 모든 프로세스를 일시 중지 시킴 • 쉼(Idle) • 프로세스가 fork() 시스템 호출에 의해서 생성되었으나, 아직 실행할 수 없다는 것을 의미 • 터미네이트(Terminate) • 프로세스가 종결되었으나, 자신의 부모에게 종료 코드를 아직 반환 하지 않았다는 것을 의미. • 프로세스는 그들의 부모가 wait() 시스템 호출을 사용하여 반환 코드를 받아들일 때까지 남아 있음 ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 (5) • 프로세스 상태도 ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 (6) • 프로세스 구성 • 코드 영역 (code area) • 프로세스의 실행할 수 있는 부분을 포함한다. • 자료 영역 (data area) • 정적자료를 포함하기 위하여 프로세스에 의해서 사용된다. • 스택 영역 (stack area) • 일시적인 자료를 저장하기 위하여 프로세스에 의해서 사용됨 • PCB 영역 (user area) • 프로세스에 대한 관리(housekeeping) 정보를 가지고 있다. • 힙 영역 (heap area) • 메모리 관리 시스템에 의하여 사용된다. ESP 교안 2부 4장
Linux 커널의 구성 –프로세스 관리 (7) • 실시간 프로세스 스케줄링 정책 • 타임 슬라이스(time-slice) 기반의 라운드로빈(round-robin) • FIFO (First-input First-output) • 우선순위 기반의 스케줄링 정책 • 긴급성(criticalness) 반영한 스케줄링 정책 • 실시간 스케줄링을 위해서는 적합성(eligibility) 및 우선순위(priority) 등을 고려하여 스케줄링을 해야함 ESP 교안 2부 4장
Linux 커널의 구성 (2) • 메모리 관리 • 시스템 성능과 밀접한 관련 • 가상 주소 영역 관리, 프로세스에 자원 할당 정책관리 • X86기반의 리눅스 커널은 세그멘테이션과 페이징을 사용 • page 구조체 • 커널이 물리 메모리를 관리 하기 위한 모든 정보를 유지 • 리눅스는 3 단계 페이지 테이블 유지 • Motorola 계열의 CPU에서는 1 단계 해시 알고리즘을 이용한 페이징 사용 • 각 프로세스는 자신만의 가상 주소 공간을 가짐 • 32비트 주소 공간에서는 4GB 가상 메모리 공간을 사용 가능 • High memory vs. Low memory • High memory: 논리 주소가 없는 메모리, • Low memory: 커널 영역에서 존재하는 논리 주소 메모리 • 요구 페이징 기법 및 캐시 사용 ESP 교안 2부 4장
Linux 커널의 구성 (3) • 파일 시스템 • 리눅스(유닉스)는 모든 것을 파일로 취급하여 처리 • VFS에 의한 다양한 파일시스템 지원 • 디스크의 물리적 구조를 논리적인 구조로 표현 • 블록 입출력을 위한 버퍼캐시 관리기법 제공 ESP 교안 2부 4장
Linux 커널의 구성 (4) • 리눅스 VFS(Vitual File system Switch) Layer Tasks System Call Interface Virtual File System proc … ext2 ReiserFS Buffer Cache 디바이스 드라이버 Hardware ESP 교안 2부 4장
Linux 커널의 구성 (5) • VFS의 역할 • 표준 유닉스 파일 시스템과 관련된 모든 시스템 콜을 처리하는 계층 • Common File Model • superblock object – 마운트 된 파일시스템의 정보, file system control block과 일치 • inode object - 특정 파일에 대한 정보 • file object - 열려있는 파일과 프로세스에 관한 정보, 커널 메모리에 존재 • dentry object - 디렉터리 엔트리와 연결된 정보 • 프로세스와 VFS 객체간의 상호작용 디스크 superblock object inode object 프로세스 1 file object dentry object dentry object 프로세스 1 file object ESP 교안 2부 4장
Linux 커널의 구성 (6) • 디바이스 제어 • 커널에서 물리적 장치를 제어 • 디바이스 드라이버에서 각 장치의 행위를 기술 • 입출력 요청을 스케줄링 • 인터럽트 요청 및 처리 • 네트워크 • 네트워크 서브시스템과 디바이스 드라이버로 구성 • 통신 프로토콜 구현 ESP 교안 2부 4장
리눅스의 타이머 인터럽트 • 타이머 인터럽트 핸들러 호출 • 시스템 시작때부터 얼마나 시간이 지났는지 값을 유지 • jiffies 값으로 유지 • time과 date를 업데이트 시킴 • 현재 프로세스가 얼마나 오랫동안 CPU를 점유하고 사용되었는지 점검하고, 주어진 퀀텀을 소모했으면 중지(preemption) 시킴 • 통계 유지 • 각 프로세스의 CPU 사용 시간 업데이트(유저 영역, 시스템 영역) • 타이머 큐에 들어 있는 작업 처리 • 타이머 큐에는 일정한 시간에 수행되어야 할 커널 루틴이 함수로 등록됨 • 주어진 시간이 만료된 큐의 함수들에 대한 처리를 수행 struct timer_struct { unsigned long expires; void (*fn) (void); } ESP 교안 2부 4장
작업 수행 중 CPU 타이머 인터럽트 핸들러 일정한 주기로 인터럽트 발생 PIC IRQ0 IRQ1 IRQ2 IRQ3 8254 ESP 교안 2부 4장
비주기적 타이머 인터럽트 • 리눅스 커널은 10 밀리 세컨드의 일정한 주기로 타이머 인터럽트가 수행되며, 최소 10 밀리 세컨드의 간격으로 특정한 작업 수행가능 • 세밀한 시간 단위에서 커널에서 인터럽트를 받아서 작업을 하기 위해서는 비주기적인 타이머 프로그램 방법을 사용 CPU 타이머 인터럽트 핸들러 타이머 칩 타이머 인터럽트를 받고 싶은 시간만큼 타이머 칩을 프로그램 8254 PIC IRQ0 IRQ1 IRQ2 IRQ3 ESP 교안 2부 4장
세밀한 시간 측정 • TCS를 활용해서 측정 구간의 앞뒤에서 rdtsc 호출 a = RDTSC 시간 측정 구간 b = RDTSC 총걸린 시간 = (b – a) * (rdtsc의 한주기 시간) ESP 교안 2부 4장
시스템 콜 • 시스템 콜 호출 절차 • 사용자 프로그램에서 라이브러리 함수 호출 • libc.a • 인수를 스택에 저장 • 시스템 콜 번호 저장 • 0x80 인터럽트를 생성(소프트웨어 인터럽트, 트랩) • _system_call() • IDT에 의해 트랩처리 시작 • 인터럽트 핸들러 실행 • 시스템 콜 테이블 • 시스템 콜 번호 :$(TOPDIR)/include/asm/unistd.h에 정의 #define __NR_exit 1 #define __NR_fork 2 #define __NR_read 3 … #define __NR_vfork 190 ESP 교안 2부 4장
시스템 콜 (2) • 시스템 콜 정의 : $(TOPDIR)/arch/i386/kernel/entry.S에 정의 • 시스템 콜의 추가 • 커널 수정 • 추가할 시스템 콜 코드 작성, 커널에 포함 • 시스템 콜 번호 할당 • sys_call_table에 등록 • 새로운 시스템 콜을 사용하는 응용 프로그램 작성 .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_exit) .long SYMBOL_NAME(sys_fork) … .long SYMBOL_NAME(sys_vfork) ESP 교안 2부 4장
시스템 콜 (3) ESP 교안 2부 4장
Real-time Linux • RT-Linux • 리눅스 커널 하부에 서브 커널의 형태를 둠 • 서브 커널이 H/W 신호를 가로채어 실시간 태스크들에 우선 제공 • 경성 실시간 처리 지원 • 유사 프로젝트로 RTAI등이 존재 • Linux 선점 패치 • 커널 영역 내부에서 일부분 선점이 가능하도록 함 • 멀티미디어 처리 등의 연성 실시간 처리에 적당 • 패치 파일 형태로 제공( ≤v2.4) • Timesys Linux • Linux 선점 패치와 유사 • 인터럽트를 쓰레드 방식으로 처리 • 연성 실시간 처리 제공 • 이 외에 Montavista Linux, Linux/RK, Kurt, ADEOS등 ESP 교안 2부 4장
리눅스 커널 v2.6 • 성능과 확장성 향상 • SMP 지원 강화 : SMP에서 NUMA 지원 • 임베디드 시스템을 위한 새로운 프로세서 타입 추가 지원 • 스케줄러 향상 – O(1) 알고리즘 • SMP 효율성 증가, 로드 밸런싱 향상 • 커널 선점 지원 • 부분적인 커널 태스크 실행에서 선점 가능 -> 응답성 증가 • 다양한 파일 시스템 • JFS, XFS 지원 • 디바이스 드라이버 모듈 개발을 위한 API 일부 변경 • module_init(), module_exit() 으로 변경 • xxx.o 모듈에서 xxx.ko 모듈로 변경 • 메모리 관리 및 가상 메모리의 변화 ESP 교안 2부 4장
IPC의 목적 • 데이터 전송(data transfer) • 데이터 공유(sharing data) • 이벤트 전송(event notification) • 자원 공유(resource sharing) • 프로세스 제어(process control) ESP 교안 2부 4장
IPC 종류 • pipe(half duflex) • FIFO (named pipes) • stream pipe(full duflex) • named stream pipes • message queues • semaphore • socket • stream ESP 교안 2부 4장
세마포어 • 세마포어는 다중 프로세서에게 공유 자원을 접근하는 허가를 관리하는 카운터 • 공유 자원 접근 과정 • 자원을 제어하는 세마포어 테스트 • 세마포어가 양의 정수이면 자원에 접근 가능 • 세마포어를 1만큼 감소 – 자원의 한 부분을 사용중임 표시 • 세마포어가 0 인 경우 • 세마포어값이 0보다 커질때까지 sleep • wake up 이 된 경우 첫번째 단계로 되돌아감 • 공유 자원을 사용하고 난 후 세마포어를 증가시킴 • 세마포어의 증감은 원자 연산(atomic operation)이 되어야 함 • 일반적인 형태는 binary semaphore로 구현됨 ESP 교안 2부 4장
메시지 큐 • 커널에 연결 리스트 형태로 저장된 메시지 • 메시지 큐 식별자로 구분됨 • 관련 함수(related function) • msgget : 새로운 큐를 생성하거나 이미 존재하는 큐를 개방 • msgsnd : 큐에 새로운 메시지가 추가 • msgrcv : 큐에서 메시지를 읽어옴 • 각 큐는 msqid_ds 구조체를 하나씩 유지함 ESP 교안 2부 4장
메시지 수신 • Type 아큐먼트는 수신될 메시지를 지정 • type == 0 • 큐에 있는 첫번째 메시지가 리턴 • type > 0 • 큐에 있는 메시지 중에서 type과 같은 메시지가 리턴 • type < 0 • type 의 절대값보다 작거나 같은 메시지 타입을 가지고 있는 메시지 리턴 • Flag • msgsnd와 같은 의미를 지님 #include <sys/ipc.h> int msgrsv(int msqid, void *ptr, size_t nbytes, long type, int flag); ESP 교안 2부 4장
physical memory B logical address space for process A logical address space for process B A A B A B 공유메모리 공유 메모리 • 공유 메모리를 사용하면 서로 관련이 없는 프로세스들이 같은 물리 메모리를 사용할 수 있음 • 실행중인 두개의 프로세스 사이의 데이터 전송에 효율적인 방법 • 동시성 제어는 프로그래머가 해결 ESP 교안 2부 4장
공유 메모리 생성 • 리턴값 : 공유 메모리 식별자 • 공유 메모리의 제한(리눅스 커널 2.2 기준으로 조사) #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); ESP 교안 2부 4장
시그널 개념 • 시그널은 프로세스 또는 프로세스의 그룹에게 보낼 수 있는 매우 짧은 메시지를 지칭 • 시그널의 목적 • 프로세스가 특별한 이벤트에 대해서 반응할 수 있게 함 • 프로세스가 가지고 있는 시그널 핸들러를 통해서 작업을 수행 • 현재 리눅스는 31개의 시그널을 가지고 있음 • 시그널의 특성은 상대 프로세스가 어떤 수행 상태에 있는지 상관없이 메시지를 보낼 수 있음 • 수행중아 아닌 프로세스에게 시그널을 보내는 경우, 해당 프로세스가 문맥전환이 되면서 시그널을 핸들링함 • 시그널을 전송했으나 아직 처리가 되지 않은 시그널을 pending signal 이라 함 • pending signal에게 같은 종류의 시그널이 반복해서 전송되는 경우 무시 ESP 교안 2부 4장
리눅스 시그널 리스트 ESP 교안 2부 4장
signal action • A • Default action is to terminate the process. • B • Default action is to ignore the signal. • C • Default action is to dump core. • D • Default action is to stop the process. • E • Signal cannot be caught. • F • Signal cannot be ignored. • G • Not a POSIX.1 conformant signal. ESP 교안 2부 4장
시그널 기능(2) • SIGABRT • process abort signal • abort() 에 의해서 불려짐 • core dump • 디버깅을 목적으로 프로세스의 현재 상태를 나타내는 정보를 디스크로 저장 • SIGALRM • alarm clock • 타이머가 expired 되었다는 신호 • 모든 프로세스는 최소한 세개 이상의 인터벌 타이머(interval timer)가 존재 • SIGBUS • BUS error • 하드웨어 폴트가 감지됨 • 비정상적으로 프로세스 종료 ESP 교안 2부 4장
시그널 기능 (3) • SIGCHLD • child process terminated or stopped • 자식 프로세스가 종료하거나 멈추는 경우 발생 • 기본적으로 부모 프로세스는 SIGCHLD 무시 • SIGCONT • continue executing if stopped • job control signal • SIGSTOP에 의해서 멈춘 작업을 재개시킴 • SIGFPE • 부동 소수 예외 • 비정상적 종료 • SIGHUP • hangup signal • control terminal에 접속해 있는 모든 프로세스에게 커널이 시그널 전송 ESP 교안 2부 4장
시그널 기능 (4) • SIGILL • illegal instruction • 프로그램이 깨졌을 경우에 발생(corrupted) • SIGINT • interrupt • 사용자가 인터럽트 키를 누른 경우 • SIGKILL • kill • 하나의 프로세스가 다른 프로세스에게 보내는 특별한 시그널 • 예를 들어 시스템 셧 다운 • ignored 되거나 caught 될 수 없음 • SIGPIPE • Write on a pipe or socket when recipient has terminated ESP 교안 2부 4장
시그널 기능 (5) • SIGQUIT • quit • SIGINT와 유사 • 비정상적 종료, core dump • SIGSEGV • 잘못된 주소 참조-segmentation violation • SIGSTOP • stop executing • 현재 수행중인 작업을 중지 • SIGUSR1, SIGUSR2 • 사용자의 목적에 따라서 사용 가능한 시그널 ESP 교안 2부 4장
정상 종료 및 비정상 종료 • 대부분의 시그널은 정상 종료 : _exit 호출 • 비정상 종료 시그널 : core dump • SIGABRT, SIGBUS, SIGSEGV, SIGQUIT, SIGILL, SIGTRAP, SIGSYS, SIGXCPU, SIGXFSZ, SIGFPE #include <sys/wait.h> .. .. if((pid=wait(&status)) == -1) { perror(“wait failed”); exit(1); } /* test to see if the child exited normally */ if(WIFEXITED(status)){ exit_status = WEXITSTATUS(status); printf(“Exit status from %d was %d\n”,pid,exit_status); } /* test to see if the child received a signal */ if(WIFSIGNALED(status)){ sig_no = WTERMSIG(status); printf(“signal number %d terminated child %d\n”,sig_no, pid); } ESP 교안 2부 4장
시그널 핸들링 • 시그널을 수신했을 때 프로세스는 세가지 방식으로 처리할 수 있음 • default action • 프로세스 종료 • SIGUSR1,SIGUSR2의 경우는 무시 • SIGSTOP은 작업 중지 • 시그널 무시 • 시그널을 무시하고 작업을 계속 진행 • 사용자가 정의한 작업 수행 ESP 교안 2부 4장
SIGNAL SET • 시그널을 처리하기 위해서 시스템 호출을 통해서 파라미터를 전달 • 관심의 대상이 되는 시그널의 리스트를 지정 시그널 집합 초기화 /* empty the set */ int sigemptyset(sigset_t *set) /*include all available signals */ int sigfillset(sigset_t *set) 시그널 집합 처리 루틴 /* add signal to the set */ int sigaddset(sigset_t *set,int signum) /* remove signal from the set */ int sigdelset(sigset_t *set, int signum) /*returns 0 if signal is not member of the set*/ int sigismember(sigset_t *set, int signum) ESP 교안 2부 4장
Signal set 예제 #include <signal.h> sigset_t mask1, mask2; .. .. /* create empty set */ sigemptyset(&mask1); /* add signal */ sigaddset(&mask1, SIGINT); sigaddset(&mask1, SIGQUIT); /* create full set */ sigfillset(&mask2); /*remove signal */ sigdelset(&mask2, SIGCHLD); ESP 교안 2부 4장
signal function • 시그널을 처리할 수 있는 가장 간단한 인터페이스 • signo • 핸들링하기를 원하는 시그널 번호 • func • SIG_IGN : 시그널 무시 • SIG_DFL : default action을 수행 • 사용자가 제공하는 함수 #include <signal.h> void (*signal(int signo, void (*func)(int)))(int); ESP 교안 2부 4장
#include <signal.h> #include "ourhdr.h" /* one handler for both signals */ static void sig_usr(int); int main(void) { if (signal(SIGUSR1, sig_usr) == SIG_ERR) err_sys("can't catch SIGUSR1"); if (signal(SIGUSR2, sig_usr) == SIG_ERR) err_sys("can't catch SIGUSR2"); for ( ; ; ) pause(); } static void /* argument is signal number */ sig_usr(int signo) { if (signo == SIGUSR1) printf("received SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else err_dump("received signal %d\n", signo); return; } ESP 교안 2부 4장
setting the signal action #include <signal.h> int sigaction(int signo, const struct sigaction *act, struct sigaction *oact); • signo에 해당되는 시그널이 전송된 경우 act에 등록된 시그널 핸들러가 수행 • signo는 SIGKILL, SIGSTOP을 제외한 시그널 • oact가 NULL이면, act에 등록된 새로운 핸들러가 시그널을 처리하게 됨 • oact가 NULL이 아닌 경우 이전에 등록된 시그널 핸들러는 oact에 저장 struct sigaction{void (*sa_handler)(int) sigset_t sa_mask;int sa_flags;void (*sa_sigaction)(int, siginfo_t *, void *); } ESP 교안 2부 4장