- 메모리 영역에 접근하게 될 때, 메모리에 페이지 부재(=페이지 폴트(Page fault)율이 높은 것을 의미하며, 심각한 성능 저하를 초래합니다.
- 활발하게 사용되는 페이지 집합을 지원해 줄 만큼 프레임이 충분히 할당 받지 못한 프로세스는 페이지 폴트(Page fault)가 발생하게 됩니다.
이 때, 페이지 교체가 필요하지만 이미 활발히 사용되는 페이지들만으로 이루어져 있으므로 어떤 페이지가 교체되던 바로 다시 페이지 교체가 필요하게 될 것입니다.
결과적으로 바로바로 반복해서 페이지 폴트가 발생하며, 교체된 페이지는 또 다시 얼마 지나지 않아 읽어올 필요가 생기게 됩니다. 이렇게 과도한 페이징 작업을 Thrasing(쓰레싱) 이라 합니다.
(쓰레싱의 원인)
1) 다중 프로그래밍 정도가 높아짐에 따라 CPU이용률이 높아지게 되고, CPU이용률이 최대값에 도달했을 때, 다중 프로그래밍의 정도가 그 이상으로 커지게 되면 쓰레싱이 일어나게 되고 CPU이용률은 급격히 떨어집니다.
2) 운영체제는 CPU이용률을 감시하며, CPU이용률이 너무 낮아지면 새로운 프로세스를 시스템에 추가하여 다중 프로그래밍의 정도를 높이게 됩니다. 이 때 전역 페이지 교체 알고리즘을 사용하여 어떤 프로세스의 페이지인지에 대한 고려없이 교체를 수행하게 됩니다.
그런데, 교체된 페이지들이 해당 프로세스에서 필요로 하는 것이었다면 그 프로세스 역시 페이지 폴트를 발생시키고 또 다른 프로세스에서 프레임을 가져옵니다.
이러한 프로세스들이 페이지 스왑 인, 스왑 아웃을 위해 페이징 장치를 사용해야 하는데, 이 장치에 대한 Queueing 이 진행되며 Ready-Queue는 비게 됩니다.
프로세스들이 페이징 장치를 기다리는 동안 CPU이용률은 떨어지게 되고, CPU 스케줄러는 이용률이 떨어지는 것을 보고 높이기 위하여 새로운 프로세스를 추가하여 다중 프로그래밍의 정도를 더 높입니다.
새로 시작하는 프로세스는 실행중인 프로세스들로부터 프레임을 가져오고자 하며, 더 많은 페이지 폴트와 더 긴 페이징 대기시간을 야기하게 됩니다.
결과적으로 CPU이용률은 더 떨어지게 되며, CPU스케줄러는 다중 프로그래밍의 정도를 더 높이려 하게 되어 쓰레싱이 일어나게 됩니다. 따라서 시스템 처리율은 상당히 낮아지고 페이지 폴트는 늘게되어 실질적인 메모리에 접근하는 시간은 증가하고 프로세스들은 페이징 하는데에 시간을 소비하게 되어 아무런 일도 할 수 없는 상태가 됩니다.
[다중 프로그래밍의 정도]
쓰레싱은 지역교환 알고리즘이나 우선순위 교환 알고리즘을 사용해 제한할 수 있습니다.
-> 지역교환 알고리즘 하에서는 한 프로세스가 쓰레싱을 유발하더라도 다른 프로세스로부터 프레임을 뺏어 올 수 없으므로 다른 프로세스는 쓰레싱에서 자유로울 수 있습니다.
(쓰레싱 현상 방지)
: 각 프로세스가 필요로 하는 최소한의 프레임 갯수를 보장해주어야 합니다.
참고 ) http://faithpac27.tistory.com/entry/쓰레싱-Thrashing-이란
fork()와 exec()는 모두 한 프로세스가 다른 프로세스를 실행시키기 위해 사용하게 됩니다.
exec에는 execl, execv등 여러가지 함수군을 가지고 있습니다. exec의 함수군에 대해서는 아래쪽에서 차이를 간단히 정리하고자 합니다.
우선 fork()와 exec()의 차이점은 fork() 시스템 호출은 새로운 프로세스를 위한 메모리를 할당합니다. 그리고 fork()를 호출한 프로세스를 새로운 공간으로 전부 복사하게 되고, 원래 프로세스는 원래 프로세스대로 작업을 실행하고 fork()를 이용해서 생성된 프로세스도 그 나름대로 fork() 시스템 콜이 수행된 라인의 다음 라인부터 실행이 됩니다. (새로 생성된 프로세스는 원래의 프로세스와 똑같은 코드를 가지고 있습니다.)
반면, exec()는 fork()처럼 새로운 프로세스를 위한 메모리를 할당하지 않고, exec()를 호출한 프로세스가 아닌exec()에 의해 호출된 프로세스만 메모리에 남게됩니다.
간단히 정리하면, fork()의 결과는 프로세스가 하나 더 생기는 것입니다.( = 프로세스 id- PID 가 완전히 다른 또 하나의 프로세스가 생기는 것)
반면 exec()실행의 결과로 생성되는 새로운 프로세스는 없고, exec()를 호출한 프로세스의 PID가 그대로 새로운 프로세스에 적용이 되며, exec()를 호출한 프로세스는 새로운 프로세스에 의해 덮어 쓰여지게 됩니다.
이제, exec()관련 함수들에 대해 조금 간단히 다뤄볼까 합니다. exec는 execl, execv, execlp, execvp 등이 있습니다.
이들에 대하여 본 4가지만 간단히 구분하는 방법을 정리해보았습니다.
exec를 먼저 l계열(execl, execlp)과 v계열(execv, execvp)로 나누어 설명하겠습니다.
l계열 : 인자를 열거하는 방식이 나열형
v계열 : 인자를 열거하는 방식이 배열형
다음으로 p가 붙은 계열(execlp, execvp), 안붙은 계열(execl, execv)로 나누어 정리하면,
p가 안붙은 계열 : 경로를 지정해주면 ,현재/절대경로를 기준으로 찾게 됩니다.(경로로 실행파일을 지정)
p가 붙은 계열(path) : path에 잡혀있으면 실행됩니다.(실행파일의 이름만 지정)
exec계열은 첫번째 인자의 코드가 들어오고 나머지 기존에 exec아래에서 실행해야할 코드는 전부 잃어버리게 된다는 점을 가지고 있다고 보시면 됩니다.
IPC(Inter Process Communication) - 프로세스 간 통신에 대하여 종류와 특징들에 대하여 살펴보겠습니다.
[리눅스 커널 구조]
- 위그림처럼 Process는완전히독립된실행객체입니다. 서로독립되어 있다는것은다른프로세스의영향을받지않는다는장점이있습니다. 그러나독립되어있는만큼별도의설비가없이는서로간에통신이어렵다는문제가있게 됩니다. 이를위해서커널영역에서 IPC라는내부프로세스간통신 - Inter Process Communication을제공하게 되고,프로세스는커널이제공하는 IPC설비를이용해서프로세스간통신을할수있게 됩니다.
IPC의 2가지 표준(System V IPC와 POSIX IPC)
- System V IPC는 오래된 버전이고 POSIX IPC는 비교적 최근에 개발된 표준입니다. System V IPC는 오랜 역사를 가진 만큼 이기종간 코드 호환성을 확실히 보장해 주지만, API가 오래되었으며, 함수명도 명확하지 않습니다. POSIX IPC는 직관적으로 API가 구성되어 있어서 상대적으로 조금 더 사용하기 쉽다고 보여집니다.
IPC 설비들
- 현실에서도 필요에 따라 다양한 통신 설비들이 존재하는 것처럼 IPC에도 다양한 설비들이 존재합니다. 각각의 필요에 따라서 적당한 통신 설비들이 준비되어야 하는 것과 마찬가지로 내부 프로세스간 통신에도 그 상황에 맞는 IPC 설비를 선택할 필요가 있게 됩니다.
상황에 맞는 IPC의 선택은, 특히 fork()를 이용해서 만들어진 멀티 프로세스의 프로그램에 있어서 중요합니다. 잘못된 IPC 설비의 선택은 코딩과정을 어렵게 만들거나 프로그램의 작동을 효율적이지 못하게 만들 수 있기 때문입니다.
1) PIPE (익명 PIPE, Anonymous PIPE)
- 위 그림은 PIPE의 작동원리를 보여줍니다. 파이프는 두 개의 프로세스를 연결하게 되고, 하나의 프로세스는 데이터를 쓰기만, 다른 하나는 데이터를 읽기만 할 수 있습니다. 한쪽 방향으로만 통신이 가능한 파이프의 특징 때문에 Half-Duplex(반이중) 통신이라고 부르기도 합니다.
PIPE와 같은 반이중 통신의 경우 하나의 통신선로는 읽기나 쓰기 중 하나만 가능하므로 만약 읽기와 쓰기, 즉 송/수신을 모두 하기 원한다면 두개의 파이프를 만들어야만 가능해집니다.
PIPE는 매우 간단하게 사용할 수 있다는 장점이 있습니다. 만약한쪽프로세스가단지읽기만하고다른쪽프로세스는단지쓰기만하는,단순한데이터흐름을가진다면고민없이 PIPE를사용하면됩니다. 단점은반이중통신이라는점으로만약프로세스가읽기와쓰기통신모두를해야한다면 PIPE를두개만들어야하는데, 구현이꽤나복잡해질수있습니다. 만약전이중통신을고려해야될상황이라면 PIPE는좋은선택이아니라고 보여집니다.
2) Named PIPE(FIFO)
- 익명파이프(Pipe)는통신을할프로세스가명확하게알수있는경우사용합니다. 예를들어자식과부모프로세스간통신의 경우에 사용할 수 있으며, Named PIPE는 전혀 모르는 상태의 프로세스들 사이의 통신의 경우 사용합니다. 익명 파이프(PIPE)의 단점으로 같은 PPID(같은 부모 프로세스)를 가지는 프로세스들 사이에서만 통신이 가능하지만, Named PIPE는 그 부분을 해결한, PIPE의 확장이라고 할 수 있을 것입니다. Named PIPE는부모 프로세스와 무관하게 전혀 다른 모든 프로세스들 사이에서 통신이 가능한데 그 이유는 프로세스 통신을 위해 이름이 있는 파일을 사용하기 때문입니다. Named PIPE의 생성은 mkfifo를 통해 이뤄지는데, mkfifo가 성공하면 명명된 파일이 생성됩니다.
단점으로는, Named PIPE도 PIPE의 또 다른 단점인 읽기/쓰기가 동시에 가능하지 않으며, read-only, write-only만 가능합니다. 하지만 통신선로가 파일로 존재하므로 하나를 읽기 전용으로 열고 다른 하나를 쓰기전용으로 영어서 이러한 read/write문제를 해결 할 수 있습니다. 호스트 영역의 서버 클라이언트 간에 전이중 통신을 위해서는 결국 PIPE와 같이 두개의 FIFO파일이 필요하게 됩니다.
3)Message Queue
- Queue(큐)는선입선출의자료구조를가지는통신설비로커널에서관리합니다. 입출력방식으로보자면 위의 Named PIPE와동일하다고볼수있을것입니다. Named PIPE와다른점이라면 Name PIPE가데이터의흐름이라면메시지 큐는메모리 공간이라는점입니다. 파이프가아닌, 어디에서나물건을꺼낼수있는컨테이너벨트라고보면될것입니다.
- Socket은 프로세스와 시스템의 기초적인 부분이며, 프로세스 들 사이의 통신을 가능하게 합니다. sys/socket.h>라는 헤더를 이용하여 사용할 수 있으며, 같은 도메인에서의 경우에서 연결 될 수 있습니다. 소켓을 사용하기 위해서는 생성해주고, 이름을 지정해주어야 합니다. 또한 domain과 type, Protocol을 지정해 주어야 합니다. 서버 단에서는 bind, listen, accept를 해주어 소켓 연결을 위한 준비를 해주어야 하고 , 클라이언트 단에서는 connect를 통해 서버에 요청하며, 연결이 수립 된 이후에는 Socket을 send함으로써 데이터를 주고 받게 됩니다. 연결이 끝난 후에는 반드시 Socket 을 close()해주어야 하며, Socket과 관련해서는 이후 네트워크 부분에서 자세히 다루도록 하겠습니다.
7) Semaphore
- Semaphore는 Named PIPE, PIPE, Message Queue와 같은 다른 IPC설비들이 대부분 프로세스간 메시지 전송을 목적으로 하는데 반해, Semaphore는 프로세스 간 데이터를 동기화 하고 보호하는데 그 목적을 두게 됩니다. 프로세스간 메시지 전송을 하거나, 혹은 Shared Memory를 통해서 특정 데이타를 공유하게 될 경우 발생하는 문제가 공유된 자원에 여러개의 프로세스가 동시에 접근하면 안되며, 단지 한번에 하나의 프로세스만 접근 가능하도록 만들어줘야 할 것이며, 이 때 사용되는 것이 Semaphore입니다. 자세한 부분은 이전에 포스팅했던 Semaphore와 Mutex 부분에서 다루고 있으므로 생략하도록 하겠습니다.
RAID에 대한 소개부터 시작하여 아래에서 RAID의 종류와 특징, 구성방식에 대하여 포스팅하겠습니다.
-RAID는왜? 사용되나
: 서버의 사용자가 서버 운영에 있어 가장 당혹스러울 때는하드디스크의 장애로 인한 data 손실일 것입니다. 하드디스크는 사실 상 소모품으로 분류되며 I/O 가 많은 서버에는 고장이 잦은 것이 당연하다고 볼 수 있습니다. 하지만서버에 저장되는 데이터의 경우 손실 또는 유출 되었을 때
치명적인 것이 대부분일 것으로 대표적으로 은행과 같은 금융, 군사적 목적의 데이터가 있을 것입니다. 이로
인해백업이 절대적으로 필요한 경우가 있고 또한, 여분의
디스크가 있어 용량을 증설하려고 할 때 데이터 손실 없이 증설이 필요한 경우가 있습니다. 그래서 많은 서버 관리자는RAID 구성을 통해 하드디스크의 가용성을 높이거나 서버 데이터의
안정성을 확보해야 합니다.
-RAID란?
: RAID는 Redundant Array of Inexpensive Disks의 약자입니다. 여러 개의 디스크를 배열하여 속도의 증대, 안정성의
증대, 효율성, 가용성의 증대를 하는데 쓰이는 기술입니다.
-RAID의장점
1) 운용 가용성, 데이터 안정성 증대
2) 디스크 용량 증설의 용이성
3) 디스크 I/O 성능 향상
-그 전에패리티(Parity)란무엇인가?
1) 정수의홀수또는짝수특성
2) 정보블록과연결된중복정보, 패리티는오류후데이터를재구축하는데사용되는계산된값입니다.
-RAID의종류와구성방식
RAID 0
: RAID 0에는Concatenate 방식과 Stripe 방식 두 가지 방식이 있습니다.
1) Concatenate방식
[concat 방식]
-> 두개 이상의 디스크에 데이터를 순차적으로 쓰는 방법
장점 :
디스크 기본 공간이 부족할 때데이터는 보존하며 여분의 디스크를 볼륨에 포함하여 용량 증설이 가능하게 됩니다.
단점 :
RAID 0의 특성상 디스크 중하나의 디스크라도 장애가 발생하면 복구가 어렵고,패리티(오류검출기능)를 지원하지 않습니다.
용량 : 모든 디스크의 용량을 합친 용량 ex)
300GB disk * 2ea = 600GB
2) Stripe 방식
흔히 RAID 0라고
하면 Stripe 방식을 말하는 것을 생각하면 됩니다.
-> 두개 이상의 디스크에 데이터를 랜덤하게 쓰는 방법
장점 : 데이터를
사용할 때 I/O를 디스크 수 만큼 분할하여 쓰기 때문에 I/O
속도가 향상되고I/OController나 I/O board 등 I/O를 담당하는 장치가 별도로 장착된 경우더 큰 I/O 속도 향상 효과를 볼 수 있습니다.
단점 : Stripe를
구성할 시기존 데이터는 모두 삭제되어야 합니다.
그 외의 단점은 위의
Concat 방식과 같습니다.
용량 : 위의 Concat 방식과 같습니다.
RAID 1(Mirror)
: Mirror 볼륨 내의패리티를
사용하지 않고디스크에 같은데이터를 중복
기록하여 데이터를 보존하게
되며,적어도동일한 용량의디스크 두 개가 필요합니다.
장점 : 볼륨
내 디스크 중하나의 디스크만 정상이어도 데이터는 보존되어 운영이 가능하기 때문에 가용성이
높고, 복원이 비교적 매우 간단합니다.
단점 : 용량이
절반으로 줄고,쓰기 속도가 조금 느려집니다.
용량 : 모든 디스크의절반의 용량 ex) 300GB *2ea = 300GB
RAID 2
: RAID2는 RAID 0처럼 striping 방식이지만 에러 체크와 수정을 할
수 있도록 Hamming code를
사용하고
있는 것이 특징입니다. 하드 디스크에서 ECC(Error
Correction Code)를 지원하지 않기 때문에
ECC를 별도의 드라이브에 저장하는
방식으로 처리됩니다.
하지만 ECC를 위한 드라이브가 손상될 경우는 문제가
발생할 수 있으며 패리티 정보를 하나의
하드 드라이브에 저장하는 RAID 4가 나오면서
거의 사용되지 않는 방식입니다.
RAID 3, RAID 4
: RAID 3, RAID 4는 RAID 0, RAID 1의 문제점을 보완하기 위한 방식으로 3, 4로 나뉘긴 하지만
RAID 구성 방식은 거의 같습니다. RAID 3, 4는 기본적으로 RAID 0과 같은 striping 구성을 하고 있어
성능을 보안하고 디스크 용량을 온전히 사용할 수 있게 해주는데 여기에 추가로 에러 체크 및 수정을
위해서 패리티 정보를 별도의 디스크에 따로 저장하게 됩니다.
RAID 3은 데이터를
바이트 단위로 나누어 디스크에 동등하게 분산 기록하며 RAID 4는 데이터를
블록 단위로 나눠 기록하므로 완벽하게 동일하진 않다는 차이가 있습니다.
RAID 3은 드라이브 동기화가 필수적이라 많이 사용되지 않고 RAID 4를 더 많이
쓴다고 보시면 됩니다.
RAID 5
: RAID 5는 RAID 3,4 에서 별도의 패리티 정보 디스크를 사용함으로써 발생하는 문제점을 보완하는
방식으로 패리티 정보를 stripe로 구성된
디스크 내에서 처리하게 만들었습니다.
만약 1개의 하드가 고장 나더라도 남은 하드들을 통해
데이터를 복구할 수 있다는 장점이 있습니다.
RAID 6
: RAID 6은 RAID 5와 같은 개념이지만 다른 드라이브들 간에 분포되어 있는 2차
패리티 정보를 넣어
2개의 하드에 문제가 생겨도 복구할 수
있게 설계되었으므로 RAID 5보다 더욱
데이터의 안전성을
이번에는 Little-endian과 Big-endian에 대한 설명과 차이점을 공부해보도록 하겠습니다.
먼저 Little endian은메모리시작주소가하위바이트부터기록된다는것입니다.
반대로 Big endian은메모리시작주소가상위바이트부터기록됩니다.
이게 무슨 말인지..? 아래 그림으로 참고해보도록 하겠습니다.
"메모리시작주소가 little(하위), Big(상위) 바이트부터기록된다"
Little endian –
인텔계열 프로세스에서 주로 사용되는 바이트 오더입니다.
Big endian –
Unix 시스템인 RISC 프로세서계열에서 사용되는 바이트 오더입니다.
[Big endian 과 Little endian, 메모리에 담기는 모습]
- Big endian은 그림을 참고하면 0x0A는 메모리 하위 주소에 위치하게 되고 차례로 0x0B, 0x0C, 0x0D가 오게 됩니다. 읽는 순서는 왼쪽 -> 오른쪽 순서로 읽으면 되기 때문에 사람이 보기에 가장 편한 방식이라고 할 수 있습니다.
-Little endian 은 Big endian과 반대로 0x0D가 메모리 하위 주소에 위치하게 되고, 상위 바이트로 올라가며 차례로 나머지 값들이 들어가게 됩니다. Little endian 또는 Big endian에 따라 받아들이는 쪽에서 처리를 잘못하면 엉뚱한 형태가 되므로, 항상 주의가 필요합니다.
위 그림으로 보면
Big endian은 메모리 a번지부터 ABCD로, Little endian은 메모리 a번지부터 DCBA로 위치된다고 보시면 됩니다.