REAL LINUX

2019.11.27 수요일 강남역에서 진행된 세미나

전세계 OS의 70퍼센트는 리눅스다.

개발자로써, 내가 만든 프로그램이 리눅스에서 돌아갈 확률이 높다.

트레이싱 : 디버그와 다르게, 프로그램의 동작을 가시적으로 확인 하는 것.

uftrace : User + Library + kernel 함수까지 다 보는 것들!


리눅스, 제대로 알고 코딩하자!

리눅스 커널도 C 프로그래밍이다

OS가 하는일?

  • 사용자 application 관리
  • HW 자원 관리 ( cpu, RAM, disk )

중요한것은 사용자 어플리케이션 관리이다! OS의 본 목적을 잊지 말자.

OS의 구성

  • Core 부분 : 프로세스 매니지먼트 PM, 메모리 매니지먼트 MM , IRQ, Locking
  • I/O 처리 : 네트워크, 스토리지 (VFS/FS/Block), 디바이스 드라이버
  • 기타 : 보안, 툴, 소리

core부분은 다른 파트가 사용할 수 있는 API라고도 볼 수 있다.

위의 파트들 중 가장 개발이 활발한 분야는? 드라이버다.

따라서 어떤 제품을 판매 할 때 디바이스 드라이버에 넣는게 중요할 텐데

디바이스 드라이버 메인테이너 같은 사람을 직접 구인하거나 기부를 하고 있다.

커널도 make명령어로 컴파일 할 수 있는데, c를 컴파일하면 a.out이라는 바이너리로 나오는 것 처럼,

커널 코드도 make로 컴파일하면 vmlinux라는 하나의 아웃풋으로 출력하게 된다.

ELF는 Section의 모음이다. 우리가 짠 코드는 .text에 들어 있다.

마찬가지로 우리가 만든 vmlinux 또한 Section의 모음이며, 마찬가지로 .text에 코드가 들어있다.

따라서 커널또한 우리가 만든 C와 다를 바 없는 프로그램이다.


페이지폴트는 왜 발생할까?

컴퓨터, SW 동작 과정

CPU → 뇌

Memory → 공책

Disk → 책

우리가 디스크에서 프로그램을 실행하면 메모리에 적재됨! → 공책에 문제를 적음

CPU는 문제를 풀 때 풀이를 적을 수 있음 → 풀이를 적음

이때 문제는 text코드이며, 풀이는 stack, heap이라고 볼 수 있음.

그럼 페이지 폴트는 왜 발생할까?

물리 페이지 프레임이 없어서 : 이거는 부적절한 답변! 미분 거꾸로한게 적분이야! 같은 거임

페이지 폴트는?

메모리를 관리하는 하나의 메커니즘 때문에 생기는 문제. 진짜 메모리 조각을 지 않고 가상 메모리 조각만 주는 경우에 발생한다.

메모리를 사용 할 수 있는 애들이 있음 (프로그램들 : 크롬, 슬랙, 빔 … ) 얘네들은 메모리를 페이지라는 단위로 받아오는데, OS는 메모리를 실제로 주는게 아니라

가짜 종이를 나눠줌! 그게 페이지이다.

이때 보통 한 페이지가 4K이므로, 참고할 수 있는 주소가 4096개가 있는거임.

  • 바이너리 인터페이스 깨짐 현상

    가상 어드레스를 왜 사용할까? int a = 1; 이라고 하는 코드는 컴파일러에 의해서 mov 1 ( 주소 ) 이런 명령어로 바뀌게 되는데 이걸 피지컬 메모리로 사용하게 되면 내 컴퓨터에서 밖에 사용 할 수 있는 바이너리 인터페이스 깨짐 현상이 발생하게 된다.

왜 이렇게 사용할까?

  • 실제로 필요할 때 요구하므로 메모리 절약할 수있다.
  • 가상 메모리 레이어가 존재하므로 허가받지 못한 주소를 참조를 막을 수 있따.
  • 바이너리 인터페이스 깨짐 현상 해결 ( 하드코딩 하지 않아도 된다. )

페이지 폴트의 종류는 2가지임. 인스트럭션을 가져오다가 폴트가 나거나, 아니면 힙이나 스택에 접근하다가 폴트가 나거나.

왜냐하면 리눅스에서는 프로그램 코드, 힙, 스택모두 가상 메모리에 올리기 때문임!!

