반응형

함수를 활용해서 쉘스크립트안에서 멀티 스레드와 백그라운드를 구현하는 방법에 대해 알아보도록 하겠습니다. 사실 제가 쉘 스크립트를 사용하면서 다른 언어와 비교했을 때 가장 편하다고 생각했던 부분입니다.

 

리눅스에서는 command 뒤에 '&'를 붙이게 되면 백그라운드로 동작하게 되고 리눅스의 예약어 $!로 해당 PID 값을 갖고 있게 되면 그 프로세스를 제어할 수 있습니다. 일단 샘플 코드와 수행 결과 값을 확인해 보겠습니다.

 

 #!/bin/bash

THREAD()
{
        while [ 1 ]
        do
                echo "THREAD 1 : $1"
                sleep 1
        done
}

 

echo "CALL 1st thread - Background Operating"
THREAD first&
THREAD_1st_PID=$!


echo "THREAD PID : $THREAD_1st_PID"
sleep 5
echo "Wait 5sec -> 1st thread suspend 5sec  "
echo "CALL 2nd thread - Background Operating"
kill -19 $THREAD_1st_PID
THREAD second&
THREAD_2nd_PID=$!

sleep 5


echo "Wait 5sec -> 1st thread continue 5sec  "
kill -18 $THREAD_1st_PID
sleep 5
kill -9 $THREAD_1st_PID $THREAD_2nd_PID

 root@ubuntu:/shell# ./multi.sh
CALL 1st thread - Background Operating
THREAD PID : 13595
THREAD 1 : first
THREAD 1 : first
THREAD 1 : first
THREAD 1 : first
THREAD 1 : first
Wait 5sec -> 1st thread suspend 5sec
CALL 2nd thread - Background Operating
THREAD 1 : second
THREAD 1 : second
THREAD 1 : second
THREAD 1 : second
THREAD 1 : second
Wait 5sec -> 1st thread continue 5sec
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second
THREAD 1 : first
THREAD 1 : second

 

파란색으로 및줄친 부분이 백그라운드 및 멀티스레드의 핵심적인 요소 입니다. 해당 구문에 백그라운드로 돌리고 해당 프로세스의 PID값을 저장하고 순차적으로 하나의 스레드를 추가로 생성하고 마지막에는 스레드를 종료하고 마치게 되는 구조 입니다.

반응형
반응형

쉘 스크립트를 작성하다 보면 함수를 사용해서 반복적인 일들을 수행 하면 좋을 경우가 있습니다. 다른 프로그램 언어와 마찬가지로 쉘 스크립트 역시 함수를 지원하고 이를 통해 수많은 기능 구현이 가능합니다.

 

그럼 선언하는 방법을 비롯해 가장 기초적인 상황에 대해서 알아보도록 하겠습니다.

 

 #!/bin/bash

 #함수선언 및 정의

 func ()

 {

   수행문

 }

 

 func

 

문법 형식은 다음과 같습니다.

 

C언어를 기준으로 비교할 때 큰 부분은 비슷하지만 몇가지 차이점이 있습니다. 먼저, 쉘 스크립트에서는 함수를 따로 선언하고 사용할 수가 없고 선언과 동시에 정의를 해야 하고 스크립트의 상단에 먼저 배치해서 사용해야 됩니다. 이 부분의 인터프리터 언어에서 나오게 되는 한계점이라고 생각하시면 될거 같습니다.

 

그리고 함수를 선언할 때 타입을 지정해야 할 필요가 없으며 사용할 때는 함수의 이름으로 만 사용이 가능합니다. 그럼 간단한 샘플 코드를 통해 마무리를 하도록 하겠습니다.

 

 #!/bin/bash

func()
{
        echo func $1 $2 $3
}

echo "CALL func()"
func "hello" "World" "WoW"

root@ubuntu:/shell# ./func.sh
CALL func()
func hello World WoW

 

샘플 코드에는 Argument 값도 추가로 넣어서 해보았습니다. 이렇게 Argument를 이용할 경우에는 다양한 인풋값을 함수로 보내서 보다 기능을 다양하게 사용할 수 있습니다.

 

 

#!/bin/bash

func()
{
        echo func $1 $2 $3
        return 100
}

echo "CALL func()"
func "hello" "World" "WoW"
echo "func return value : $?"

root@ubuntu:/shell# ./func.sh
CALL func()
func hello World WoW
func return value : 100

 

마지막으로 함수 리턴값을 활용하는 방법을 알아보겠습니다.

다른 여타 프로그램과 마찬가지로 return 으로 넘길 수 있으며 바로 뒤에 $? 예약어로 결과를 받을 수 있습니다. 여기서 중요한 점은 함수 바로 뒤에서 $?을 활용해야되며 이후 다른 명령어를 활용하게 되면 해당 명령어의 return 값을 들고 온다는 점 유의 바랍니다.

