Presentation is loading. Please wait.

Presentation is loading. Please wait.

리눅스 시스템 프로그래밍 고 영 웅.

Similar presentations


Presentation on theme: "리눅스 시스템 프로그래밍 고 영 웅."— Presentation transcript:

1 리눅스 시스템 프로그래밍 고 영 웅

2 차 례 리눅스 커널 인터럽트, 시스템 호출 개념 프로세스 아키텍쳐 프로세스 제어 프로그래밍 1
유닉스 프로세스 환경 및 프로세스 관계 프로세스 제어 프로그래밍 2 시그널 개요 시그널 프로그래밍

3 타이머 처리 개요 타이머 프로그래밍 파일 시스템 아키텍쳐 설명 파일/디렉토리 개념 및 파일 입출력 파일 입출력 프로그램밍 1 파일 입출력 프로그래밍 2 IPC 아키텍쳐 IPC 프로그래밍 ( pipe, message queue, 공유메모리) 시스템 프로그래밍 관련 툴 소개

4 리눅스 특징 모노리틱 커널 구조(monolithic) 모듈 지원 커널 쓰레딩 제공
다양한 컴포넌트로 구성된 거대하고 복잡한 프로그램 마이크로 커널 구조와 설계 철학이 상이함 모듈 지원 전통적인 유닉스 커널은 정적(statically)으로 컴파일및 링크 동적으로 로딩 및 제거가 가능한 커널 코드 제공(디바이스 드라이버) 커널 쓰레딩 제공 주기적으로 수행되는 커널 함수를 지원하는데 제한적으로 사용 완전한 의미의 커널 쓰레드는 사용자 프로그램 및 커널 함수로 수행가능해야 함(솔라리스 2.x , SVR4.2/MP)

5 비중단형 커널(nonpreemptive kernel)
커널내에서 작업이 수행중일때에 임의의 지점에서 수행을 중단시키는 능력을 가지고 있지 않음 중단형 커널은 실시간 시스템에 주로 사용되며 솔라리스 2.0 및 Mach 3.0이 완전한 중단형 커널로 설계되었으며, SVR4.2/MP의 경우는 커널의 일부 지점에 고정된 중단 지점을 지정함으로 제한적인 중단 능력을 제공하고 있다. 다중 프로세서 지원 SMP(symmetric multiprocessing) 지원 아직까지는 최적화되지 못해서 커널 코드의 많은 부분이 동시성을 제공하지 못함(네트워크 코드, 파일 시스템 코드)

6 리눅스의 장점 무료 목적에 맞게 컴포넌트 커스터마이징 가능 저가의 하드웨어 플랫폼에서 수행 강력한 성능
GPL에 따라서 소스코드의 수정 및 배포가 가능 저가의 하드웨어 플랫폼에서 수행 4MB의 Intel 시스템에서 네트워크 서버 구축 가능 강력한 성능 리눅스는 효율성(efficiency)을 강조 다른 운영체제와 호환성이 뛰어남 다양한 파일 시스템 지원(MS-DOS, MS window, OS/2, etc) 다양한 네트워크 프로토콜 지원 에뮬레이터를 통한 윈도우 어플리케이션 수행 POSIX 준수에 따른 유닉스 어플리케이션의 포팅이 용이

7 리눅스 소스 코드 구성도 Linux modules mm net kernel init lib include ipc arch fs
drivers ext2 hpfs msdos nfs minix proc sysv unix inet char block scsi sound linux asm-alpha asm-i386 asm-m68k asm-mips asm-sparc mips alpha sparc m68k i386 boot math-emu

8 리눅스 커널의 발전 날짜 사용자 수 버젼 커널 크기 1991 1 0.01 10,000 1992 1,000 0.09 40,000
1993 20,000 0.99 100,000 1994 1.0 170,000 1995 500,000 1.2 250,000 1996 1,500,000 2.0 400,000 1997 3,500,000 2.1 800,000 1998 7,500,000 2.1.1 1999 2.2 1,600,000

9 운영체제(커널) 개요 운영체제의 목적 운영체제는 저수준의 프로그래밍 인터페이스를 제공해주는 물리적인 기계위에서 고수준의 프로그래밍 인터페이스 및 사용자 인터페이스를 제공해주는 가상 기계(virtual machine) 다양한 하드웨어 위에서 추상화된 인터페이스를 제공해줌으로써, 개발자가 복잡한 주변장치들을 제어하는 어려움을 없애줌 운영체제 ls Word tar Peripherals Memory CPU

10 커널 서비스 시스템 초기화 프로세스 관리 메모리 관리 파일 시스템 관리 커뮤니케이션 기능
Bootstrapping, startup 프로세스 관리 Creation, scheduling, contol, termination 메모리 관리 Allocation, deallocation, swapping, paging 파일 시스템 관리 Long-term storage, device access, I/O 커뮤니케이션 기능 Inter-process communication, machine communication Programmatic interface System call function

11 프로세스 관리 새로운 프로세스를 생성 스케줄링 타이머 관리 프로세스간 시그널 전송
어떤 프로세스가 CPU를 사용해야 하는지 결정 SCHED_OTHER, SCHED_RR, SCHED_FIFO 타이머 관리 프로세스간 시그널 전송 프로세스가 종료될때 프로세스가 사용했던 자원의 반납을 관리

12 프로세스간 통신(IPC) IPC는 프로세스간 자원을 공유 (resource sharing), 동기화(synchronize) 그리고 데이터 교환(exchanging data)을 위한 수단으로 사용됨 IPC 종류 공유 메모리(Shared memory) 세마포어(Semaphore) 시그널(Signal) 파이프(Pipe) 메시지 큐(Message queue)

13 메모리 관리 가상 메모리 시스템 메모리 보호(Protection) 메모리 매핑(Memory mapping)
프로세스는 실제 물리 메모리보다 큰 주소 공간을 가질 수 있음 메모리 보호(Protection) 프로세스의 메모리는 다른 프로세스에 의해서 읽혀지거나 수정되어서는 않됨 메모리 매핑(Memory mapping) 프로세스는 파일을 가상 메모리에 매핑해서 사용함 물리 메모리에 대한 공평한 접근 공유 메모리 기법(shared memory)

14 리눅스 커널 구조 Hardware System Call Interface Network Process Management
Memory IPC File System Device Driver System Call Interface

15 사용자 모드/커널 모드 응용 프로그램과 커널은 서로 독립적으로 수행 사용자 모드(User Mode)
프로그램은 대부분의 수행 시간을 사용자 영역에서 보내며, 커널 서비스가 필요한 경우 모드 스위칭을 함 사용자 모드(User Mode) 독립적인 사용자 주소 공간에서 사용자 코드를 수행 자원 접근 제약이 있으며, 시스템 호출을 통해서 커널 서비스 이용 시스템 콜, 하드웨어 인터럽트를 사용하여 커널 모드 접근 커널 모드(Kernel Mode) 운영체제 수행에 관련된 데이터 저장 커널 코드 수행 예외 처리 하드웨어 및 소프트웨어 자원에 대한 접근

16 사용자/커널 모드의 전환 프로세스 USER MODE KERNEL MODE 시스템 호출 시스템호출 핸들러 타이머 인터럽트
디바이스 인터럽트 스케줄러 인터럽트

17 선점형 커널 선점형 커널은 현재 프로세스가 어떤 상태에 있더라도 그 프로세스의 실행을 가로채어서 (preempt) 보다 높은 우선 순위를 가진 실행가능한 프로세스를 수행시키는 커널 이벤트의 발생에 의해서 보다 높은 우선 순위의 프로세스가 활성화 되면, 그 즉시 프로세스가 실행된다.

18 비선점형 커널 비선점형 커널은 실행되는 프로세스들이 하던 일을 마치고 CPU 의 제어권을 커널에 넘겨 주어야만, 커널이 스케쥴링을 수행하여 대기하고 있는 가장 높은 우선권을 가진 프로세스를 실행 높은 우선 순위의 프로세스가 실행되기를 기다리고 있다고 하더라도, 현재 CPU 를 점유하고 있는 프로세스가 CPU 의 사용권한을 커널에 넘겨주기 전에는 그 프로세스는 실행되지 않음

19 재진입 가능성(reentrancy) 선점형 커널이 되기 위해서 커널 함수들은 '재진입 가능‘ 해야함
실행의 흐름(flow or path)이 다른 곳으로 넘어갔다가 다시 그곳부터 실행을 할 수 있는 함수 선점형 커널에서는 커널함수라 할지라도, 언제 인터럽트 등에 의해 cpu 제어권을 뺏겨서 다른 실행 경로로 넘어갈지 모르기 때문에, 모든 함수가 재진입 가능해야 함 재진입 가능 방법 로컬 변수 사용 cli, sti 등의 어셈블리 호출(x86 의 경우)을 이용해서 크리티컬한 부분에서 인터럽트 발생을 금지 세마포어를 사용해서 공용자원인 전역변수에 대한 접근을 프로세스별로 상호 배타적으로 만듬

20 시스템 호출(System Call) 인터페이스
커널이 사용자 프로그램에게 제공하는 프로그래밍 인터페이스 fork(2) – create new process open(2) – open a file semop(2) - semaphore operations 표준 C 언어 라이브러리는 커널이 제공해주는 시스템 호출을 사용할 수 있게 하는 래퍼루틴(wrapper routine)을 포함 malloc(3) – memory allocation

21 malloc 함수와 sbrk() 시스템 호출
Kernel User Process Application code Memory allocation Fucntion malloc Sys_brk System call