ps -eo rsss,vsz,comm | head -2

명령어를 치면, 결과를 볼 수 있지만, 가상 메모리가 엄청엄청 커져도, 실제로 할당받는 애는 거의 없다.

성능적인 측면에서 늘리는 방법!

  1. 애초에 1이나 0을 마구 넣어서 피지컬 메모리를 잡아버린다.
  2. 폴트가 나서 느려지는것이니 폴트를 미리 내버린다!

페이지 관리 테이블은 프로그램마다 나눠져있다.

왜 하나가 아니라 여러개일까? 그것은 컴파일러가 컴파일 할 때 다른 프로그램과 무관하게 동작하게 하려고!

하기 때문이다. 그럼 프로그램이 여러개가 되면 페이지 테이블 개수도 같이 늘어나니까 엄청 무거워지지 않을까?

  • 4레벨 페이지 테이블

    페이지 테이블이 단순히 가상메모리와 피지컬 메모리의 1:1 매칭 이라면,

    무려 공간이 4G = 4 * 1024 * 1024 개나 필요하므로, 여러가지 레벨로 나누어서

    저장해 공간의 효율을 높인다.


리눅스 커널과 나의 서버 프로그램의 관계 및 성능에 미치는 영향?

System call interface
VFS (virtual file system) Layer
Indivisual File System Layer
Block Layer

문제 상황 : 커널 버전 업그레이드 이후 Disk I/O가 많아짐!

어디서 부터 봐야할까? → 트레이싱 기술이 중요하다.

커널에서 트레이싱 함수를 만들어서 어느 구간이 문제인지,

어느 구간에서 시간이 많이 걸렸는지를 체크할 수 있다.

트레이싱 기술의 중요성 강조!

연이어지는 call-graph 상에서 latency가 아니라

그냥 call count가 많아서 생기는 latency?

(latency : 자극과 반응사이의 시간 : 지연시간 )

read ahead 사이즈의 이해와 성능 영향?


컨테이너가 죽은 이유

  • 컨테이너란?
    1. chroot : 우리만의 공간 , namespace : 나만의 공간

    2. cgroup : 나만의 자원, 우리만의 자원.

namespace를 눈에다 먹이면 나 혼자 리눅스를 쓰고 있다고 생각하는것과 비슷하나,

알고보면 다른 애들도 존재하는것이다.

활용 방법 ( Docker 컨테이너라고 보면 됨! )

cgroup은 메모리를 제한 해야하는 환경에서 직접 물리적 메모리를 바꾸지 않고도 제한할 수 있게해줌

namespace를 이용하면 아무것도 없는 빈 공간에서 나만의 프로세스를 돌릴 수 있음.

→ 나만의 독립된 리눅스 공간!

→ 어플리케이션 하나가 컨테이너 하나가될 수 있지만 하나의 컨테이너에 여러 어플레이케이션이 들어갈 수 있음!

다른 컨테이너가 죽은 이유

컨테이너를 사용 할 경우, 나는 나만 쓰는 리눅스라고 생각하고 있는데 옆 컨테이너의 영향에 의해

내가 죽을 수 있다! → 어처구니 없는 이유

실습 1! chroot를 통해 나만의 리눅스 만들기

sudo chroot rootfs /bin/bash

이럴경우 새로운 루트로 바뀌게 됨!

하지만 이때, ps 명령어를 입력하게 되면 프로세스를 기준으로 보면 프로세는 공유됨.

따라서 이것도 개인으로 바꿔주게 된다. (이런게 겹겹히 쌓여서 컨테이너가 된다.)

명령어 ~~

실습 2! cgroup을 통해서 메모리 제한하기

실습1 을 한 상태에서,

mkdir /sys/fs/cgroup/memory/test
echo 100000000 (100Mb) > /sys/fs/cgroup/test/memory.limit_in_bytes
echo 0 > /sys/fs/cgroup/memory/test/memory.swappiness ( 디스크에서 빌려오는거 금지 )

이때 메모리를 자꾸 먹는 py를 실행하면 죽는 모습을 볼 수 있다.

커널 기능을 통해 어떻게 죽는지도 볼 수 있다.


결론

리눅스는 더이상 어두운 Hidden Box가 아니다! 트레이싱과 함께라면 당신도 리눅스 삽고수

좋은 시간이었다!