반응형
반응형

서버 시스템을 구축하다보면 가장 어려운 점이 아마도 HBA와 RAID 카드이지 않을까 싶습니다.

 

많은 사람들이 어렵지 않게 컴퓨터를 사용하는 이 시대에 어쩌면 가장 생소할 수 있는 부분이 HBA와 RAID 카드이지 않을까 싶습니다

 

디테일하게 이야기하려고 하면 컴퓨터 구조 등 설명해야 할 부분이 많지만 각설하고 간략하고 쉽게 설명하지면....

 

서버에서 다양한 스토리지 (HDD, SSD ...)등을 관리해 줄 수 있는 모듈이라고 생각할 수 있습니다.

 

그럼 여기서 드는 의문이 ?? 그럼 왜 ??? PC에는 HBA나 RAID 카드가 없나요 입니다. 물론... PC에도 사용할 수 있습니다. 다만 사용하지 않는 이유를 몇가지 들어보자면

 

먼저 HBA와 RAID 카드는 상당히 고가의 부품입니다. 그렇기 때문에 굳이 PC에 사용할 필요가 없다고 볼 수 있는 것이며

 

다음은 기본적으로 CPU에도 HBA의 기능을 지원해 줍니다. 그렇지만 지원하는 Storage의 대수가 한정되어 있습니다.

 

반면 서버에서는 많은 수의 스토리지가 장착되기 때문에 추가적인 PCI 카드가 필요하게 되었습니다. 물론 저가형 서버에는 HBA나 RAID카드없이 CPU에 바로 다이렉트로 연결되서 나오는 경우도 있지만 그럴 경우에는 CPU도 느려지고 I/O 성능도 느려지는 처참한 경우가 나오게 되겠죠

 

마지막으로는 HBA와 RAID 카드의 고유한 기능들입니다. 이부분은 다음번 연재때 알아보도록 하고 ...

 

다음번에 RAID와 HBA에 대해서 자세히 한번 알아보도록 하겠습니다.

 

반응형

'인프라 구축 기술' 카테고리의 다른 글

VIP (Virtual IP)란 ??  (0) 2017.12.06
RAID 와 HBA 카드 (2)  (0) 2017.11.13
메모리의 종류 (UDIMM, RDIMM, RLDIMM, NVDIMM)  (0) 2017.10.23
Xeon(제온) CPU는 ??  (0) 2017.10.21
서버 시스템 이해하기  (0) 2017.10.09
반응형

쉘 스크립트를 작성할 때 다양한 환경변수(예약어)를 사용하게 되면 보다 스크립트를 깔끔하게 사용할 수 있어서 전부는 아니더라도 제가 많이 사용한 것을 위주로 한번 정리하도록하겠습니다.

 

$0~n : 일반적으로 사용할 때는 입력받은 파라미터를 의미하고 함수에 사용할 경우 함수의 파라미터를 의미

($0 은 현재 쉘스크립트 이름이거나 함수의 이름)

 

$$ : 쉘의 PID

 

$# : 파라미터의 개수

 

$@ : 파라미터 목록

 

$* : 명령어의 모든 인수 목록

 

$? : 바로 직전에 수행한 결과의 리턴값

 

$! : 백그라운드 프로세스 PID -> 이부분은 추후 추가 설명

 

$PWD : 현재 디렉토리의 절대경로명

 

$USER : 현재 사용자 이름

 

$UID : 현재 사용자의 UID

 

$PATH : 명령어 검색 경로

 

$SHELL : 로그인 쉘의 절대 경로

 

$TERM : 터미널 종류의 이름

 

$RANDOM : (bash, csh) 1~65535까지의 랜덤의 정수

 

 

이밖에도 여러가지만 있지만... 여기까지 정리하도록 하겠습니다

 

반응형
반응형

리눅스 스케줄링 알고리즘

 

스케줄러 클래스

 

1. 리눅스 스케줄러는 모듈화돼어 있으며 여러유형의 프로세스를 각기 다른 알고리즘을 통해 스캐줄링이 가능하며 모듈화된 형태를 스케줄러 클래스라고 한다.

 

2. 스케줄러 클래스를 이용해 교체 가능한 여러 알고리즘을 동시에 사용하면서 클래스별로 독자적인 방식으로 프로세스를 스케줄링이 가능

 

3. kernel/sched.c 에 정의된 기본 스케줄러 코드는 각 스케줄러 클래스를 우선순위에 따라 차례대로 실행

 

4. 실행가능한 프로세스가 있는 가장 우선순위가 높은 스케줄러가 다음에 실행할 프로세스를 선택

 