22 리눅스 커널 시스템 호출

23 System Call Overview Character of System Call Type of System Call
커널 루틴을 통하여 결과를 얻음 사용자 모드에서 커널 모드로 전환됨 0x80 인터럽트를 이용 (trap gate 사용) Type of System Call 입출력 조작 입출력 디바이스에 대한 access 프로세스 제어 프로세스가 자기 자신의 실행을 제어할 수 있도록 함 프로세스간 통신 다른 프로세스로 정보를 송신할 수 있도록 하기 위함 타이밍 서비스 상태 정보의 제공

24 라이브러리 함수가 커널 모드로 전환 시키는 명령어 호출
System Call Step(1) Step1: User Program 라이브러리 함수가 커널 모드로 전환 시키는 명령어 호출 라이브러리 함수가 시스템 호출 번호를 넘겨줌 커널은 호출 번호를 이용하여 특정 시스템 호출 레지스터 사용

25 System Call Step(2) Step 2 : kernel 시스템 호출 번호에 해당하는 시스템 호출 테이블의 항을 찾는다
시스템 호출에 대한 인수의 개수를 결정한다. 인수들을 사용자 주소 공간에서 복사한다. 중도 실패 복귀 (abortive return)을 위해 현행 문맥을 저장 커널내의 시스템 호출 코드를 호출

26 인터럽트 처리 인터럽트의 필요성 CPU가 직접 입출력 장치를 제어하면 CPU의 고속성이 상실
인터럽트 요구가 없으면 보통의 루틴 수행 인터럽트 요청이 있으면 인터럽트 처리루틴 실행

27 Bottom halves(4) do_bottom_half defined kernel/softirq.c
bh_base 와 bh_active를 이용하여 handler 호출 네트워크 디바이스의 경우 net_bh() 호출 defined net/core/device.c init_bh(int nr, void(*handler)) defined <asm/softirq.h> Bottom half table에 handler 삽입 bh_base[nr] = handler Bottom half 핸들러 종류 <linux/interrupt.h> 에 정의

28 프로세스 아키텍쳐 A process is a program in execution. A process must have system resources, such as memory and the underlying CPU. The kernel support illusion of concurrent execution of multiple processes by scheduling system resources among the set of processes that are ready to execute

29 프로세스 프로그램은 디스크에 저장되어 있는 기계어 명령어 코드의 집합 프로세스는 수행상태에 있는 프로그램을 의미
리눅스는 다중 태스크 환경 지원 각 태스크 또는 수행 쓰레드를 프로세스라 함 각 프로세스는 자신이 수행할 문맥(context)를 가짐 리눅스는 단일 쓰레드 프로세스 모델 솔라리스 및 Window NT는 다중 쓰레드 프로세스 모델 리눅스는 공평성(fairness)를 보장하기 위한 스케줄링 정책을 제공 리눅스에서 태스크는 task_struct 구조체로 표현됨

30 단일 쓰레드 프로세스 모델

31 다중 쓰레드 프로세스 모델

32 태스크의 구성 요소 Identifiers State Process synchronization
Links(Process relationships) Times and Timers Files Virtual memory Processor specific context Scheduling Information

33 Task_struct 구조체 정보

34 프로세스 수행 모델 1 Five-state Process Model New Ready Running Blocked Exit
Admit Dispatch Timeout Release Event occurs Event wait

35 프로세스 수행 모델 2

36 다중 큐 방식의 블럭킹 모델

37 리눅스의 프로세스 상태도 Interrupt Scheduler Interrupt routine Return from
System call Running Ready Waiting Interrupt Scheduler

38 리눅스 프로세스 스케줄링 및 관련 함수 Process Process Process run queue wait queue
wake_up_ process() wake up the waiting process, change the state of process to TASK_RUNNING, insert it into the ready queue Process Process Process fork run queue wait queue wakeup compute priority, and select most deserving process schedule() goodness() interrupt scheduler CPU context switching the last operation of scheduler

39 프로세스간 관계 새로운 프로세스는 부모 프로세스로부터 생성 태스크 스트럭쳐는 부모 및 형제 프로세스에 대한 포인터 유지
시스템의 모든 프로세스는 이중 연결 리스트로 유지

40 Family relationships : struct task_struct *next_task;
struct task_struct *prev_task; struct task_struct *p_opptr; /* original parent */ struct task_struct *p_pptr; /* parent */ struct task_struct *p_cptr; /* youngest child */ struct task_struct *p_ysptr; /* younger sibling */ struct task_struct *p_osptr; /* older sibling */ youngest child child oldest child parent p_pptr p_osptr p_ysptr p_cptr Family relationships

41 프로세스 계층도

42 실행 프로세스 관리 실행큐는 실행 가능한 프로세스들의 이중 연결 리스트
init_task부터 시작해서 태스크 구조체의 prev_run, next_run 변수를 이용하여 모든 프로세스가 연결

43 스케줄링 리눅스는 멀티태스킹을 지원하기 위해서 시분할 방식을 도입
일정하게 발생되는 타이머 인터럽트의 주기를 이용한 스케줄링 수행중인 태스크가 주어진 타임 퀀텀(time quantum)을 소모한 경우 우선순위가 높은 다른 태스크가 수행 퀀텀(Quantum) : 각 프로세스에게 할당된 수행시간의 양 퀀텀이 작으면 시스템 응답시간은 높아지나 성능은 저하 각 프로세스는 이벤트가 발생되기를 기다리는 동안 자발적으로 CPU를 양도 비선점형 구조에서 기인한 비실시간 스케줄링 방식 리눅스의 스케줄링 고려사항 시스템 응답 시간 최소화, 태스크의 수행 시간 최소화 기아(starvation) 방지 공평한 자원 분배

44 리눅스 스케줄링 정책 리눅스는 서로 다른 세가지 스케줄링 방식을 지원 SCHED_OTHER 일반적인 프로세스의 수행시
실시간 태스크 스케줄링 SCHED_FIFO SCHED_RR SCHED_OTHER 실시간 태스크가 없는 경우, 수행 대기 상태에 있는 태스크 중 우선 순위가 높은 태스크 수행 프로세스의 우선순위는 동적으로 결정되어 짐 nice 시스템 호출 및 setpriority CPU를 많이 사용하면 우선 순위가 떨어짐 입출력에 의한 블럭킹 상태가 있는 태스크의 우선 순위를 높임

45 SCHED_FIFO SCHED_RR 우선 순위가 가장 높은 실시간 태스크가 비중단으로 수행될 수 있음 예외 상황
더 높은 우선 순위의 태스크가 준비상태에 있는 경우는 현재 태스크가 중단됨 이벤트를 기다리면서 중지상태에 있는 경우 sched_yield를 호출해서 자발적으로 CPU를 양도하는 경우 SCHED_RR SCHED_FIFO와 유사함 일정한 타임 슬롯을 할당함으로 다른 태스크가 수행될 수 있게 함

46 스케줄링 관련 시스템 호출 int sched_setscheduler(pid_t pid, int policy, struct sched_param *p); int sched_getscheduler(pid_t pid); pid의 프로세스의 스케줄링 정책 설정 및 현재 설정 상태 검색 policy 인자는 SCHED_OHTER, SCHED_FIFO, SCHED_RR int sched_get_priority_max(int policy); int sched_get_priority_min(int policy); policy가 갖을 수 있는 우선 순위 값의 범위 제공 SCHED_OTHER는 항상 0 SCHED_FIFO와 SCHED_RR은 1에서 99 사이

47 int sched_setparam(pid_t pid, const struct sched_param *p);
int sched_getparam(pid_t pid, struct sched_param *p); pid 프로세스의 스케줄링 정책 정보 설정 및 검색 우선 순위 조작 int sched_yield(void); 이 함수를 호출한 프로세스를 중단함

48 프로세스 정보 획득 SYNOPSIS #include <unistd.h>
pid_t getpid(void); returns: process ID of calling process pid_t getppid(void); returns: parent process ID of calling process pid_t getuid(void); returns: real user ID of calling process pid_t geteuid(void); returns: effective user ID of calling process pid_t getgid(void); returns: real group ID of calling process pid_t getegid(void); returns: effective group ID of calling process

49 프로세스 생성 전통적인 유닉스 시스템에서는 부모 프로세스의 자원 복제를 통해서 새로운 프로세스를 생성함 해결 방안
부모 프로세스의 모든 자원을 복제해서 자식 프로세스가 가지고 있어야 하므로 비효율성과 지연을 초래 대부분의 자식 프로세스는 부모 프로세스의 일부 자원만 수정 자식 프로세스 생성후 곧바로 Execve를 호출함으로 부모 프로세스의 자원이 필요치 않은 경우가 대부분 해결 방안 COW(Copy On Write) 방식 실제적으로 물리 페이지를 접근할때 부모 프로세스의 자원을 자식 프로세스의 영역으로 복제 Lightweight process 부모와 자식간의 주소공간을 공유하고 실행 문맥만 따로 저장함 대부분의 프로세스 데이터 스트럭쳐를 공휴(파일, 주소공간) Vfork 부모 프로세스의 메모리 주소 공간을 자식 프로세스와 공유

