메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

리눅스 커널 락을 없애려는 시도들

한빛미디어

|

2007-09-13

|

by HANBIT

16,796

제공 : 한빛 네트워크
저자 : 한동훈

Linux Scalability Effort
http://sourceforge.net/project/showfiles.php?group_id=8875
: 락은 동기화를 위해 필요하지만 수행 성능에 큰 저하를 가져온다.

적절히 무시할 수 있는 센스
http://minjang.egloos.com/1094167
: 위의 블로그에도 써 있는 것처럼 무시할 수 있다면 무시하는 것이 더 좋다.

위 소스포지 사이트는 리눅스 커널의 수행성능을 끌어올리기 위해 커널에서 사용되는 다양한 잠금(lock)을 제거하는 패치로 이뤄져 있다. 커널 2.2와 2.4를 대상으로 하고 있는 커널 패치이다. 위 프로젝트는 현재 중단되었으며, 프로젝트의 내용들은 대부분 커널 2.6에 포함되었다. 어떤 식으로 커널의 잠금을 제거하거나 성능 향상을 이뤄냈는지 살펴보기엔 귀중한 소스이다. 중단된 프로젝트라해도 오픈된 채로 남겨두면 누군가에겐 도움이 된다. 특히, 커널을 공부하는 입장에서는...(실제로, 소스포지에는 RTLinux 패치도 여전히 남아있다. 리얼타임 패치의 대부분은 커널에 사용된 잠금 구조를 제거하는 것으로 이뤄져있다. RTLinux 패치의 일부분이었던 O(1) 스케줄러는 현재 커널 2.6에 포함되어 있다)

커널의 잠금을 제거하고, 수행성능을 최적화하기 위한 시도는 커널 2.4에서 2.6으로 넘어가는 동안에도 이뤄졌다.

커널 2.4에서는 빅 커널 락(Big Kernel Lock, BKL)이 있다. 커널 2.4는 CPU가 커널 영역에서 실행하기 위해 BKL을 획득하는 구조였다. 즉, CPU0이 BKL을 획득하고 커널 영역에서 실행중이라면 다른 CPU들은 커널 영역에 진입할 수 없었다. CPU0가 커널 영역에서 실행되는 동안에는 CPU1은 사용자 프로세스를 실행하던가, 사용자 프로세스도 다 실행해버려서 다른 프로세스로 전환하기 커널 영역에 진입해야 한다면 CPU0이 커널 영역에서 볼일 다 볼 때까지 손가락 빨고 있어야하는 구조인 것이다. 물론, 커널 영역에서의 실행은 대부분 매우 짧지만 커널 영역 선점을 위해 CPU들이 경쟁하는 경우엔 비효율적인 구조였다. 장점은 잠금 메커니즘이 매우 단순하게 구현되기 때문에 커널 개발자 입장에서 매우 편하다는 것이다. 하지만, CPU 개수가 늘어나면 늘어날수록 커널 영역 진입을 위한 경쟁은 심화될 수 밖에 없었다. 따라서, 커널 2.6부터는 CPU0이 커널 영역에서 실행되고 있더라도 CPU1이 CPU0의 커널영역 제어권을 뺏어올 수 있게 되었다. 이를 커널 선점(Kernel Preemption)이라 부른다.

커널 2.6에서는 BKL의 상당부분을 제거하고, 세마포어(semaphore, 원어로는 세머퍼라 읽는다), 스핀락(spinlock)을 이용하는 구조로 전환하였다. 이는 BKL에 비하면 커널 선점을 허용하면서 잠금을 관리하는 데 들어가는 비용이 낮다. 커널 2.6은 BKL을 완전히 제거하지는 못했다. 그저, 상당부분을 제거했을 뿐이다.

[참고]
커널 선점을 허용하기 위한 잠금 메커니즘은 매우 복잡하며, 이로 인해 시스템에 있는 버그를 발견하는 것이 더 어렵게 되었다며, 커널 선점을 사용하지 않게 커널을 설정할 것을 권하며 논쟁이 되었던 적도 있다.

Linux: Debating The Merits Of Kernel Preemption
http://kerneltrap.org/node/3966