5. 완전 공정 스케줄러(CFS)는  SCHED_NORMAL로 정의된 리눅스의 일반 프로세스용 스케줄러 클래스

 

 

유닉스 시스템의 프로세스 스케줄링

 

증요한 2가지의 개념 : 프로세스 우선순위와 타임슬라이스

 

타임 슬라이스는 프로세스가 얼마나 오랫동안 실행되는가이고 높은 우선순위 프로세스는 더 자주 실행되고 더 긴 타임슬라이스 값을 할당 받는다.

→ 이 시스템의 방법론적인 문제발생

 

1. 작업전환의 최적화 문제 발생

2. 우선순위(나이스 값)가 타임슬라이스와 묶이는 것과 나이스 값의 상대적인 차이 발생

3. 나이스값에 따라 타임슬라이스를 할당 하려면 타임슬라이스의 절대값을 할댕해야 됨

4. 우선순위 기반 스케줄러가 대화형작업을 최적화 하고자 할 경우 프로세스 깨우기 처리와 관련된 문제 발생

 

 

공정 스케줄링 (CFS)

 

CFS는 이상적이고 완벽한 프로세서를 가지고 있는 시스템의 프로세스 스케줄링을 추구

 

1. CFS는 각 프로세스를 순차적으로 일정시간동안 실행하고 가장 실행이 될 된 프로세스를 다음에 실행할 프로세스를 선택

2. 실행가능한 전체 프로세스 개수와 관련된 함수를 이용해 프로세스를 얼마동안 실행해야 하는지 계산

3. 프로세스에 할당할 프로세서 시간 비율의 가중치로 나이스값을 활용

4. CFS는 실제 타임슬라이스 값을 계산하기 위해 완전 멀티태스킹의 '무한히 작은' 스케줄링 단위를 근사 할 수 있는 목표치를 정해 놓고 이를 목표 응답시간이라고 한다.

 

 

리눅스 스케줄링 구현

 

CFS의 4가즈 구성요소

- 시간 기록

- 프로세스 선택

- 스케줄러 진입 위치

- 휴면 및 깨어남

 

시간 기록

 

1 모든 프로세스 스케줄러는 각 프로세스의 실행 기록을 기록

2 대부분 유닉스 시스템은 프로세스에 타임슬라이스를 할당하면서 기록

3. 시트메 클럭 한틱이 지날때마다 그틱에 해당하는 시간만큼 타임슬라이스가 줄어든다

 

스케줄러 단위 단위 구조체

 

1 CFS에는 타임슬라이스 개념이 없지만 공정하게 할당된 몫만큼을 사용하기 때문에 프로세스의 실행시간을 기록해 두어야 한다.

2 <linux/sched.h>에 정의된 struct sched_entity라는 스케줄러 단위 구조체를 사용해서 정보를 저장

 

가상실행 시간

 

1. vruntime 변수에는 프로세스의 가상 실행시간이 저정되며 가상 실행시간은 실행 가능한 프로세스 개수에 따라 정규화한 실제 실행시간을 의미한다.

2. 가상실행시간을 이용해 CFS가 지행하는 '이상적인 멀티태스킹 프로세서'를 근사적으로 구현 가능

이상적인 프로세서에서는 우선순위가 같은 프로세스의 가상 실행시간은 3. 모두 같으며 CFS는 vruntime을 통해 프로세서가 얼마나 오랫동안 실행 됬는지 앞으로 얼마나 더 실행되어야 하는지를 기록

4. 이작업은 kernel/sched_fair.c에 정의된 update_curr()에서 수행

 

프로세스 선택

 

1. 다음 실행할 프로세스를 선택할 때 CFS는 vruntime이 가장 작은 프로세스를 선택

2. CFS는 이를 효율적으로 하기 위해 레드블랙트리를 사용한다 (rbtree)

3. 레드블랙트리는 어떤 데이터를 노드에 저장하는 자료구조로, 특정키로 각 노드를 식별할 수 있으며, 키값이 주어졌을 때 그 키값을 가진 데이터를 효율적으로 탐색할 수 있는 자료구조

 

다음 작업 선택

 

1. 시스템의 실행가능한 모든 프로세스에 대해 각 프로세스별로 가상 실행시간을 키값으로 하는 노드를 만들어 레드블랙를 구성했을 때,

2. 주어진 트리에서 vruntime값이 가장 작은 CFS가 다음에 실행하고자 하는 프로세스는 트리의 가장 왼쪽에 있는 노드에 해당하는 프로세스

3. 트리의 루트노드에서부터 말단 노드에 이를 때 까지 계속 왼쪽 노드를 다라 가면 vruntime 값이 가장 작은 프로세스를 찾을 수 있다.