50 fork SYNOPSIS DESCRIPTION RETURN VALUE #include <unistd.h>
pid_t fork(void); DESCRIPTION 새로운 자식 프로세스 생성 파일 락(File lock)이나 전달된 시그널( pending signal)등은 상속되지 않음 리눅스에서 COW(copy-on-write page)를 통해서 구현 fork를 수행함으로써 발생되는 시스템 오버헤드는 부모 프로세스의 페이지 테이블을 복사 및 자식 프로세스의 고유한 태스크 스트럭쳐를 생성하는 하는 비용 및 시간이다. RETURN VALUE 성공적했을때, 부모 프로세스에게 자식 프로세스의 PID를 리턴 자식 프로세스는 0을 리턴 실패했을때, -1을 리턴하며, 자식 프로세스가 생성되지 않음

51 프로그램 소스 코드 fork() Child process parent process
if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { /* child */ 자식 프로세스의 작업 수행 } else /* parent */ 부모 프로세스의 작업 수행 fork() Child process Result == 0 parent process Result > 0 Result < 0

52 리눅스 커널 내부의 Fork 수행 과정 자식 프로세스의 프로세스 디스크립터와 커널 모드 스택을 저장할 공간(8KB)을 확보 : alloc_task_struct() 확보된 공간에 부모 프로세스 디스크립터의 내용을 복사 새롭게 생성될 프로세스를 저장할 엔트리가 있는지 확인함 : find_empty_process() – 리눅스에서는 NR_TASKS에 최대 태스크의 개수가 제한되어 있음 새로운 프로세스에게 PID 할당 : get_pid() 부모로부터 상속받은 프로세스 디스크립터의 내용중에서 상속받지 못한 내용을 채움 : 예를 들어서 프로세스 관계등 자식 프로세스의 상태를 TASK_RUNNING 상태로 전환 자식 프로세스의 PID를 부모 프로세스에게 돌려줌

53 vfork SYNOPSIS DESCRIPTION #include <unistd.h>
pid_t vfork(void); DESCRIPTION 새로운 프로세스를 생성한 후에 exec를 호출해서 프로그램을 수행시키고자 하는 목적으로 제공 vfork는 fork 함수와 같은 호출 경로 및 리턴값을 가짐 부모 프로세스의 주소 공간을 자식 프로세스에게 복사하지 않고, 주소만 참조하는 방식 사용 자식 프로세스는 exec를 호출하기 전까지 부모 프로세스의 주소공간에서 수행

54 Exec 관련 함수 SYNOPSIS DESCRIPTION #include <unistd.h>
int execl( const char *path, const char *arg, ...); int execlp( const char *file, const char *arg, ...); int execle( const char *path, const char *arg , ..., char * const envp[]); int execv( const char *path, char *const argv[]); int execvp( const char *file, char *const argv[]); DESCRIPTION 새로운 프로그램 수행을 위한 함수 현재 프로세스를 새로운 프로세스로 대체

55 execl 예제 pc before after ls main() { printf(“executing ls\n”);
execl(“/bin/ls”,”ls”.”-l”,(char*)0); perror(“execl failed to run ls”); exit(1); } before after printf(…); execl(…..); /* first line of ls */ pc ls

56 fork 호출후 exec 사용 main() { pid_t pid; switch(pid = fork()){
case -1: perror(“fork failed”); exit(1);break; case 0 : execl(“/bin/ls”,”ls”,”-l”,(char*)0); /* child */ perror(“fork failed”); exit(1);break; default : wait((int *) 0); /* parent */ printf(“ls completed\n”); exit(0); }

57 pc before fork A after fork after exec B pid=fork(); wait((int *) 0);
execl(“/bin/ls”,..); /* 1st line of ls */ A B after fork after exec

58 프로세스 종료 정상적인 종료(normal termination) 비정상적인 종료(abnormal termination)
main 함수로부터 return 수행 exit 함수를 호출 _exit 함수를 호출 : exit 함수는 _exit 함수를 호출 비정상적인 종료(abnormal termination) abort 호출 프로세스가 시그널을 받을때(자기 자신, 다른 프로세스, 커널) 참조할 수 없는 주소 영역을 참조하려고 시도하는 경우 0 으로 어떤값을 나누려고 시도하는 경우 관련 함수 exit, atexit

59 exit SYNOPSIS DESCRIPTION #include <stdlib.h>
void exit(int status); DESCRIPTION 현재 수행중인 프로세스를 종료 열려진 파일 디스크립터를 닫음 부모 프로세스가 wait를 호출하고 블럭킹 상태에 있으면, 부모 프로세스에게 이벤트를 발생시켜 진행시킴 프로그래머가 정의한 exit 핸들링 루틴을 실행 clean-up 액션에 정의된 나머지 작업 수행

60 atexit SYNOPSIS DESCRIPTION #include <stdlib.h>
int atexit(void (*function) (void)); DESCRIPTION 프로그램이 종료될때 불려지는 함수 등록 ANSI C에서는 32개까지 함수를 등록할 수 있으며, exit 함수에 의해서 각 함수가 자동적으로 호출되어짐

61 How a C program is started and how it terminated
exec main function user C start-up routine exit exit handler ….. standard I/O clean up KERNEL _exit USER Process

62 wait SYNOPSIS DESCRIPTION RETURN VALUE #include <sys/types.h>
#include<sys/wait.h> pid_t wait(int* status); pid_t waitpid(pid_t pid, int * status, int options); DESCRIPTION 프로세스간 동기화(synchronizing process) 제공 자식 프로세스가 수행중인 동안 일시적으로 프로세스의 수행을 중지 자식 프로세스가 종료하는 경우, 수행 재개 특정한 자식 프로세스의 종료를 기다리는 경우 waitpid 사용 RETURN VALUE 성공 : 수행이 종료된 자식 프로세스의 PID 리턴 실패 : -1

63 pstree 프로세스 계층도를 보여주는 프로그램

64 top 프로세스 정보를 보여주는 프로그램

65 Gkrellm 시스템의 각 상황을 그래픽하게 보여줌

66 Environment of a UNIX process

67 example of exit handler
#include "ourhdr.h" static void my_exit1(void), my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) err_sys("can't register my_exit2"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); printf("main is done\n"); return(0); } static void my_exit1(void) { printf("first exit handler\n"); } my_exit2(void) printf("second exit handler\n"); main is done first exit handler second exit handler

68 command line argument #include "ourhdr.h"
int main(int argc, char *argv[]) { int i; /* echo all command-line args */ for (i = 0; i < argc; i++) printf("argv[%d]: %s\n", i, argv[i]); exit(0); } $ ./echoarg arg1 tet foo argv[0] : ./echoarg argv[1] : arg1 argv[2] : test argv[3] : foo

69 Environment list 환경변수 리스트(envronment list)는 문자형 포인터의 배열로 구성되어 있으며, 각 포인터는 환경 변수들의 문자열을 가르키고 있음 extern char **environ; HOME=/home/stevens\0 NULL PATH=:/bin:/usr/bin\0 SHELL=/bin/sh\0 USER=stevens\0 environ environment pointer list strings

70 environ example int main(int argc, char *argv[]) { int i; char **ptr;
extern char **environ; /* echo all command-line args */ for (i = 0; i < argc; i++) printf("argv[%d]: %s\n", i, argv[i]); /* and all env strings */ for (ptr = environ; *ptr != 0; ptr++) printf("%s\n", *ptr); exit(0); }

71

72 Memory layout of a C program
Text segment 프로세서에 의해서 실행되는 기계어 코드가 위치 공유 가능한 세그먼트 읽기 전용으로 되어있음 Initialized data segment 초기화된 데이터 위치 int maxcount = 99; uniInitialized data segment 초기화되지 않은 데이터 위치 bss (block started by symbol) long sum[1000]; Heap 동적인 메모리 할당 장소 Stack 자동 변수 및 임시 변수 저장 함수 호출시 복귀 주소 및 caller의 환경저장

73 Memory arrangement text read from program file by exec
initialized data uninitialized data bss heap stack command-line arguments and environment variables initalized to zero by exec read from program file by exec

74 라이브러리(libraries) 개요 라이브러리의 종류 정적 라이브러리(static library)
정적라이브러리, 공유라이브러리, 동적라이브러리 정적 라이브러리(static library) 프로그램을 컴파일하고 링크하는 과정에서 프로그램 연결 공유 라이브러리(shared library) 프로그램이 수행되는 단계에서 로딩 동적 라이브러리(dynamic library) 공유 라이브러리의 변형 프로그램이 라이브러리의 함수를 호출하는 단계에서 메모리에 적재 사용이 되지 않는 경우 메모리에서 제거됨 공유 및 동적 라이브러리 사용은 프로그램의 크기를 최소화 할 수 있음

75 라이브러리 이름 리눅스에서 라이브러리의 위치는 /usr/lib 또는 /lib에 위치함 라이브러리의 이름은 항상 lib으로 시작
suffix는 라이브러리의 종류에 따라서 틀려짐 정적라이브러리 : libname.a 동적라이브러리 : libname.so.major.minor example libm.so.5 : math 공유 라이브러리 주버젼 5 libm.a : math 정적 라이브러리 libX11.so.6 : x window 공유 라이브러리 주번젼 6

76 리눅스 /usr/lib

77 라이브러리 내용

78 nm : 라이브러리 또는 목적파일에 있는 함수 및 변수명까지 검색

79 system #include <stdlib.h> int system(const char *cmdstring);
하나의 프로그램 내부에서 다른 프로그램 실행 fork를 호출한 후 exec를 수행하는 것과 같은 효과 #include <stdlib.h> #include <stdio.h> int main() { printf(“running ps with system\n”); system(“ps –al”); printf(“Done\n”); exit(0); }

80 fork의 다양한 적용 #include <unistd.h> #include <stdio.h>
1 2 #include <unistd.h> #include <stdio.h> if((childpid = fork()) == 0) { printf(“I am the child, ID = %d\n”, getpid()); /* child code goes here */ } else if (childpid > 0) { printf(“I am the parent, ID = %d\n”, getpid()); /* parent code goes here */ }

81 chain 구조 #include <unistd.h> #include <stdio.h> int i;
1 2 3 #include <unistd.h> #include <stdio.h> int i; int n; pid_t childpid; for(i=0;i<n;i++) if(childpid = fork()) break; printf(“This is process %d with parent %d\n”, getpid(), getppid());

82 pan 구조 #include <unistd.h> #include <stdio.h> int i;
1 2 3 4 #include <unistd.h> #include <stdio.h> int i; int n; pid_t childpid; for(i = 0; i < n; i++) if((childpid = fork()) <= 0) break; printf(“This is process %d with parent %d\n”, getpid(), getppid());

83 트리 구조 #include <unistd.h> #include <stdio.h> int i; int n;
3c 1 2b 2a 3b 3a #include <unistd.h> #include <stdio.h> int i; int n; pid_t childpid; for(i = 0; i < n; i++) if((childpid = fork()) == -1) break; printf(“This is process %d with parent %d\n”, getpid(), getppid());

84 wait and waitpid 예제 아래 코드는 부모 프로세스가 자식 프로세스의 종료 상태를 결정하는 코드임.
#include <sys/types.h> #include <sys/wait.h> #include <error.h> pid_t child; int status; while(((child = wait(&status)) == -1) && (errno ==EINTR)) ; if(child == -1) perror(“Could not wait for child”); else if (!status) printf(“Child %d terminated normally, return status is zero\n”, child); else if (WIFEXITED(status)) printf(“Child %d terminated normally, return status is %d\n”, child, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf(“Child %d terminated due to signal not caught\n”, child);

85 wait 함수를 사용하는 용례를 보이는 소스코드
#include <sys/types.h> #include <sys/wait.h> #include <error.h> void main(){ pid_t childpid; int status; if((childpid = fork()) == -1){ perror(“The fork failed”); exit(1); } else if (childpid == 0) printf(“I am the child with pid = %d\n”, getpid()); else if (wait(&status) != childpid) printf(“A signal must have interrupted the wait\n”); else printf(“I am the parent with pid = %d and child pid = %d\n”, getpid(), getppid()); exit(0);

86 SIGNAL

87 시그널 개념 시그널은 프로세스 또는 프로세스의 그룹에게 보낼 수 있는 매우 짧은 메시지를 지칭 시그널의 목적
프로세스가 특별한 이벤트에 대해서 반응할 수 있게 함 프로세스가 가지고 있는 시그널 핸들러를 통해서 작업을 수행 현재 리눅스는 31개의 시그널을 가지고 있음 시그널의 특성은 상대 프로세스가 어떤 수행 상태에 있는지 상관없이 메시지를 보낼 수 있음 수행중아 아닌 프로세스에게 시그널을 보내는 경우, 해당 프로세스가 문맥전환이 되면서 시그널을 핸들링함 시그널을 전송했으나 아직 처리가 되지 않은 시그널을 pending signal 이라 함 pending signal에게 같은 종류의 시그널이 반복해서 전송되는 경우 무시

88 리눅스 시그널 리스트

89 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.

90 시그널 기능 SIGABRT SIGALRM SIGBUS process abort signal abort() 에 의해서 불려짐
core dump 디버깅을 목적으로 프로세스의 현재 상태를 나타내는 정보를 디스크로 저장 SIGALRM alarm clock 타이머가 expired 되었다는 신호 모든 프로세스는 최소한 세개 이상의 인터벌 타이머(interval timer)가 존재 SIGBUS BUS error 하드웨어 폴트가 감지됨 비정상적으로 프로세스 종료

91 SIGCHLD SIGCONT SIGFPE SIGHUP child process terminated or stopped
자식 프로세스가 종료하거나 멈추는 경우 발생 기본적으로 부모 프로세스는 SIGCHLD 무시 SIGCONT continue executing if stopped job control signal SIGSTOP에 의해서 멈춘 작업을 재개시킴 SIGFPE 부동 소수 예외 비정상적 종료 SIGHUP hangup signal control terminal에 접속해 있는 모든 프로세스에게 커널이 시그널 전송

92 SIGILL SIGINT SIGKILL SIGPIPE illegal instruction
프로그램이 깨졌을 경우에 발생(corrupted) SIGINT interrupt 사용자가 인터럽트 키를 누른 경우 SIGKILL kill 하나의 프로세스가 다른 프로세스에게 보내는 특별한 시그널 예를 들어 시스템 셧 다운 ignored 되거나 caught 될 수 없음 SIGPIPE Write on a pipe or socket when recipient has terminated

93 SIGQUIT SIGSEGV SIGSTOP SIGUSR1, SIGUSR2 quit SIGINT와 유사
비정상적 종료, core dump SIGSEGV 잘못된 주소 참조-segmentation violation SIGSTOP stop executing 현재 수행중인 작업을 중지 SIGUSR1, SIGUSR2 사용자의 목적에 따라서 사용 가능한 시그널

94 정상 종료 및 비정상 종료 대부분의 시그널은 정상 종료 : _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);

