Linux kernel v4.4에서 간단한 블록 장치 드라이버 만들어보기

08. per-cpu 변수와 통계 정보(v2.6.11)

중간에 제가 예전에 처음 발견하고 신기해했던 코드가 있어서 소개를 하겠습니다.

__inc_zone_page_state(page, NR_FILE_PAGES) 함수가 있었는데요 바로 페이지가 어떤 zone에 속하는지 찾고, 해당 zone에 페이지 사용량에 대한 통계를 갱신하는 함수입니다. 우리는 페이지캐시에 대한 통계만 봤었지만, 당연히 그 외에도 많은 통계정보들이 있겠지요. NR_FILE_PAGES가 정의된 include/linux/mmzone.h 파일을 보면 그 외에 다양한 통계 항목들이 있습니다.

제가 신기했던건 통계 자체가 아니라 통계 정보를 per-cpu 변수로 관리한다는 점이었습니다. 사실 통계 정보를 별 생각없이 atomic이나 spinlock으로 동기화를 하는데, CPU가 늘어날 수록 캐시 효율을 매우 떨어뜨려서 성능에 매우 안좋습니다. 그래서 어플단에서는 통계 정보를 lazy하게 갱신하는 등의 방법을 쓰는데, 커널단에서는 역시 per-cpu 변수로 각 cpu별로 저장해놨다가 사용자가 /proc/zoneinfo 파일을 출력할때만 각 cpu별 변수를 합해서 출력합니다. 그러면 평상시 페이지캐시 동작에는 오버헤드가 아주 적겠지요. 사용자가 /proc/zoneinfo를 파일을 출력해볼 일이 거의 없으니까요.

그래서 이번장에서는 per-cpu를 어떻게 구현하는지를 간단하게 알아보겠습니다. per-cpu 구현 자체를 알고나면 __inc_zone_page_state() 함수의 분석은 그리 어렵지 않겠지요.

(per-cpu의 구현은 단순히 C코드가 아니라 링커와 gcc 컴파일러의 기능을 써서 구현되므로 코드가 좀 복잡합니다. 특히 최신 커널 버전에서 per-cpu 변수의 동적 할당에 대한 코드가 많이 바껴서 v2.6와 v4.4의 코드가 완전히 다릅니다. 저도 잘 이해안되는 코드도 많고, 그 외의 코드들도 글로 설명하려니 너무 길어질것 같습니다. 그래서 간단히 v2.6 코드 기준으로 설명하는데, 실제 최신 버전에는 좀더 최적화가 되었다는걸 생각하시고 강좌를 보시기 바랍니다. 최신 버전의 구현은 다음 참고 자료를 확인하세요.)

참고

  • http://jake.dothome.co.kr/per-cpu/
  • http://www.makelinux.net/ldd3/chp-8-sect-5
  • http://studyfoss.egloos.com/5375570
  • http://studyfoss.egloos.com/5377666

댓글

댓글 본문
작성자
비밀번호
버전 관리
gurugio
현재 버전
선택 버전
graphittie 자세히 보기