또한, 잠금을 아예 하지 않으면서 동기화를 이루기 위한 구조로 RCU(Read-Copy-Update) 구조를 도입했다.

CPU0이 A라는 데이터를 접근하고 있고, CPU1이 A를 접근해서 데이터를 수정해버리면 RCU에서는 A"을 생성한다. 이때는 시스템에 A와 A"이 동시에 존재하게 된다. 이때 CPU2가 A를 접근하게 되면 RCU에 등록된 연결리스트를 타고 A"에 접근하게 된다. 시간이 경과해서 CPU0이 A라는 데이터를 더 이상 접근하지 않게 되면 RCU에서는 A를 완전히 제거하게 된다.

A라는 구조체에는 참조 카운팅을 관리하는 멤버도 갖지 않는다. 이 말은 내가 A 구조체의 참조 카운팅을 관리하기 위한 루틴을 작성하지 않아도 되는 것을 의미하고, A 구조체의 잠금을 관리하기 위한 루틴을 작성하지 않아도 되는 것을 의미한다. A라는 자료의 동기화는 오직 RCU에 의존해서 수행된다.

A와 A"이 동시에 존재하는 상황에서 A를 제거하는 시점은 시스템 내의 모든 CPU들이 프로세스 전환이 발생하거나 대기(idle) 상태가 되는 경우가 일정 횟수 이상 발생하면 A를 참조하지 않는다는 것을 알 수 있다. 물론, 이때도 A"은 여전히 참조하고 있는 것이다. 이렇게 되면 시스템은 모두 업데이트된 A"을 참조하게 되고, 데이터 무결성을 보장할 수 있게 된다.

말은 쉽지만 복잡하다. 구현이 시작되고, 커널의 메인라인에 포함되기까지 거의 2년이 걸린 것으로 알고 있다. (거의 2년으로 알고 있음. 그만큼 구현하기 어렵고, 테스트하기 어렵다는 의미가 아닐까. 지금은 만들어져서 널리 쓰이고 있으므로 커널 개발자들은 RCU 관련 API들을 가져다 쓰기만 하면 된다)

[참고]
RCU는 여러번 수정하는 것도 허용한다. 이때는 A가 A", A"이 A"", A""이 A"""으로 변경되는 구조이며, 앞에서 얘기한 특정한 조건이 만족되면 리스트를 따라 A, A", A""을 시스템에서 제거하고, 모든 수정이 반영된 A"""만 남게 된다.

RCU는 현재 커널 전반에서 널리 쓰이고 있으며, RCU로 대체할 수 있다면 RCU로 모두 대체하고 있는 중이다. RCU가 쓰이는 곳으로는 IP 라우팅, 가상 파일 시스템에서의 덴트리 등이다.

그러나, 사람들은 여전히 이것에 만족하지 않으며, 보다 많은 커널 잠금을 제거해서 최대한의 성능을 내려고 하고 있다.

많은 사람들이 최적의 성능을 위해 끊임없이 머리를 짜내서 만들어 놓고도 지칠 줄 모르는지 그 위에 더 나은 성능을 내기 위해 노력하고 있다.

커널 2.4 -> 2.6의 큰 변화에 대해서는 다음의 발표자료가 참고가 된다.(2004. 1월 자료)

Linux 2.6 Performance in the Corporate Data Center
ftp://www6.software.ibm.com/software/developer/library/os-ltc-kernel/2.6-datacenter.pdf

커널에서 동기화를 위한 프로그래밍은 상당히 어려웠고, 커널 개발자들은 동기화 메커니즘을 테스트하기 위한 다양한 코드를 만들어왔다. 그리고, 이러한 코드들을 모아서 Kernel Lock Validator라 이름 붙였고, 커널 2.6.17 이후부터 포함되었다

관심있는 분들이라면 아래 사이트의 내용을 참고하면 좋을 것이다.

The kernel lock validator
http://lwn.net/Articles/185666/

KLV를 들여다보면 락 메커니즘을 테스트하기 위한 코드를 어떻게 작성해야 하는지 이해할 수 있지 않을까.
TAG :
댓글 입력
자료실