Download presentation
Presentation is loading. Please wait.
1
8. 리눅스의 내부 군자삼락 [君子三樂] 청출어람이청어람 [ 靑出於藍而靑於藍 ] Why Linux ?
Smart phone : Embedded system OS study 몸값
2
소 개 목 적: 프로세스, 메모리 관리, 입출력, 파일 시스템을 지원하기 위해 리눅스가 사용하는 메카니즘에 대하여 설명한다.
커널의 자료구조와 알고리즘에 대하여도 설명한다.
3
소 개 기본 구조: 커널의 기본(Kernel Basics): 시스템 호출과 인터럽트
파일 시스템(File System): 디렉토리 계층, 정규 파일, 주변 장치, 다중 파일 시스템을 관리하는 방법 프로세스 관리(Process Management): 프로세스의 CPU와 메모리를 공유, 시그널의 구현. 입출력(Input/Output): 프로세스의 파일 접근, 터미널 I/O 프로세스간 상호 통신(Interprocess Communication, IPC): 프로세스간의 상호 통신
4
커널의 기본 리눅스 커널은 다음을 수행하는 코드를 포함하는 리눅스 운영체제의 한 부분:
경쟁하는 프로세스 사이에 CPU와 RAM을 공유 모든 시스템 호출을 처리 주변 장치들을 관리 커널은 컴퓨터가 처음 켜질 때, 디스크로부터 RAM으로 적재되는 프로그램이다. 이것은 항상 RAM에 상주한다. 그리고 시스템이 꺼질 때까지, 또는 파괴될 때까지 실행된다. 사용자 프로그램은 시스템 호출 인터페이스를 통하여 커널을 사용한다.
5
커널의 기본 커널 서브시스템: 메모리 관리 프로세스 관리 프로세스간 상호 통신(IPC) 입출력 파일 관리
6
커널의 기본 프로세스와 파일:
7
커널의 기본 커널과 대화: 프로세스는 시스템 호출 인터페이스를 통하여 커널의 기능에 접근한다. 그리고 외부 주변 장치(특수 파일)들은 하드웨어 인터럽트를 통해 커널과 통신한다. 시스템 호출과 하드웨어 인터럽트는 외부 세계가 커널과 대화할 수 있는 유일한 방법이다.
8
커널의 기본 시스템 호출: 시스템 호출은 커널에 대한 프로그래머의 기능적인 인터페이스이다. 그들은 리눅스 커널 내에 거주하는 서브루틴이다.
9
커널의 기본 시스템 호출:
10
커널의 기본 사용자 모드와 커널 모드: 커널의 자료 구조
작업 배열(task array): 시스템 내에 있는 프로세스에 대한 정보를 저장하는 자료 구조인 프로세스 기술자(process descriptor)에 대한 포인터를 가진다. 사용중인 파일 객체 리스트의 각 항목은 적어도 하나의 프로세스에 의해서 사용된다. 프로세스가 파일을 열 때 파일 객체가 만들어지는데, 파일 객체들은 사용중인 파일 객체 리스트를 구성한다. 또한, 프로세스들은 자신이 사용중인 파일들의 정보를 위해 files_struct라는 자료구조를 가진다.
11
커널의 기본 사용자 모드와 커널 모드: 사용자 프로세스는 실행될 때 사용자 모드라고 불리는 특별한 기계 모드에서 작업
사용자 모드는 프로세스가 커널 자료구조에 접근을 허용하는 것을 포함한 특권 명령어를 실행하지 못하도록 한다. 커널 모드 프로세스는 모든 기계어 명령을 실행할 수 있다. 사용자 프로세스가 커널 모드로 들어가기 위한 유일한 방법은 시스템 호출을 실행하는 것이다.
12
커널의 기본 사용자 모드와 커널 모드: 커널은 서로 다른 여러 시스템 호출을 갖기 때문에, 프로세스가 시스템 호출을 요청할 때는 시스템 호출 인수들과 시스템 호출 번호(system call number)를 추가로 전달한다. 시스템 호출 처리기(system call handler)에 의해서 시스템 호출 서비스 루틴(system call service routine)을 호출하여 처리한다. 특별한 복귀 명령(ret_from_sys_call())을 수행하면, 다시 사용자 모드로 반환되어 사용자 프로세스의 코드로 돌아온다. 시스템 호출 번호에 해당하는 시스템 호출 서비스 루틴을 알려주기 위한 시스템 호출 디스페치 테이블(system call dispatch table)을 사용한다.
14
커널의 기본 동기 및 비동기 처리:
15
커널의 기본 인터럽트: 인터럽트는 하드웨어 장치가 커널에게 처리해 줄 것을 통보하는 방법이다.
CPU 시간을 위하여 프로세스들이 경쟁하는 것과 같은 방법으로, 하드웨어 장치들은 인터럽트 처리를 위하여 경쟁한다. 장치들은 그들의 상대적인 중요도에 근거하여, 인터럽트 우선순위가 할당된다. 인터럽트가 발생했을 때, 현재의 프로세스는 일시 중지되고, 커널은 인터럽트의 발생 원인을 알아낸다. 인터럽트를 처리할 코드의 위치를 찾기 위해 하위 커널 메모리에 위치한 인터럽트 벡터표를 조사한다. 그 후, 해당 "인터럽트 처리기" 코드가 실행된다. 인터럽트의 처리기가 인터럽트 처리를 완료했을 때, 중지된 프로세스는 다시 실행된다.
16
커널의 기본 인터럽트:
17
커널의 기본 인터럽트:
18
커널의 기본 인터럽트 도중 인터럽트 처리:
19
커널의 기본 인터럽트 도중 인터럽트 처리:
20
파일 시스템 레이블에 의해 참조되는 파일이 종류:
리눅스 파일은 보통 디렉토리 구조로 알려진, 레이블의 계층 구조에 의해서 구성된다. 정규 파일(Regular file) : 일반적으로 자료 또는 코드에 해당하는 일련의 바이트를 포함한다. 정규 파일은 표준 입출력 시스템 호출을 통해 참조된다. 디렉토리 파일(Directory file) : 특별한 형식으로 디스크에 저장되며 파일 시스템의 중추를 이룬다. 디렉토리 파일은 디렉토리 명시적 시스템 호출을 통해서만 참조된다. 특수 파일(Special file) : 프린터와 디스크 같은 주변 장치나 또는 파이프와 소켓 같은 프로세스간 상호 통신 체계에 해당된다. 특수 파일은 표준 입출력 시스템 호출을 통해 참조된다.
21
파일 시스템 디스크 구조: 디스크 제어기(disk controller)는 리눅스 커널 내에 위치한 특수한 소프트웨어인 디스크 장치 드라이버(disk device driver)로부터의 명령어에 대응하여 읽기/쓰기 헤드를 움직인다.
22
파일 시스템 디스크 구조:
23
파일 시스템 인터리빙: 연속적으로 번호 붙여진 블록을 순서적으로 읽을 때, 디스크 제어기와 디스크 드라이버 사이의 통신 과부하 때문에 각 블록 사이에 잠복 지연(latency delay)이 존재한다. 그러므로 잠복 지연이 경과된 후에 헤드가 정확한 블록에 위치되도록, 논리적으로 연속된 블록들은 디스크 표면상에서 서로 일정한 간격을 가진다.
24
파일 시스템 파일 저장:
25
파일 시스템 블록 입출력:
26
파일 시스템 inode: 리눅스는 각 파일에 대한 정보를 기억하기 위하여 inode(Index Node)라 부르는 구조를 사용한다. 정규 또는 디렉토리 파일의 inode는 그것의 디스크 블록의 위치를 포함한다. 그리고 특수 파일의 inode는 주변 장치를 식별할 수 있는 정보를 포함한다. inode는 파일의 허가권, 소유권, 그룹 및 최근 수정된 시간 같은 파일과 관련되는 정보를 갖는다. inode는 디스크 블록에 대한 포인터와 (대형 파일에 대한) 추가적인 간접 포인터를 포함하는 고정된 크기의 구조체이다. 파일 시스템 내의 모든 inode에는 유일한 inode 번호가 할당되고, 모든 파일은 정확히 하나의 inode를 가진다. 디스크상의 파일들과 관련되는 모든 inode는 inode 리스트라 부르는 디스크의 시작 부분에 있는 특수한 장소에 저장된다.
27
파일 시스템 inode:
28
파일 시스템 inode 내용: 파일의 유형: 정규 파일, 디렉토리, 블록 특수, 문자 특수 등등 파일의 허가권
소유권과 그룹 ID 하드 링크 계수 마지막 수정과 마지막 접근 시간 파일의 길이(바이트), 블록 크기(바이트), 파일 블록 수
29
파일 시스템 Ext2 파일 시스템의 블록 맵: 리눅스 시스템은 가상 파일 시스템을 사용한다.
리눅스의 기본 파일 시스템인 Ext2(또는 Ext3) 파일 시스템은 파일의 데이터가 저장된 블록에 대한 포인터를 가진다. 맨 앞의 12개는 데이터를 저장한 실제 블록에 대한 포인터를 가지며, 나머지 3개는 간접 블록 포인터를 가진다. 이러한 접근법은 Ext2 파일 시스템에서 지원하는 2기가 바이트의 파일을 주소화 되도록 허용한다. 리눅스의 레드햇 7.2 버전부터 기본 파일 시스템인 Ext2에서 Ext3로 변경되었다. Ext3는 shutdown 이후의 불필요한 일관성 조사를 제거하여 가용성 및 자료의 무결성을 높이고 속도 향상 등이 개선된 파일 시스템이다.
30
파일 시스템 Ext2 파일 시스템의 블록 맵:
31
파일 시스템 파일 시스템 구조: 1 2 n+2 부트스트랩 블록 슈퍼 블록 inode 블록들(n 개) 데이터 블록들
부트스트랩 블록 슈퍼 블록 inode 블록들(n 개) 데이터 블록들 LINUX 로드를 이한 하드웨어 지정부트 프로그램 포함 1 파일 시스템에 대한 중요한 정보들을 저장하고 있다 파일시스템의 총 크기, inode 블록의 크기, 갱신날짜 가용 자료 블록 번호들에 대한 체인을 저장한 목록 가용 inode 블록 번호들에 대한 체인을 저장한 목록 2 n+2
32
파일 시스템 슈퍼 블록: 총 inode의 수 파일 시스템의 크기 사용가능한 첫 번째 블록 번호 파일시스템이 생성된 운영체제
블록 그룹 번호 블록 크기 그룹당 블록의 수 그룹당 inode의 수 자유블록의 수 파일 시스템내의 자유 inode의 수 첫번째 inode - 첫 번째 inode는 "/"디렉토리에 대한 디렉토리 엔트리이다.
33
파일 시스템 그룹 기술자와 비트맵: 각 블록 그룹은 자신의 그룹 기술자를 가진다. 이 그룹 기술자는 다음과 같은 정보를 가진다. 블록 비트맵의 블록번호 inode 비트맵의 블록 번호 첫번째 inode 테이블 블록의 블록번호 그룹 내의 자유 블록수 그룹 내의 자유 inode 수 그룹 내의 사용된 디렉토리 수 블록 비트맵은 블록의 할당 상태를 나타내는 비트 맵으로 블록의 수 만큼 존재한다. inode 비트맵은 inode의 할당 상태를 나타내고 블록의 수만큼 존재한다. inode 테이블은 블록의 수만큼 가지며 128바이트로 inode의 정보를 포함한다. 블록의 크기가 1024일 경우에는 한 블록당 8개의 inode를 포함한다.
34
파일 시스템 디렉토리: 첫 번째 inode는 루트(root) 디렉토리가 포함된 블록(들)의 위치를 포함한다.
디렉토리가 만들어질 때, 디렉토리 자신인 "."과 그것의 부모 디렉토리인 ".."을 위한 항목은 자동적으로 할당된다. 파일 이름과 inode 번호로 구성되는 쌍은 효과적으로 이름을 파일에 연결하기 때문에 이러한 연관을 "하드 링크(hard link)"라 부른다. 파일 이름은 디렉토리 블록에 저장되므로 그들은 파일의 inode 내에 저장되지 않는다. 모든 리눅스 시스템은 파일 이름으로 적어도 14개의 문자를 허용한다. 그리고 대부분은 255개 문자까지 길이를 지원한다.
35
파일 시스템 파일 시스템 마운팅: $ mount /dev/fd0 /mnt
$ umount /dev/fd0 또는 $ umount /mnt
36
입출력 입출력 객체:
37
입출력 입출력 시스템 호출: open / close read / write lseek dup unlink Ioctl
mknod / mkdir link mount / umount
38
입출력 입출력 버퍼링: 커널은 디스크에 저장된 데이터를 주메모리로 옮겨 저장하기 위하여 버퍼 캐쉬와 페이지 캐쉬를 사용한다.
버퍼 캐쉬는 디스크에서 데이터를 읽고 쓰는 동안 대기하지 않고 프로세스가 다른 작업을 계속 수행하도록 한다. 버퍼 캐쉬는 다음과 같은 자료구조를 가진다. 캐쉬 내의 버퍼에 대한 정보를 가진 버퍼 헤드 장치와 블록에 해당하는 버퍼에 대한 정보를 저장하여 버퍼 헤드를 빠르게 검색하기 위한 해쉬 테이블
39
입출력 입출력 버퍼링: 페이지 캐쉬는 페이지 입출력을 통해 접근되는 데이터를 캐쉬하기 위해 사용되는 것이다.
일반적으로 read(), write(), mmap()과 같은 시스템 호출을 이용하는 정규 파일에 대한 요청은 페이지 캐쉬를 사용한다. 페이지 캐쉬는 페이지를 다루기 때문에 캐쉬에 저장되는 단위는 페이지이다. 페이지들은 파일의 inode와 파일에 대한 옵셋을 사용하여 캐쉬 내에서 식별된다. 버퍼 캐쉬와 마찬가지로 페이지 캐쉬도 페이지 해쉬 테이블을 가진다. 해쉬 테이블의 검색은 inode와 옵셋을 사용한다.
40
정규파일 입출력 open(): fd=open("/home/user/sample.text", O_RDONLY);
41
정규파일 입출력 read(): read(fd, buf1, 100); /* 100바이트를 버퍼 buf1로 읽어 오기*/ read(fd, buf2, 200); /* 200바이트를 버퍼 buf2로 읽어 오기*/ read(fd, buf3, 5000); /* 5000바이트를 버퍼 buf3로 읽어 오기*/ 첫 번째 "read()"에 의해서 요구되는 자료는 파일의 첫 번째 블록(4096바이트) 내에 존재. 커널은 블록이 버퍼에 없음으로, 디스크로부터 그 블록을 잠기지 않은 버퍼로 복사한다. 버퍼로부터 첫번째 100바이트를 buf1으로 복사한다. 파일 테이블 내에 저장된 파일 위치는 새로운 값 100으로 수정 두 번째 "read()" 에 의해서 요구되는 자료도 또한 파일의 첫 번째 블록 내에 존재한다. 커널은 블록이 이미 버퍼풀 내에 있음으로, 버퍼로부터 buf2로 다음의 200바이트를 복사한다. 파일 위치는 300으로 수정 세 번째 "read()"에 의해서 요구된 자료는 파일의 첫 번째 블록과 두 번째 블록에 각각 부분적으로 존재. 커널은 버퍼풀로부터 buf3로 첫 번째 블록의 나머지 전송. 디스크로부터 잠기지 않은 버퍼로 두 번째 블록을 복사. 버퍼로부터 buf3로 나머지의 자료를 복사. 파일 위치는 5300으로 수정
42
정규파일 입출력 lseek(): lseek(fd, 3000, SEEK_SET);
43
정규파일 입출력 close(): 파일 기술자가 닫히고 그것이 특정 파일과 연관된 유일한 파일 기술자이면, 커널은 파일의 inode를 디스크로 복사한다. 그리고 이에 해당하는 파일 테이블과 inode 테이블 엔트리들을 free로 표시한다. 프로세스가 종료될 때, 커널은 자동적으로 프로세스의 모든 파일 기술자를 닫는다. 여러 파일 기술자들에 의해서 공유될 수 있는 세 가지 방법 파일이 같은 프로세스에 의해서 또는 다른 프로세스에 의해서, 두 번 이상 명시적으로 열린다. 파일 기술자가 "dup()", "dup2()", 또는 "fctnl()"에 의해서 복제된다. 프로세스가 "fork()"를 수행한다. 이 경우 프로세스의 파일 기술자 엔트리들이 모두 복제된다.
44
정규파일 입출력 close(): 파일 기술자가 닫힐 때, 커널은 기술자와 연관된 파일 테이블 내의 참조 계수 필드를 감소시킨다. 만약 파일 테이블 참조 계수가 0보다 크다면, 아무 일도 발생하지 않는다. 만약 참조 계수가 0이 되면, 파일 테이블 엔트리는 free로 표시되고 파일의 inode 내의 참조 계수는 감소된다. 만약 inode 참조 계수가 0보다 크다면, 아무 일도 발생하지 않는다. 만약 참조 계수가 0이 되면, inode는 디스크로 다시 복사되고 inode 엔트리는 free로써 표시된다.
45
정규파일 입출력 dup():
46
정규파일 입출력 unlink(): "unlink()"는 디렉토리로부터 하드 링크를 제거하고 그것과 연관된 inode의 하드 링크 계수를 감소시킨다. 하드 링크 계수가 0으로 되면, 그것을 사용하는 마지막 프로세스가 종료할 때 파일의 inode와 사용자 블록은 할당이 해제된다. 이것은 프로세스가 파일을 unlink하고도, 그 파일이 존재하는 한 접근을 계속한다는 것을 의미한다.
47
정규파일 입출력 unlink():
48
디렉토리 파일 입출력 디렉토리 파일과 정규파일의 차이점:
디렉토리 파일은 단지 "mknod()" 또는 "mkdir( )"를 사용하여 생성될 수 있다. 디렉토리 파일은 단지 “readdir()"를 사용하여 읽어질 수 있다. 디렉토리 파일은 단지 "link()"를 사용하여 수정될 수 있다.
49
디렉토리 파일 입출력 mknod(): "mknod()"는 디렉토리, 명명된 파이프, 또는 특수 파일을 생성한다.
모든 경우에 있어서 디스크에 새로운 inode를 할당하고, 그것에 적절한 유형 필드를 설정하고 하드 링크를 통하여 그것을 디렉토리 계층으로 추가함으로써, "mknod()" 시스템 호출은 시작한다. 만약 디렉토리가 생성되면, 사용자 블록은 inode와 연계되고 또한 디폴트 "."과 ".." 엔트리로 채워진다. 만약 특수 파일이 생성되면, 적절한 주(major)와 보조(minor) 장치 번호가 inode 내에 저장된다.
50
디렉토리 파일 입출력 link(): "link()"는 디렉토리에 하드 링크를 추가한다. 다음은 "link()"의 사용 예이다.
link("/home/user/file1.c", "/home/user/file2.c"); 커널은 소스 파일명 "/home/user/file1.c"의 inode 번호를 발견하고, 이를 목적 디렉토리 "/home/user"에 있는 이름 file2.c와 연관시킨다. 이로 인해 inode의 하드 링크의 계수가 증가된다. 수퍼 유저만이 디렉토리를 링크할 수 있으며, 이 제한은 부주의한 사용자들이 원형 디렉토리들을 생성하지 못하도록 하기위해 존재한다.
51
디렉토리 파일 입출력 mount(): 파일 시스템이 "mount()"를 사용하여 마운트되면, 다음 필드들을 포함하는 엔트리가 마운트 테이블에 추가된다. 새롭게 마운트된 파일 시스템을 포함하는 장치 수 새롭게 마운트된 파일 시스템의 루트 inode에 대한 포인터 마운트 점(point)의 inode에 대한 포인터 새롭게 마운트된 파일 시스템의 버퍼화된 수퍼 블록에 대한 포인터
52
디렉토리 파일 입출력 mount(): mount("/dev/da0", "/mnt", 0);
53
디렉토리 파일 입출력 파일 이름 전환: 이름 전환 알고리즘은, 마운트 점을 지나는 경로 이름을 해석할 때 마운트 테이블의 내용을 사용한다. 이것은 디렉토리 계층을 위로 또는 아래로 움직일 때 발생한다. $ cd /mnt/tmp1 $ cd ../../bin 첫 번째 cd 명령은 루트 장치로부터 "/dev/da0" 장치로 교차된다. 두 번째 cd 명령은 루트 장치로 다시 교차한다.
54
디렉토리 파일 입출력 파일 이름 전환: inode의 전환 과정 동안 마운트 포인트(mount point)인 inode가 나타나면, 마운트된 파일 시스템의 루트 inode에 대한 포인터가 대신 반환된다. 예를 들면, "/mnt/tmp1'의 "/mnt" 위치가 전환될 때, 마운트된 파일 시스템의 루트 노드에 대한 포인터가 반환된다. 이 포인터는 경로 이름 전환의 나머지를 위한 출발점으로 사용된다. ".." 경로 이름 구성 요소를 대하면, 커널은 마운트 점이 교차되는지를 검사한다. 만약 전환 과정의 현재 inode 포인터가 루트 노드를 가리키고 ".."또한 루트 노드를 가리킨다면, 그때 교차점에 도달한 것이다.
55
디렉토리 파일 입출력 파일 이름 전환:
56
디렉토리 파일 입출력 unmount(): unmount될 파일 시스템 내에 열린 파일이 없는가를 검사한다. 파일 시스템의 장치 번호를 포함한 엔트리를 찾아 inode 테이블을 스캔함으로써 검사 할 수 있다. 만약 어떤 사용중인 inode들이 발견된다면, 시스템 호출은 실패한다. 수퍼 블록, 쓰기-지연 블록, 버퍼화된 inode들을 파일 시스템으로 다시 옮긴다. 마운트 테이블 항목을 제거하고 마운트 점 디렉토리로부터 "마운트 점" 표시를 제거한다.
57
특수 파일 입출력 특수 목적 파일: 대부분의 특수 목적 파일은 프린터, 터미널, 디스크 드라이버 같은 주변 장치에 해당된다.
시스템 내의 모든 주변 장치는, 주변 장치 명세 코드를 모두 포함한 소프트웨어인 장치 드라이버를 가지고 있다. 예) 테이프 드라이버의 장치 드라이버는 테이프를 되감거나 장력 조절을 위한 코드를 포함한다. 특정 종류의 주변 장치는 단일 드라이버에 의해서 제어된다. 시스템 내의 모든 주변 장치를 위한 장치 드라이버는 커널이 시스템 관리자에 의해 구성될 때 커널 내에 링크 되어야 한다.
58
특수 파일 입출력 장치 인터페이스: 2개의 주변 장치의 인터페이스
블록 지향적(block-oriented): 입출력이 버퍼화되고, 물리적인 입출력이 블록 단위를 기본으로 수행됨을 의미한다. 디스크 드라이버와 테이프 드라이버는 블록 위주의 인터페이스를 가진다. 문자 지향적(character-oriented): 입출력이 버퍼화되지 않고, 물리적 입출력이 문자 단위를 기본으로 발생한다. 문자 지향적 인터페이스는 때때로 raw 인터페이스로 알려져 있다. 디스크 드라이버와 테이프 드라이버를 포함한 모든 주변 장치는 보통 raw 인터페이스를 가진다. 랜덤 접근과 공통적인 블록에 대한 반복적인 접근을 실행한 경우에는, 블록 지향적 인터페이스를 통해 주변 장치에 접근하는 것이 좋은 방법이다. 단일 선형 순서의 블록을 접근한다면, 문자 지향적 인터페이스를 통하여 주변 장치에 접근하는 것이 좋다. 이것은 커널의 내부적 버퍼링 체계에서 오버헤드를 피하고 커널이 하드웨어의 DMA(Direct Memory Access) 능력을 사용할 수 있게 한다.
59
특수 파일 입출력 스위치 테이블: 모든 리눅스의 장치 드라이버는 주변 장치를 열고, 닫고, 주변 장치에 접근하는 함수에 대한 진입점의 집합을 포함하는 미리 정의된 형식에 따라야 한다. 블록 지향적 장치 드라이버는 물리적 장치에게 블록 지향적 입출력 수행을 위해 커널에 의해서 사용되는 진입점을 포함한다. 각 블록 지향적 인터페이스와 각 문자 지향적 인터페이스의 진입점은 블록 장치 스위치 테이블과 문자 장치 스위치 테이블이라 불리는 시스템 테이블에 저장된다.
60
특수 파일 입출력 스위치 테이블:
61
특수 파일 입출력 스위치 테이블 : fd = open("/dev/tty2", O_RDWR);
62
특수 파일 입출력 open(): 프로세스가 파일을 열 때 커널은 파일의 inode의 유형 필드를 조사함으로써 주변 장치를 식별할 수 있다. 만약 필드가 블록 지향적 또는 문자 지향적 장치를 나타낸다면, 주번호와 보조번호를 읽어 장치의 종류와 열려고 하는 장치의 실예(instance)를 정한다. "open()"이 처리될 때, 커널은 주변 장치와 무관한 동작에 이어 주변 장치에 의존적인 동작을 수행한다. "open()"의 주변 장치에 무관한 부분은 정규 파일 "open()"과 같은 작업을 한다. 파일의 inode는 inode 테이블에 저장되고, 파일 테이블의 엔트리가 만들어진다. "open()"의 주변 장치에 의존적인 부분은 장치 드라이버의 "open()" 루틴을 불러낸다. 예) 테이프 드라이버의 "open()" 루틴은 보통 테이프를 되감고 장력을 조절한다.
63
특수 파일 입출력 read(): 문자 지향적 장치로부터 읽어들일 때, "read()"는 물리적 입출력을 실행하는 장치 드라이버 내의 "read" 함수를 불러낸다. 블록 지향적 장치로부터 읽을 때, "read()"는 표준 입출력 버퍼링 방법을 사용한다. 만약 블록이 장치로부터 버퍼풀로 물리적인 복사를 필요로 한다면, 장치 드라이버 내의 "strategy" 함수가 호출된다. 이 함수는 읽기와 쓰기 능력을 결합한다.
64
특수 파일 입출력 write(): 문자 지향적 장치에 쓸 때, "write()"는 물리적 입출력을 실행하도록 장치 드라이버에 있는 write 함수를 실행한다. 블록 지향적 장치에 쓸 때, "write()"는 입출력 버퍼링 시스템을 사용한다. 쓰기 지연이 발생할 때, 장치의 "strategy" 함수가 물리적 입출력을 실행하도록 사용된다.
65
특수 파일 입출력 close(): 커널은 정규 파일을 닫는 것과 같은 방법으로 주변 장치를 닫는다. "close()“ 를 수행하는 프로세스가 장치를 접근한 마지막 프로세스일 때는 예외이다. 이런 특별한 경우에는, 장치 드라이버의 "close()" 루틴이 실행되고 정규 파일을 닫기 위한 일련의 동작들이 뒤따른다. 단일 장치가 하나 이상의 inode를 경유하여 접근되는 것 같이, 커널은 사용중인 inode들의 참조 계수를 간단히 조사하여 그것의 마지막 사용자에 의해서 특수 파일이 닫혀 있었다고 결정할 수 없다. 이와 같은 상황은 하나의 프로세스가 블록 지향적 인터페이스를 경유하여 장치를 접근하고 다른 프로세스가 동시에 문자 지향적 인터페이스를 경유하여 같은 파일에 접근할 때 발생한다. 이 경우에, inode 리스트에서 동일한 물리적 장치와 연관된 다른 inode를 탐색해야 한다.
66
특수 파일 입출력 ioctl(): "ioctl()"는 파일 기술자를 통하여 장치 명시적 특성들을 제어한다.
장치 명시적 동작의 예는 터미널 보드율 설정, 프린터의 폰트 선택, 테이프 드라이버 되감기를 포함한다.
67
터미널 입출력 터미널 장치 드라이버: 터미널 장치 드라이버와 다른 장치 드라이버 사이의 주된 차이점은 그들의 입력과 출력에 다양한 종류의 선후 처리를 각각 지원해야 한다는 것이다. 다양한 각 처리를 line discipline이라 부른다. 터미널의 line discipline는 "ioctl()"을 사용하여 설정된다.
68
터미널 입출력 line discipline :
raw 모드는 전혀 특수한 처리를 수행하지 않는다. 키보드에서 입력되는 문자는 "ioctl()" 인수에 근거한 읽기 처리에 유용하다. Control-C 같은 일련의 키 조작은 어떤 특수한 행동도 초래하지 않고, 보통의 ASCII 문자들로 통과된다. 예를 들면, Control-C는 ASCII 값 3을 가진 문자로 읽혀진다. raw 모드는 자신만의 문자 처리를 선호하는 편집기 같은 응용에 의해서 사용된다. cbreak 모드는 오직 몇 개의 키 순서만을 특별히 처리한다. 예를 들면 Control-S와 Control-Q를 통한 흐름 제어는 계속 유효하다. 마찬가지로, Control-C는 전면 작업 내의 모든 프로세스에게 인터럽트 시그널을 발생한다. raw 모드에서와 같이 모든 다른 문자들은 "ioctl()" 인수에 근거한 읽기 처리에 유용하다. cooked 모드(때로는 canonical 모드로 알려진)는, 완전한 선후 처리를 수행한다. 이 모드에서, delete와 backspace 키는 자주 사용되지 않는 단어 지우기와 라인 지우기 문자와 함께 특별한 의미를 가진다. 입력은 Enter 키가 눌러졌을 때만, 읽기 처리에 유용하게 된다. 비슷하게, 탭(tab)은 출력할 때 특별한 의미를 가지며 line discipline에 의해서 공란의 정확한 수가 확장된다. newline 문자는 carriage return 문자와 newline 문자의 쌍으로 확장된다.
69
터미널 입출력 터미널 자료구조: clists: 고정된 크기의 문자 배열의 링크 리스트이다. 선처리되는 입력, 후처리되는 입력, 각 터미널과 연관된 출력을 버퍼하기 위하여 이 구조를 사용한다. tty 구조: clists에 대한 포인터와 현재 선택된 line discipline, 특별히 처리될 문자들의 목록, "ioctl()"에 의해 설정될 옵션을 포함하는 터미널의 상태를 포함한다. 터미널마다 하나의 tty 구조가 있다.
70
터미널 입출력 스트림: open() 시스템 호출에 의해 스트림이 생성될 때, 스트림 헤드(stream head)가 생성된다.
스트림 헤드는 사용자 프로그램에게 시스템 호출 인터페이스를 제공하며, 스트림을 나타내는 자료 구조를 포함한다. 어떤 새로운 터미널 드라이버들은 위에서 설명된 clist 체계가 아닌 STREAMS로 구현된다.
71
프로세스 관리(작업관리) 실행 가능 파일: 파일의 첫 번째 몇 바이트는 매직 수(magic number)라고 알려져 있고, 커널에 의해서 실행될 수 있는 파일의 유형을 정의하는데 사용된다. 만약 첫 번째 두 바이트가 문자 "#!"이면, 커널은 셸 텍스트를 포함한 실행 가능 파일임을 알고, 텍스트를 실행하도록 셸을 호출한다. 만일 첫 두 바이트가 "#!"가 아니면 , 그 파일을 기계 코드와 자료를 포함한 정규 적재 이미지로 인식한다. 이런 종류의 파일은 코드나 자료를 포함하는 몇 개의 부분으로 나누어지는데, 각 부분들은 독립된 헤더를 갖는다.
72
프로세스 관리(작업관리) 실행 가능 파일:
73
프로세스 관리(작업관리) 첫 번째 프로세스:
리눅스는 프로세스를 생성하고, 이를 명명된 실행 파일과 연관시킴으로써 프로그램을 실행한다. 기존의 프로세스를 복제하여 새로 생성된 자식 프로세스를 실행 파일 X와 연관시켜야한다. 프로세스 ID(PID)가 0인 첫번째 프로세스는 swapper 프로세스라고 부르며 부트 시간 동안 리눅스에 의해서 생성된다. 이 프로세스는 init 프로세스를 만들고, 커널 스레드를 만든다. 이 스레드들이 하는 일은 메모리 캐슁과 스와핑 작업을 수행한다. 리눅스에서는 0번 프로세스를 확인할 수 없다. ps명령을 이용하면 1번 프로세스부터 보여준다.
74
프로세스 관리(작업관리) 첫 번째 프로세스:
75
프로세스 관리(작업관리) 커널 스레드와 사용자 프로세스:
대부분의 프로세스는 시스템 호출 시에 커널 모드로 일시적으로 전환되는 것을 제외하고는 사용자 모드에서 실행된다. 커널 스레드로 만들어진 스레드들은 그들의 중요성 때문에 커널 모드에서 영구적으로 실행되며, 유닉스에서는 커널 프로세스라고 부르나 리눅스에서는 커널 스레드라고 부른다. 사용자에 의해서 생성된 다른 프로세스들은 사용자 프로세스로 이들과 구별된다.
76
프로세스 관리(작업관리) 프로세스 계층 구조:
프로세스가 "fork()"를 사용함으로써 복제할 때, 원래의 프로세스는 자식 프로세스의 부모(parent)로써 알려진다. 모든 사용자 프로세스는 PID 1인 init 프로세스의 자손이다. 부모와 자식 프로세스들은 init 프로세스를 루트 프로세스로 갖는 계층 구조 내에서 관련되어 있다.
77
프로세스 관리(작업관리) 프로세스 상태: TASK_RUNNUNG : 프로세스가 현재 CPU를 사용하거나, 실행을 기다린다.
TASK_INTERRUPTIBLE : 프로세스가 어떤 사건이 발생하기를 기다리는 것을 의미하며, 잠듬(Sleeping)상태라고 말한다. 예를 들어 만약 프로세스가 "read()" 시스템 호출을 실행했다면, 입출력 요구를 끝마칠 때까지 잠든다. TASK_UNINTERRUPTIBLE : 잠들어 있는 프로세스에 신호를 전달해도 상태가 변경되지 않는다. 예를 들어, 장치 파일을 열 때 이 장치의 하드웨어 상태를 검사할 동안 이 상태에 있을 수 있다. TASK_STOPPED : 일시 중지(Suspended)상태이며 프로세스가 SIGSTOP 같은 시그널에 의해서 "frozen"되어 있다는 것을 의미한다. 그 프로세스는 SIGCONT 신호가 보내졌을 때만 재개된다. 예를 들면, 키보드로부터 Control-Z는 전면 작업내에 있는 모든 프로세스를 일시 중지시킨다.
78
프로세스 관리(작업관리) 프로세스 상태: TASK_ZOMBIE : 좀비(Zombified)상태이며 프로세스가 종결되었으나, 자신의 부모에게 종료 코드를 아직 반환하지 않았다는 것을 의미한다. 프로세스는 그들의 부모가 "wait()" 시스템 호출을 사용하여 반환 코드를 받아들일 때까지 좀비로 남는다.
79
프로세스 관리(작업관리) 프로세스의 구성: 코드 영역(code area): 프로세스의 실행할 수 있는 부분을 포함
자료 영역(data area): 정적 자료를 포함하기 위하여 프로세스에 의해서 사용 스택 영역(stack area): 일시적인 자료를 저장하기 위하여 프로세스에 의해서 사용 사용자 영역(user area): 프로세스에 대한 관리(housekeeping) 정보를 가지고 있다. 페이지 테이블(page table): 메모리 관리 시스템에 의하여 사용.
80
프로세스 관리(작업관리) 프로세스의 구성:
81
프로세스 관리(작업관리) 사용자 영역: 시스템 내의 모든 프로세스는 프로세스 관리를 위해 커널에 의해서 사용되는 "관리(housekeeping)" 정보를 가지고 있다. 이 정보는 사용자 영역에 저장된다. 모든 프로세스는 고유의 사용자 영역을 소유한다. 사용자 영역은 커널의 자료 영역 내에 생성되고 단지 커널에 의해서만 접근할 수 있다. 사용자 프로세스는 사용자 영역에 접근할 수 없다.
82
프로세스 관리(작업관리) 작업 배열: 커널의 자료구조에는 시스템 내의 각 프로세스마다 하나의 항목을 가지는 고정된 크기의 작업 배열(task array)이 있다. 이 작업 배열은 프로세스 기술자의 포인터를 가지며 커널의 자료 영역 내에 만들어지고, 단지 커널에 의해서만 접근이 가능하다. 프로세스 ID(PID)와 부모 프로세스 ID(PPID) 실제와 유효 사용자 ID(UID)와 그룹 ID(GID) 프로세스의 상태 코드, 자료, 스택, 사용자 영역의 위치 모든 대기중인 시그널의 목록
83
프로세스 관리(작업관리) 스케줄러: 커널은 경쟁하는 프로세스들 사이에 CPU를 공유해야 한다.
시간 공유 기술이란 각 프로세스에게 실행을 허가하기 위해 적은 시간 할당량 또는 시간 조건을 할당하는 것이다. 리눅스 스케줄러는 우선순위를 고려하는데 이것을 "goodness" 순위라고 한다. 즉, 프로세스가 오래동안 CPU를 사용하지 못하면 그들의 우선순위는 증가되고, CPU를 자주 사용하는 프로세스는 그들의 우선순위가 감소하게된다.
84
프로세스 관리(작업관리) 실행 파일 적재: execve()
코드와 자료 페이지 테이블 항목은 자신에 해당하는 디스크 블록의 위치를 포함하도록 설정된다. 이 위치들은 실행 파일의 inode와 헤더로부터 추출된다. 프로세스가 처음으로 이 페이지 중 하나에 접근할 때, 이에 해당하는 블록은 디스크로부터 주메모리로 복사되고, 페이지 테이블의 항목은 물리적인 주메모리 페이지 번호로 변경된다.
85
프로세스 관리(작업관리) 실행 파일 적재: execve()
86
프로세스 관리(작업관리) 프로세스 복제: fork()
프로세스는 가끔 "fork()" 다음에 바로 "exec()"가 뒤따르도록 하여, 그것의 이전 메모리 영역의 할당을 해제한다. 자식의 코드 항목을 부모의 코드 페이지 테이블을 포인트 하도록 설정한다. 그리고 그것이 공유되고 있다는 것을 가리키도록 페이지 테이블과 연관되어 있는 참조 계수를 증가한다. 부모의 복제인 자식을 위한 자료 페이지 테이블과 스택 페이지 테이블을 만든다. 그리고 프로세스의 자료와 스택 테이블의 모든 페이지 테이블의 엔트리에 대한 copy on write 비트를 설정한다. 만약 부모의 페이지 테이블 엔트리가 RAM을 가리키면 자식의 페이지 테이블 엔트리는 같은 위치를 가리키도록 설정하고, RAM 페이지와 연관된 참조 계수는 그것이 공유되고 있다는 것을 나타내도록 값을 증가시킨다. 비슷하게, 만약 부모의 페이지 테이블 엔트리가 스왑 공간을 가리키면, 자식의 페이지 테이블 엔트리도 같은 위치를 가리키도록 설정하고, swap 공간 위치와 연관된 참조 계수는 그것이 공유되고 있다는 것을 나타내도록 증가시킨다.
87
프로세스 관리(작업관리)
88
프로세스 관리(작업관리) 프로세스의 종결: exit() 프로세스의 파일 기술자(file descriptor)들은 닫혀진다.
프로세스의 각 참조 계수는 감소한다. 만약 참조 계수가 0으로 떨어지면, 프로세스의 모든 RAM 페이지와 적절하다면 swap 페이지의 참조 계수는 감소된다. 참조계수를 0으로 가지는 모든 RAM 또는 swap 페이지들은 할당이 해제된다.
Similar presentations