4. 따라서, CFS의 프로세스 선택 알고리즘은 "레드블랙트리의 가장 왼쪽노드에 해당하는 프로세스를 실행한다"로 요약

( kernel/sched_fair.c __pick_next_entity() 가 수행)

 

스케줄러 진입 위치

 

1. 프로세스 스케줄링 작업을 시작하는 곳은 kernel/sched.c 파일의 schedule()함수에 정의

2. 커널의 다른 부분에서 이 함수를 통해 프로세스 스케줄러를 호출함으로서 다음에 실행할 프로세스를 선택하고 실행

3. schedule()함수는 더 일반적인 형태의 스케줄러 클래스이고 이 함수는 가장 우선순위가 높은 실행 가능한 프로세스를 가진 스케줄러 클래스를 찾고 다음에 실행할 프로세스를 해당 스케줄러에게 물어본다.

4. kernel/sched.c 파일의 pick_next_task()함수는 가장 높은 우선순위의 스케줄러 클래스부터 돌아가면서 우선순위가 가장 높은 클래스의 우선순위가 가장 높은 프로세스를 찾아낸다.

반응형
반응형

멀티태스킹 :

하나 이상의 프로세스를 동시에 중첩형태로 실행할수 있는 운영체제

 

멀티태스킹 운영체제:

협동형 멀티태스킹 (Cooperative Multitasking) & 선접형 멀티태스킹프로세스 (Preemptive Multitasking)

 

선점형 멀티태스킹 :

 

- 프로세스 실행을 언제 중단하고 다른 프로세스를 실행할지리를 스케줄러가 결정

- 실행중인 프로세스를 강제로 중지시키는 작업을 선점이라고 정의

- 프로세스가 선점되기 전까지 주어지는 시간은 보통 미리 정해져 있으며 이것을 Timeslice(타임슬라이스)라고 함

타임슬라이스 : 프로세스가 선점되기 전까지 프로세스에 주어지는 시간

- 스케줄러는 타임슬라이스를 관리하는 방식으로 전체적인 시스템 스케줄링을 결정

 

협동형 멀티태스킹 :

- 프로세스가 자발적으로 실행을 중단하지 않는 한 프로세스를 중지 불가

- 프로세스가 자주 양보함으로써 실행 중인 프로세스가 충분한 프로세서가 충분한 동작 시간을 확보할 있다

 

 

정책 : 스케줄러가 무엇을 언제 실행 할  것인지를 정하는 동작

- 스케줄러의 정책을 통해 프로세서 시간의 사용을 최적화하는 책임

 

입출력중심 / 프로세서중심 프로세스

 

입출력중신 프로세스 : 입출력 요청을 기다리는데 대부분의 시간을 사용하는 프로세스

-> 입출력을 기다리는 작업을 반복하게 되므로 실제 실행시간을 짧다

ex) GUI 어플리케이션, Word Application

 

프로세서 중심 프로세스 : 대부분의 시간을 코드를 실행하는 데 사용

-> 선점될때 까지 계속 실행 / 긴시간동안 덜 자주실행되는것이 중요

ex) ssh-keygen , MATLAB

 

 

프로세스 우선순위

1. 스케줄링 알고리즘의 일반적인 형태는 우선순위 기반의 스케줄링이다

2. 목표는 가치와 필요에 따라 프로세스의 순위를 매겨 프로세서 시간을 할당해야 한다.

 

리눅스 커널의 두가지 우선순위 단위

1. 나이스값 (-20 ~ +19, 기본값 : 0) : 클 수록 우선순위가 낮다.

2. 실시간 우선순위 (0 ~ 09) : 클수록 우선순위가 높다

-> 실시간 우선순위값은 나이스값과 별도의 값이다

 

타임슬라이스 : 선점되기 전까지 작업을 얼마나 더 실행할 수 있는지 나타내는 값이다

1. 너무 길게 잡으면 시스템의 대화형 성능이 떨어지고 실제 App이 시스템에서 실행되고 있다는 것을 느끼기 어렵다

2. 너무 짧게 잡으면 타임슬라이를 소진한 프로세스를 다음 프로세스로 전환하는데 빈번하게 시스템 시간을 사용하게 되므로 프로세스 전환에 프로세스 시간을 소비한다.

 

※ 리눅스의 CFS스케줄러는 타임슬라이스 값을 할당하지 않고 대신 프로세스별 프로세서 할당 비율을 지정하는 방법을 사용한다

→ 리눅스에서 프로세스에 할당되는 프로세스 시간은 시스템의 부하에 따른 함수로 결정되고 이는 나이스값의 영향을 받는다 

반응형

+ Recent posts