95 시그널 핸들링 시그널을 수신했을때 프로세스는 세가지 방식으로 처리할 수 있음 default action 시그널 무시
프로세스 종료 SIGUSR1,SIGUSR2의 경우는 무시 SIGSTOP은 작업 중지 시그널 무시 시그널을 무시하고 작업을 계속 진행 사용자가 정의한 작업 수행

96 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)

97 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);

98 signal function #include <signal.h>
void (*signal(int signo, void (*func)(int)))(int); 시그널을 처리할 수 있는 가장 간단한 인터페이스 signo 핸들링하기를 원하는 시그널 번호 func SIG_IGN : 시그널 무시 SIG_DFL : default action을 수행 사용자가 제공하는 함수

99 #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; }

100 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 *); }

101 #include <signal.h>
main() { static struct sigaction act; void catchint(int); act.sa_handler = catchint; sigfillset(&(act.sa_mask)); sigaction(SIGINT, &act, NULL); printf(“sleep call #1\n”); sleep(1); printf(“sleep call #2\n”);sleep(1); printf(“sleep call #3\n”);sleep(1); printf(“sleep call #4\n”);sleep(1); printf(“Existing \n”); exit(0); } void catchint(int signo) printf(“\nCATCHINT: signo=%d\n”, signo); printf(“CATCHINT: returning \n”);

102 실행 결과(키보드 인터럽트가 없는 경우) $sligex sleep call #1 sleep call #2 sleep call #3 sleep call #4 Existing 실행 결과(중간에 키보드 인터럽트 발생) $sligex sleep call #1 sleep call #2 CATCHINT:signo=2 CATCHINT: returning sleep call #3 sleep call #4 Existing

103 sending signals #include <signal.h>
int kill(pid_t pid, int sig); pid를 가지고 있는 프로세스에게 sig에 해당되는 시그널을 전송 kill(7421, SIGTERM); kill은 상대방 프로세스 아이디를 알아야 하므로 연관이 있는 프로세스 사이에서 주로 호출 privilege issues 시그널을 전송하기 위해서 전송측과 수신측의 real user-id 또는 effective user-id가 같아야 함 슈퍼유저는 임의의 프로세스에게 시그널을 전송할 수 있는 권한을 가짐 pid pid == 0 : 프로세스 그룹에 있는 모든 프로세스에게 시그널이 전송 pid == -1 이고 슈퍼유저가 아닌 경우: real 또는 effective user-id를 가지고 있는 모든 프로세스에게 시그널 전송 pid == -1 이고 슈퍼유저인 경우: 특정한 시스템 프로세스를 제외한 모든 프로세스에게 시그널 전송

104 int ntimes = 0; void main(){ pid_t pid, ppid; void p_action(int), c_action(int); static struct sigaction pact, cact; /* set SIGUSR1 action for parent */ pact.sa_handler = p_action; sigaction(SIGUSR1, &pact, NULL); switch(pid = fork()){ case –1: /* error */ perror(“error”); exit(0); case 0: /* child */ cact.sa_handler = c_action; sigaction(SIGUSR1, &cact, NULL); ppid = getppid(); for(;;){ sleep(1); kill(ppid, SIGUSR1); pause(); } /* never exist */ default: /*parent */ for(;;) { pause(); sleep(1); kill(pid, SIGUSR1); } /* never exits */ void p_action(int sig) { printf(“parent caught signal #%d\n”, ++ntimes); void c_action(int sig) printf(“child caught signal #%d\n”, ++ntimes);

105 alarm #include <unistd.h> unsigned int alarm(unsigned int secs)
주어진 시간 secs 후에 SIGALRM을 발생 sleep 호출과의 차이 alarm은 alarm 호출후 계속해서 작업을 수행 sleep은 sleep 호출후 주어진 시간동안 중지 프로세스가 어떤 작업을 수행함에 있어서 제한 시간을 설정하는 경우에 유용함 alarm의 종료 alarm(0);

106 alarm #include <signal.h> int raise(int sig);
int pause(void); 특정한 시그널을 받을 동안 , 현재 수행 중인 프로세스를 중지

107 타이머 동작 원리 및 프로그래밍 고 영 웅

108 time() time 함수는 real time 또는 wall-clock time을 측정 time_t의 타입은 long
#include <time.h> time_t time(time_t *tloc) time 함수는 real time 또는 wall-clock time을 측정 time_t의 타입은 long 1970년 1월 1일부터 시작해서 현재시간을 저장 32bit 환경에서 232초는 68년이므로 singed long은 대략 2038년이 넘으면 오버플로이고, unsigned long 2106년에 오버플로

109 times() times는 프로세스 및 자식 프로세스의 수행 시간을 측정함 #include <time.h>
clock_t times( struct tms *buf) times는 프로세스 및 자식 프로세스의 수행 시간을 측정함

110 특정 함수가 수행하는데 걸리는 시간을 times 함수를 이용 측정

111 실행 결과 CPU가 idle한 상황에서 수행시켰을때
다른 프로세스 (find / -name “*.c”) 가 작업을 하고 있는 상황에서 수행시켰을때

112 gettimeofday() #include <sys/time.h>
int gettimeofday(struct timeval *tp, struct timezone *tzp); int settimeofday(const struct timeval *tp, const struct timezone *tzp); gettimeofday가 호출되면 timeval 구조체로 현재 시간이 저장 마이크로 세컨드 단위의 높은 해상도의 시간을 구할 수 있음 settimeofday는 슈퍼유저만 호출 가능 tzp는 항상 NULL => 역사적인 이유로 자리만 차지하고 있음 POSIX 표준이 아니므로 다양한 형태로 구현되어 있음 struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };

113 특정 함수가 수행하는데 걸리는 시간을 gettimeofday() 함수를 이용 측정

114 실행 결과 CPU가 idle한 상황에서 수행시켰을때
다른 프로세스(find / -name “*.c”)가 작업을 하고 있는 상황에서 수행시켰을때

115 Interval Timer 각 프로세스마다 몇 개의 사용자 타이머가 존재 Interval timer의 종류
#include <sys/time.h> int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); int getitimer(int which, const struct itimerval *value, struct itimerval *ovalue); 각 프로세스마다 몇 개의 사용자 타이머가 존재 Interval timer의 종류 ITIMER_REAL : real time의 값을 줄여나가면서 0 이 되는 경우 SIGALRM 발생 ITIMER_VIRTUAL : 프로세스가 유저 모드에서 수행되는 경우에만 타이머 값을 줄여나가며, 세팅된 타이머 값이 0 이 되는 경우 SIGVTALRM 발생 ITIMER_PROF : 프로세스가 유저 모드에서 수행중인 경우와 커널모드에서 수행 중일때 타이머의 값을 줄여나가며, 타이머가 0 이 되는 경우 SIGPROF 발생

116 itimerval 구조체

117 프로그램 예제

118

119 Hardware Clocks Real time clock
PC는 RTC라고 불리는 클럭을 내장하고 있으며, CPU및 다른 칩들과 무관하게 동작함 PC에 전원이 꺼진 상태에서도 동작 CMOS RAM과 RTC가 하나의 칩에 통합됨 RTC는 2HZ에서 8192HZ에 해당하는 주파수로 주기적인 인터럽트를 발생 가능 (IRQ8) 리눅스에서는 RTC를 시간과 날짜를 유지하는데 사용

120 타이머 개념 및 리눅스 타이머

121 TSC(Time stamp counter)
80x86계열의 프로세서는 CLK 입력 핀을 가지고 있어서, 외부 오실로스코프에서 클럭 시그널을 입력 받음 펜티움 기종부터 TCS 레지스터가 포함되었으며, CLK에서 입력이 들어올때마다 레지스터 값이 증가됨 RDTSC 인스트럭션을 사용해서 TCS 레지스터 값을 읽어옴 400MHZ로 동작하는 클럭 입력을 가지는 경우 TCS는 매 2.5 나노세컨드마다 값이 증가됨 리눅스는 TCS 값을 이용해서 세밀한 측정을 할 수 있음

122 PIT(Programmable Interval Timer)
일정한 주기마다 타이머 인터럽트를 발생시키는 소스 8254 CMOS chip (0x40 – 0x43 I/O port) PIT는 100HZ(10 밀리 세컨드)로 IRQ0에 인터럽트를 발생시키며, 리눅스 커널은 10 밀리 세컨드마다 타이머 인터럽트를 받게됨 타이머 인터벌을 tick이라고 부름 tick이 발생되는 간격이 작을수록 시스템 응답시간이 향상되나, 타이머 인터럽트를 처리하는 작업이 빈번해지므로 오버헤드 발생

123 리눅스의 타이머 인터럽트 타이머 인터럽트 핸들러 호출 시스템 시작때부터 얼마나 시간이 지났는지 값을 유지
jiffies 값으로 유지 time과 date를 업데이트 시킴 현재 프로세스가 얼마나 오랫동안 CPU를 점유하고 사용되었는지 점검하고, 주어진 퀀텀을 소모했으면 중지(preemption) 시킴 통계 유지 각 프로세스의 CPU 사용 시간 업데이트(유저 영역, 시스템 영역) 타이머 큐에 들어 있는 작업 처리 타이머 큐에는 일정한 시간에 수행되어야 할 커널 루틴이 함수로 등록됨 주어진 시간이 만료된 큐의 함수들에 대한 처리를 수행 struct timer_struct { unsigned long expires; void (*fn) (void); }

124 작업 수행중 CPU 타이머 인터럽트 핸들러 일정한 주기로 인터럽트 발생 PIC IRQ0 IRQ1 IRQ2 IRQ3 8254

125 비주기적 타이머 인터럽트 리눅스 커널은 10 밀리 세컨드의 일정한 주기로 타이머 인터럽트가 수행되며, 최소 10 밀리 세컨드의 간격으로 특정한 작업 수행가능 세밀한 시간 단위에서 커널에서 인터럽트를 받아서 작업을 하기 위해서는 비주기적인 타이머 프로그램 방법을 사용 CPU 타이머 인터럽트 핸들러 타이머 칩 타이머 인터럽트를 받고 싶은 시간만큼 타이머칩을 프로그램 8254 PIC IRQ0 IRQ1 IRQ2 IRQ3

126 총걸린 시간 = (b – a) * (rdtsc의 한주기 시간)
세밀한 시간 측정 TCS를 활용해서 측정 구간의 앞뒤에서 rdtsc 호출 a = RDTSC 시간 측정 구간 b = RDTSC 총걸린 시간 = (b – a) * (rdtsc의 한주기 시간)

127 파일 시스템 및 파일 입출력 고 영 웅

128 파일 시스템 개요 파일 시스템의 특징 유닉스 커널 프로그램과 프로그램 실행에 필요한 시스템 파일 및 사용자 데이터 파일로 구성됨 물리적인 장치의 블록에, 파일을 디렉토리나 소프트 링크 등과 함께 논리적인 계층 구조로 구성 블럭장치에 대해서는 관여하지 않음 즉 특정 트랙, 섹터, 실린더 등 하드 디스크 상의 그 블록이 있는 위치로 매핑하는 것은 각 블록 디바이스 드라이버의 역할 파일의 생성 및 삭제 파일 데이터의 보호 터미널과 테이프 장치등의 주변 장치를 파일로 취급

129 파일 시스템 트리 명령실행 : tree –d | more

130 파일 시스템의 구성 요소 루트 파일 시스템 일반 파일 디렉토리 파일 특수 파일
하드 디스크 상에서 적어도 하나의 파일시스템이 존재 해 있슴 시스템 프로그램과 디렉토리들이 포함되어 있음 일반 파일 수행 가능한 프로그램 파일이나 원시 프로그램 파일 텍스트 파일, 데이터 파일등 컴퓨터에 의해 처리되어 질수 있는 파일들이 저장되어 있음 디렉토리 파일 계층 구조로 구성 다른 파일과 디렉토리들에 관한 정보를 저장하는 논리적인 단위 파일명인 문자열과 inode 번호를 연결하는 부분 특수 파일 주변 장치에 속하는 파일 모든 주변장치들이 컴퓨터에 연결되기 위해서 하나 이상의 특수 파일을 가지고 있어야 함

131 파일 시스템의 구조 부트 블록(boot block) 슈퍼 블록(super block) 아이노드 리스트(inode list)
파일 시스템으로 부터 UNIX 커널을 적재시키기 위한 부트스트랩 포함 파일 시스템 시작부에 위치, 전형적으로 첫번째 섹터 차지 슈퍼 블록(super block) 파일 시스템의 상태 기술 파일 시스템의 크기, 저장 공간의 상태, 자유공간 정보 파일 시스템 마다 하나씩 존재 아이노드 리스트(inode list) 파일이나 디렉토리에 대한 모든 정보를 가지고 있는 구조체 데이터 블록 실제 데이터가 파일의 형태로 저장 되어 있음

132 파일 시스템 배치 부트 블럭 수퍼블럭 inode list 데이터 블럭

133 File primitives Name Meaning
open Opens a file for reading or writing, or creates creat Creates an empty file close Closes a previously opened file read Extracts information from a file write Places information into a file lseek Moves to a specified byte in a file unlink Removes a file remove Alternative method to remove a file fcntl Controls attributes associated with a file

134 파일 열기(open) open 시스템 호출은 파일의 데이터를 접근하기 위해서 수행하는 첫단계
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags)); int open(const char *pathname, int flags, mode_t mode)); open 시스템 호출은 파일의 데이터를 접근하기 위해서 수행하는 첫단계 pathname : 파일명 flags: 읽기/쓰기 등의 유형 mode : 파일 생성시의 허가에 관한것 리턴값: 성공: 파일 디스크립터, -1 : 에러

135 flags 필수 flags 선택 flags O_RDONLY : 읽기 전용으로 열기 O_WRONLY : 쓰기 전용으로 열기
O_RDWR : 읽기 및 쓰기 가능한 상태로 열기 선택 flags O_APPEND : 파일의 끝에 추가 O_CREAT : 파일이 존재하지 않는 경우 생성 O_TRUNC : 파일을 열면서 크기를 0으로 조절

136 mode S_IRWXU user (file owner) has read, write and execute permission S_IRUSR (S_IREAD) user has read permission S_IWUSR (S_IWRITE) user has write permission S_IXUSR (S_IEXEC) user has execute permission S_IRWXG group has read, write and execute permission S_IRGRP group has read permission S_IWGRP group has write permission S_IXGRP group has execute permission S_IRWXO others have read, write and execute permis sion S_IROTH others have read permission S_IWOTH others have write permisson S_IXOTH others have execute permission

137 #include <stdlib.h>
#include <fcntl.h> char *workfile = “junk”; main() { int filedes; if((filedes = open(workfile, O_RDWR)) == -1) printf(“couldn’t open %s \n”, workfile); exit(1); } exit(0);

138 파일 생성(creat) #include <sys/types.h> #include <sys/stat.h>
#include <fcntl.h> int creat(const char *pathname, mode_t mode); open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode)과 동일한 의미를 가짐 초창기에는 creat는 파일을 쓰기 가능으로만 생성

139 파일 닫기(close) #include <unistd.h> int close(int filedes);
파일을 닫고, 프로세스가 파일을 사용하기 위해서 사용한 락(lock)을 해제 커널은 프로세스가 종료할때 사용했던 모든 파일을 자동으로 닫아줌

140 lseek #include <sys/types.h> #include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence); 열려진 모든 파일은 현재 파일 오프셋(current file offset)을 가지고 있음 파일의 시작 위치에서 어느 정도 떨어져 있는지 알려주는 nonnegative 정수이며, 파일이 처음 열릴때 0 으로 초기화 raed 및 write는 현재 파일 오프셋에서 시작해서 작업을 진행 whence가 SEEK_SET인 경우 파일의 처음에서 offset 만큼의 위치로 이동 whence가 SEEK_CUR인 경우 파일의 (현위치 + offset)의 위치로 이동 whence가 SEEK_END인 경우 파일의 끝에서 offset 만큼의 위치로 이동

141 예제 : hole.c

142 실행 결과

143 파일 읽기 (read) #include <unistd.h>
ssize_t read(int filedes, void *buff, size_t nbytes); read가 성공적으로 수행되는 경우 읽은 바이트 수를 리턴 read로 읽기를 시도할때, 리턴값이 nbytes보다 작은 경우 파일의 끝에 도달 : 0 리턴 터미널에서 읽기를 시도할때 한줄까지만 읽을 수 있음 네트워크를 통해서 읽기를 시도하는 경우 버퍼링에 의해서 요구된 바이트 수 보다 작은값이 리턴

144 파일 쓰기 (write) #include <unistd.h>
ssize_t write(int filedes, const void *buff, size_t nbytes); write가 성공적으로 수행되는 경우 기록한 바이트 수를 리턴

145 파일 공유 모든 프로세스는 프로세스 테이블 엔트리를 가지고 있으며, 각 프로세스 테이블 엔트리에는 파일 디스크립터 테이블이 존재 파일 디스크립트 플래그 파일 테이블 엔트리의 포인터 커널은 열려진 파일에 대해서 파일 테이블을 가지고 있으며, 각 파일 테이블은 아래의 항목을 포함한다 파일의 상태 플래그(read, write, append, .etc) 현재 파일 오프셋 v-node 테이블 엔트리에 대한 포인터

146 kernel data structure for open file
fd flag ptr fd 0: fd 1: process table entry file status flags file table current file offset v-node ptr v-node info I-node info current file size v-node table

147 two independent process with the same file open
fd flag ptr fd 0: fd 1: process table entry file status flags file table current file offset v-node ptr v-node info I-node info current file size v-node table

148 Linux file structure fs files count umask root pwd close_on_exec
open_fs fd[0] fd[1] : fd[255] f_mode f_pos f_flags f_count f_owner f_inode f_op f_version task_struct fs_struct files_struct inode file file operation routines

149 dup #include <unistd.h> int dup(int filedes);
int dup2(int filedes, int filedes2); dup == fcntl(filedes, F_DUPFD,0) dup2(filedes, filedes2) == close(filedes2); fcntl(filedes, F_DUPFD,filedes2)

150 kernel data structure after dup
fd flag ptr fd 0: fd 1: process table entry file status flags file table current file offset v-node ptr v-node info I-node info current file size v-node table

151 fcntl #include <sys/types.h> #include <unistd.h>
#include <fcntl.h> int fcntl(int filedes, int cmd, …/*int arg */); fcntl 함수는 이미 열려져 있는 파일의 속성을 바꾼다 cmd F_DUPFD : duplicate an existing descripter F_GETFD/F_SETFD : get/set file descripter flags(FD_CLOEXEC) F_GETFL/F_SETFL : get/set file status flags F_GETOWN/F_SETOWN : get/set asynchronous I./O ownership

152

153

154 파일 정보 획득(stat) #include <sys/stat.h> #include <unistd.h>
int stat(const char *file_name, struct stat *buf); int fstat(int filedes, struct stat *buf)); int lstat(const char *file_name, struct stat *buf); 주어진 file_name에 대한 정보를 돌려줌 stat : 일반 파일이름을 이용 파일 정보 획득 fstat : 파일 디스크립터를 이용한 파일 정보 획득 lstat : 심볼릭 링크의 파일 정보 획득

155 struct stat struct stat { dev_t st_dev; /* device */
ino_t st_ino; /* inode */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device type (if inode device) */ off_t st_size; /* total size, in bytes */ unsigned long st_blksize; /* blocksize for filesystem I/O */ unsigned long st_blocks; /* number of blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last change */ };

156 File type Regular file Derectory file Character special file
가장 공통적인 유형의 파일 Derectory file 다른 파일의 정보를 담거나, 디렉토리의 정보를 보관 Character special file Block special file FIFO 프로세스간의 통신을 위한 IPC 파일, named pipe Socket 네트워크 통신을 위해 사용됨 Symbolic link

157 File type macro in <sys/stat.h>

158

159 acess #include <unistd.h>
int access(const char* pathname, int mode); 접근 테스트를 위한 함수 pathname : 테스트를 원하는 파일명 mode

160

161

162 Disk driver, partition and filesystem
I-node …. I-list directory blocks and data blocks boot block super block

163 I-node , directory, file …. . .. testfile file system directory blocks
…. I-list 2344 directory blocks . 123 .. 222 testfile 블록 정보 속성

164 가상 파일 시스템(Virtual File System)
리눅스가 다양한 파일 시스템을 지원할 수 있게 함 각각의 파일 시스템이 장치 개념으로 접근되지 않고, 하나의 계층적인 트리구조로 사용되게 함 예제 cp /homes/test /dev/fd0 cp /homes/test /mnt/msdos/

165 VFS 내부 구조 Registering & Mounting FileSystem Open file Dentry cache
Inode cache Buffer cache System call

166

167 link #include <unistd.h>
int link(const char* pathname, const char *newpath); link는 동일한 I-node를 가르키게 되며, 실제적으로 파일은 하나만 존재 #include <unistd.h> int unlink(const char* pathname); link count가 0이 되는경우 파일이 제거됨

168 two hard links to the same file
directory entry in /dirA directory entry in /dirB 12345 name1 12345 name2 inode 12345 this is my data nice… it is good.. 2233

169 two hard links to the same file
directory entry in /dirA directory entry in /dirB 12345 name1 23456 name2 inode 12345 inode 23456 this is my data nice… it is good.. “/dirA/name1” 2233 4567

170 tempfile을 오픈한 다음, unlink를 호출해서 파일을 지우는 작업 수행
link counter가 0이 되므로 파일이 지워짐

171 utime #include <utime.h>
int utime(const char* pathname, const struct utimebuf *times); utime을 호출하면 pathname의 파일이 가지고 있는 access time과 modify time이 변경된다. struct utimebuf { time_t actime; time_t modtime; }

172 O_TRUNC를 사용해서 파일 크기를 0으로 만든다음에 접근 시간이나 변경시간을 바꾸고
싶지 않은 경우

173 mkdir #include <sys/types.h> #include <stat.h>
int mkdir(const char* pathname, mode_t mode); 새로운 디렉토리를 생성 디렉토리 밑에 있는 파일에 접근하기 위해서는 실행권한을 주어야 함

174 rmdir #include <sys/types.h> #include <stat.h>
int rmdir(const char* pathname); 디렉토리를 제거 디렉토리를 가르키는 I-node의 link counter가 0이 되는경우 제거 디렉토리 밑에 있는 파일에 접근하기 위해서는 실행권한을 주어야 함

175 reading directory 디렉토리 밑에 파일을 생성하거나 파일을 지우기 위해서는 쓰기 권한 및 수행 권한이 있어야 함
디렉토리에 쓰기 권한이 없는 경우 디렉토리에 있는 파일 목록을 확인하고 내용을 읽어볼 수 있지만, 새로운 파일을 생성할 수 없음 디렉토리에 실행 권한이 없는 경우, 디렉토리 내부에 어떤 파일이 있는지 알아볼 수 없음 #include <sys/types.h> #include <dirent.h> DIR * opendir(const char *pathname); struct dirent *readdir(DIR *dp); void rewinddir(DIR *dp); int closedir(DIR *dp); struct dirent { ino_t d_ino; char d_name[NAME_MAX + 1]; }

176

177 예제(a program to list files in a directory)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <error.h> void main()(int argc, char argv[]) { DIR *dirp; struct dirent *direntp; if((dirp = opendir(argv[1])) == NULL) { fprintf(“stderr,”Could not open %s directory : %s\n”, argv[1], strerror(error)); exit(1); } while((direntp = readdir(dirp)) != NULL) printf(“%s\n, direntp->d_name); closedir(dirp); exit(0);

178 PROC 파일 시스템

179 시스템에 대한 정보

180

181 개별 프로세스에 대한 정보

182 The Standard I/O Library
고 영 웅

183 Standard I/O 라이브러리의 목적 효율적, 확장가능 그리고 이식성이 뛰어난 파일 제어 루틴 제공
automatic buffering mechanism 제공 사용자에게 보이지 않는 내부 메커니즘 실제적인 파일 접근(저수준의 I/O)을 줄여줌 형식화된 입출력 루틴 및 데이터 변환 기능 제공 특정 운영체제의 특징에 의존적이지 않음

184 read/write와 같은 시스템 콜 호출 버퍼링 메커니즘 저수준 시스템 함수 STANDARD I/O 라이브러리 응용 프로그램 Kernel main 함수 사용자 함수

185 FILE의 개념 Standard I/O 루틴에서는 FILE 유형의 구조체 포인터에 의해서 파일을 인식
모든 read/write 입출력 메커니즘은 FILE 내부의 버퍼를 경유 버퍼가 찬 경우 write를 통해서 실제 출력 read를 호출하는 경우 버퍼가 비어 있을때 실제 read 호출 버퍼를 통해서 입출력이 이루어지므로 실제적인 저수준의 입출력의 횟수를 줄일 수 있음 단점 : 입출력을 시도하는 경우 버퍼에 있는 최근의 내용이 언제 입출력될지 예측하기 힘듬 => 명시적인 버퍼 비우기 명령 수행

186 파일 열기 및 닫기 루틴 type #include <stdio.h>
FILE* fopen(const char * filename, const char *type); int fclose(FILE *fp); type r,rb : read, w,wb : create , a,ab : append(writing only) r+ ,rb+: open for reading and writing w+, wb+ : truncate to 0 length or create for reading and writing a+, ab+ : open or create for reading and writing at end of file

187

188 fflush 열려진 stream 파일의 버퍼를 플러쉬시킴 #include <stdio.h>
int fflush(FILE* stream); 열려진 stream 파일의 버퍼를 플러쉬시킴 버퍼에 있는 내용이 파일 또는 콘솔로 곧바로 출력

189 Kernel console 커널 버퍼 캐릭터 블록 디바이스 응용 프로그램 사용자 함수 STANDARD I/O 라이브러리
read/write와 같은 시스템 콜 호출 버퍼링 메커니즘 STANDARD I/O 라이브러리 응용 프로그램 Kernel main 함수 사용자 함수 fflush 커널 버퍼 console 블록 디바이스 캐릭터

190 단일 문자 입출력 루틴 #include <stdio.h> int getc(FILE *inf); int putc(int c, FILE *outf); The routine getc returns the next character from the input stream putc places a character onto the output stream

191 파일 복사 프로그램

192 라인 단위의 입출력 #include <stdio.h> char * gets(char *buf); char * fgets(char *buf, int nsize, FILE *inf); int puts(const char *string); int fputs(const char *string, FILE *outf); gets reads a sequence of character from standard input, placing each character into a buffer pointed to by buf newline 또는 EOF를 만나는 순간까지 데이터 읽음 newline을 널문자로 대체

193 바이너리 입출력 루틴 inf 파일 스트림으로부터 buffer로 size크기의 데이터를 nitems 만큼 읽거나 또는 쓰는 함수
#include <stdio.h> size_t fread(void *buffer, size_t size, size_t nitems, FILE *inf); size_t fwrite(const void *buffer, size_t size, size_t nitems, FILE *outf); inf 파일 스트림으로부터 buffer로 size크기의 데이터를 nitems 만큼 읽거나 또는 쓰는 함수

194 임의 접근 인터페이스 #include <stdio.h>
int fseek(FILE *stream, long offset , int direction); void rewind(FILE* stream); ling ftell(FILE *stream); fseek는 저수준 함수인 lseek와 비슷한 기능 수행 direction은 출발지점을 의미 SEEK_SET SEEK_CUR SEEK_END ftell은 현재 포지션을 리턴함

195 형식화된 출력 #include <stdio.h>
int printf(const char *fmt, arg1, arg2 …argn); int fprintf(FILE *outf, const char *fmt, arg1, arg2 …argn); int sprintf(char *string, const char *fmt, arg1, arg2 …argn); printf는 지정된 포맷 fmt에 따라서 stdout에 출력 fprintf는 outf 파일 스트림에 지정된 포맷 fmt에 따라서 형식화된 출력 sprintf는 주어진 버퍼 string에 지정된 포맷 fmt에 따라서 형식화된 출력

196 형식 변환 정수 변환 실수 변환 문자열 및 문자 변환 %d : 정수 %u:양의정수 %o:8진수 %x: 16진수
%ld: long 타입 출력 (%lo, %lu, %lx) 실수 변환 %f :float, double %e: 지수 형태 표현 %g: 자동으로 표현 문자열 및 문자 변환 %c : 문자 출력 %s:널문자를 만날때까지 출력

197 형식화된 입력 #include <stdio.h>
int scanf(const char *fmt, arg1, arg2 …argn); int fscanf(FILE *inf, const char *fmt, arg1, arg2 …argn); int sscanf(char *string, const char *fmt, arg1, arg2 …argn); 입력된 아규먼트는 주소가 되어야 함 int inarg; scanf(“%d”, &inarg); printf(%d”, inarg);

198 Inter process communication
고 영 웅

199 IPC의 목적 데이터 전송(data transfer) 데이터 공유(sharing data)
이벤트 전송(event notification) 자원 공유(resource sharing) 프로세스 제어(process control)

200 IPC 종류 pipe(half duflex) FIFO (named pipes) stream pipe(full duflex)
named stream pipes message queues semaphore socket stream

201 IPC 정보제공 명령: IPCS IPCS –[asmq] IPCRM
-a : all , -s : 세마포어, -m :공유메모리, -q : 메시지 큐 IPCRM IPC 제거 명령

202 pipe half duplex 같은 부모 프로세스의 자식들간에 사용가능 파이프는 유닉스의 강력하고 특징적인 기능 제공
#include <unistd.h> int pipe(int filedes[2]); half duplex 같은 부모 프로세스의 자식들간에 사용가능 파이프는 유닉스의 강력하고 특징적인 기능 제공 간단한 명령어를 묶어서 복잡한 프로그램으로 변환 who | wc –l filedes[0]은 읽기 목적으로 개방 filedes[1]은 쓰기 목적으로 개방

203 예제 1 read write fd[0] fd[1]

204 예제 2

205 read fd[0] write fd[1] parent child

206 예제 2 개념도 예제 개요 : 부모 프로세스의 출력을 자식프로세스가 execl로 수행시킨 pager의 입력으로 사용하는 법
stdin stdout stderr pipe fd[0] pipe fd[1] 부모 프로세스 fork 후의 자식 프로세스 execl 후의 dup2 호출 execl 전 execl 후

207

208

209 Using two pipes for parent – child synchoronization
TELL_WAIT : pipe 생성 TELL_PARENT : 자식 프로세스가 부모 프로세스에게 메시지 전달 TELL_CHILD : 부모 프로세스에게 자식 프로세스가 메시지 전달 WAIT_PARENT : 부모 프로세스의 응답을 기다림 WAIT_CHILD : 자식 프로세스의 응답을 기다림

210

211 popen popen은 system함수처럼 자식 프로세스를 생성하고 주어진 comstring에 해당하는 커맨드를 수행함
#include <unistd.h> FILE* popen(const char * comstring, const char *type); int pclose(FILE *strm); popen은 system함수처럼 자식 프로세스를 생성하고 주어진 comstring에 해당하는 커맨드를 수행함 부모 프로세스와 자식 프로세스간에 파이프가 형성 type : r 부모 프로세스는 읽기 기능, 자식 프로세스의 커맨드는 쓰기 기능 제공 type : w 부모 프로세스는 쓰기 기능, 자식 프로세스의 커맨드는 읽기 기능 제공 popen의 리턴값은 pipe를 의미

212 popen() 데이터의 흐름 부모 자식 type : r type : w

213 디렉토리에서 파일 이름을 얻어오는 함수 : getlist(“*.c”, mydir, 100)

214 FIFO named pipe 파일 시스템에 존재하는 특별한 파일 pipe와 동일한 기능 수행 mknod filename p
현재 디렉토리에 filename을 가지는 FIFO 생성 pipe와 동일한 기능 수행

215 FIFO 생성 #include <sys/shm.h>
int mkfifo(const char *filename, mode_t mode); int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0);

216 FIFO 쓰기 호출 FIFO 읽기 호출 FIFO 쓰기 및 읽기 종료

217 System V IPC 개요 각 IPC의 구조체는 커널 내부에서 양의 정수인 식별자로 구분
프로세스간에 메시지를 보내기 위해서 식별자 사용 slot usage sequence number IPC 구조체가 생성될때마다 식별자의 값은 계속 증가 최대값에 도달하면 0으로 되돌아옴 Key IPC를 생성하기 위해서 key값을 지정 Key는 커널 내부에서 식별자로 전환 permission Ipc를 호출하기 위해서는 허가 권한이 있어야 함 ipc_perm 구조체에 정의됨

218 system V IPC 종류 세마포어 메시지 큐 공유메모리

219 세마포어 세마포어는 다중 프로세서에게 공유 자원을 접근하는 허가를 관리하는 카운터 공유 자원 접근 과정
자원을 제어하는 세마포어 테스트 세마포어가 양의 정수이면 자원에 접근 가능 세마포어를 1만큼 감소 – 자원의 한 부분을 사용중임 표시 세마포어가 0 인 경우 세마포어값이 0보다 커질때까지 sleep wake up 이 된 경우 첫번째 단계로 되돌아감 공유 자원을 사용하고 난 후 세마포어를 증가시킴 세마포어의 증감은 원자 연산(atomic operation)이 되어야 함 일반적인 형태는 binary semaphore로 구현됨

220 semid_ds 구조체

221 세마포어 limits Linux 2.2 version

222 세마포어 생성 #include <sys/ipc.h>
int semget(key_t key, int nsems, int flag); 이미 존재하거나 또는 새로운 세마포어를 생성함 nsems는 세마포어의 개수를 정의 이미 존재하는 세마포어를 개방하는 경우 nsems는 0을 지정 성공 : 세마포어 식별자 리턴 실패 : -1

223 세마포어 제어 cmd #include <sys/ipc.h>
int semctl(int semid, int semnum, int cmd, union semun arg); cmd IPC_STAT : semid_ds 구조체에 있는 내용을 arg.buf로 복사 IPC_SET : arg.buf에 있는 내용을 세마포어 구조체로 복사 IPC_RMID : 세마포어 제거 GETVAL : semnum의 멤버인 semval 리턴 SETVAL : arg.val의 값을 semnum의 멤버 semval에 지정 GETPID : semnum의 멤버인 sempid 리턴 GETNCNT : semnum의 멤버인 semncnt 리턴 GETZCNT : semnum의 멤버인 semzcnt 리턴 GETALL : 모든 세마포어 값을 가져옴 SETALL :arg.array에 지정된 값으로 세마포어 값을 세팅

224 semop semop는 세마포어 집합에 대한 연산을 순차적으로 수행함 semoparray 구조체
#include <sys/ipc.h> int semop(int semid, struct sembuf semoparray[], size_t nops); semop는 세마포어 집합에 대한 연산을 순차적으로 수행함 semoparray 구조체 struct sembuf { ushort sem_num; short sem_op; short sem_flg; };

225 메시지 큐 커널에 연결 리스트 형태로 저장된 메시지 메시지 큐 식별자로 구분됨 관련 함수(related function)
msgget : 새로운 큐를 생성하거나 이미 존재하는 큐를 개방 msgsnd : 큐에 새로운 메시지가 추가 msgrcv : 큐에서 메시지를 읽어옴 각 큐는 msqid_ds 구조체를 하나씩 유지함

226 msqid_ds 및 msg 구조체

227 system limits Linux version 2.2에서 메시지 큐의 limit

228 메시지 큐 생성 #include <sys/ipc.h> int msgget(key_t key, int flag);
이미 존재하거나 또는 새로운 큐를 생성함 성공 : 식별자 리턴 실패 : -1

229 메시지 큐 제어 메시지 큐에 대해서 여러가지 오퍼레이션을 제공 cmd #include <sys/ipc.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf); 메시지 큐에 대해서 여러가지 오퍼레이션을 제공 cmd IPC_STAT : 메시지 큐에 있는 정보를 buf로 복사 IPC_SET : buf에 있는 내용으로 메시지 큐 세팅 IPC_RMID : 메시지 큐 제거

230 메시지 전송 ptr은 long 형 메시지 타입과 실제 데이터를 담고 있는 구조체를 가리킴 nbytes는 전송되는 데이터의 크기
#include <sys/ipc.h> int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag); ptr은 long 형 메시지 타입과 실제 데이터를 담고 있는 구조체를 가리킴 nbytes는 전송되는 데이터의 크기 flag IPC_NOWAIT가 세팅된 경우 시스템 리소스가 충분하지 않은 경우 sleep 상태로 대기 IPC_NOWAIT가 세팅되지 않은 경우 시스템 리소스가 충분하지 않은 경우 EAGAIN 에러 메시지를 가지고 곧바로 리턴함

231 메시지 수신 Type 아큐먼트는 수신될 메시지를 지정 Flag #include <sys/ipc.h>
int msgrsv(int msqid, void *ptr, size_t nbytes, long type, int flag); Type 아큐먼트는 수신될 메시지를 지정 type == 0 큐에 있는 첫번째 메시지가 리턴 type > 0 큐에 있는 메시지 중에서 type과 같은 메시지가 리턴 type < 0 type 의 절대값보다 작거나 같은 메시지 타입을 가지고 있는 메시지 리턴 Flag msgsnd와 같은 의미를 지님

232 공유 메모리 공유 메모리를 사용하면 서로 관련이 없는 프로세스들이 같은 물리 메모리를 사용할 수 있음
실행중인 두개의 프로세스 사이의 데이터 전송에 효율적인 방법 동시성 제어는 프로그래머가 해결 logical address space for process A for process B physical memory 공유메모리 A B

233 공유 메모리 생성 리턴값 : 공유 메모리 식별자 공유 메모리의 제한(리눅스 커널 2.2 기준으로 조사)
#include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); 리턴값 : 공유 메모리 식별자 공유 메모리의 제한(리눅스 커널 2.2 기준으로 조사) name description typical value SHMMAX 공유 메모리 최대 세그먼트 싸이즈 0x SHMMIN 공유 메모리 최소 세그먼트 싸이즈 1 SHMMNI 최대 공유 메모리 세그먼트 개수 – 시스템 전체 128 SHMSEG 최대 공유 메모리 세그먼트 개수 – 프로세스당

234 공유 메모리 접속 및 제거 #include <sys/shm.h>
int shmat(int shm_id, const void *shm_addr, int shmflg); int shmdt(void *shm_addr); shm_id : shmget 이 반환한 값 shm_addr : 공유 메모리가 프로세스 주소 공간에 접속될때 어디에 접속해야 하는지 값을 지정 NULL인 경우 시스템이 지정 shmflg SHM_RND, SHM_RDONLY 리턴값 : 공유 메모리가 접속된 주소

235 공유 메모리 제어 command #include <sys/shm.h>
int shmctl(int shm_id, int command, struct shmid_ds *buf); command IPC_STAT : 공유 메모리에 대한 정보를 buf로 복사 IPC_SET : buf에 있는 내용으로 공유메모리 세팅 IPC_RMID : 공유 메모리 세그먼트 제거

236 struct shmid_ds { struct ipc_perm shm_perm; /* operation perms */ int shm_segsz; /* size of segment (bytes) */ time_t shm_atime; /* last attach time */ time_t shm_dtime; /* last detach time */ time_t shm_ctime; /* last change time */ unsigned short shm_cpid; /* pid of creator */ unsigned short shm_lpid; /* pid of last operator */ short shm_nattch; /* no. of current attaches */ /* the following are private */ unsigned short shm_npages; /* size of segment (pages) */ unsigned long *shm_pages; struct shm_desc *attaches; /* descriptors for attaches */ };

237 공유 메모리 예제 소스 코드

238 프로그램 수행 모습

239 공유 메모리 생성 전 공유 메모리 생성 후

240 프로그램 툴 사용법

241 cscope 소스 분석 도구 사용법 cscope.files 생성 cscope 데이터베이스 생성 cscope 기능
파일에 대한 데이터베이스를 생성하기 위한 파일 목록 제공 예제: 현 위치 아래에 있는 c 파일에 대한 파일 목록 생성 find . –name “*.c” > cscope.files cscope 데이터베이스 생성 cscope 수행 cscope 기능 find C symbol, global definition find function called by this function find function calling this function find text string, pattern, file

242 cscope 초기화 과정

243 cscope 수행 화면

244 cscope 수행 화면 : find functions calling this function : scheldule

245 RCS 소스코드 관리 RCS 명령 소스 파일 하나에 대해서 그 변화를 추적하고 구 버전을 복구할 수 있도록 함
각 변화마다 주석문을 넣어서 파일의 변환 과정을 알아보는데 편함 RCS 명령 ci 명령 : 현재 파일을 체크인 co 명령 : 파일을 수정및 작업을 위해서 체크아웃 rlog 명령 : 파일의 변화 내용을 요약해서 보고 싶은 경우 rcsdiff 명령 : 두개의 리비젼 사이의 변화 확인

246 원본 파일 : hello.c rcs -i hello.c : rcs 초기화

247 rcs 초기화후 디렉토리 모습 ci hello.c : 체크인 체크인 후 디렉토리 모습

248 co –l hello.c : 체크 아웃 체크 아웃 후의 디렉토리 구조 체크 아웃 후 파일 수정

249 ci hello.c : 변경후 체크인 rlog hello.c : 파일의 변화 내용 확인

250 rcsdiff –r1.1 –r1.2 hello.c : 두개의 리비젼 사이 변화 확인

251 디버깅툴 Lint 함수 호출 툴 프로그램에서 형식 에러 제거 조금이라도 문제가 될 수 있는 부분을 모두 출력
ctags : 함수 인덱스 생성 cxref : C 소스 코드 분석 상호 참조 생성 cflow : 함수 호출 트리 출력


Download ppt "리눅스 시스템 프로그래밍 고 영 웅."

Similar presentations


Ads by Google