검색 엔진의 방문이 늘어나고 있군...

Posted
Filed under 시스템
참조 원문: What is the relationship between Unity, Gnome, Gnome 3, Compiz, Metacity, and LightDM?

리눅스 GUI의 이해에 대해 좋은 글이 있어서 가져왔습니다. GUI와 관련된 리눅스 용어 중에는 아래와 같은 것들이 있습니다.
  • Display Manager
  • Window Manager
  • Desktop Environments

Display Manager
  LightDM, GDM, KDM, LXDM 같은 것들이 여기 속합니다. 보통 이름에 display manager를 의미하는 게 어딘가 있습니다. 이것들은 부팅 시 X server를 시작하며 로그인 화면을 제공합니다. 또한 로그인 중 window manager나/와 desktop environment를 선택할 수 있게 해주는 경우도 많습니다.

Window Manager
  Compiz, Metacity, Mutter, W9dk, fluxbox 같은 것들이 여기 속합니다. 이들은 응용프로그램의 경계선(application border), 윈도우의 위치, 테마, 꾸미기를 담당합니다.

Desktop Environments
  사용자를 위해 완전한 상태계를 제공하는 응용프로그램, 패키지, 서비스 등의 종합 세트를 뜻합니다. Window Manager나 Display Manager와 달리 Desktop Environments는 로그인 화면부터 메일 프로그램, 네트워크 관리자, 텍스트 에디터, 시스템 세팅, 이미지 뷰어, 파일 관리자 등 모든 것을 포함합니다. Desktop Environments 중 아래 4가지가 유명합니다.

  • GNOME
  • KDE
  • LXDE
  • XFCE
2016/04/06 16:51 2016/04/06 16:51
Posted
Filed under 시스템
관련 링크: Mesa (computer graphics)
관련 링크: Direct Rendering Infrastructure
관련 링크: Gallium3D

  리눅스 게이밍이 떠오르는 요즘, 많이 보이는 관련 용어들에 대해 간단히 알아봤습니다.

리눅스 그래픽 스택

Mesa: OpenGL 구현하기 위한 프리&오픈 소스 라이브러리와 하드웨어 가속 3D 렌더링, 3D 컴퓨터 그래픽, GPGPU와 관련된 API의 모음집. API + DRI(Direct Rendering Infrastructure) + Gallium3D로 구성.

DRI(좌) vs Gallium3D(우)

DRI(Direct Rendering Infrastructure): X 윈도우 시스템에서 사용자 프로그램의 데이터가 디스플레이어 서버를 거치지 않고 비디오 하드웨어에 직접 접근하는 것을 안전하게 허용하기 위해 사용하는 인터페이스 및 자유 소프트웨어 기능.

DRM(Direct Rendering Manager): 비디오 하드웨어를 지원하기 위한 DRI 아키텍쳐를 구현하는 하드웨어에 의존적인 커널 모듈.

Gallium3D: 그래픽 디바이스 드라이버를 3개의 파트로 나눔으로서 3D 그래픽 칩셋을 위한 디바이스 드라이버 프로그래밍을 쉽게 만든 프레임워크.

fglrx: AMD GPU용 독점 드라이버 이름. 정확한 이름은 libGL-fglrx-glx. 참고로 NVIDIA GPU용 독점 드라이버 이름은 그냥 libGL-nvidia-glx.

nouveau: NVIDIA GPU용 오픈 소스 드라이버(정확히는 DRM) 이름. 정확한 이름은 libDRM-nouveau. 참고로 AMD GPU용 오픈 소스 드라이버 이름은 libDRM-radeon이고, Intel 내장 그래픽 칩셋용 오픈 소스 드라이버 이름은 libDRM-intel.


  AMD는 자사의 GPU를 위한 드라이버의 소스를 오픈 소스로 공개했습니다. 다만 독점 드라이버도 계속 내놓고 있는 걸 봐선 독점 드라이버의 소스를 그대로 공개한 것 같진 않습니다. 그런데 재미있는 점은 성능에서 Gallium3D의 오픈 소스 드라이버가 독점 드라이버를 앞지른다는 겁니다. 대체 뭘 하는 거냐 AMD...

  NVIDIA는 소스를 공개하고 있지 않습니다. 그래서 nouveau도 순전히 리버스 엔지니어링에 의존하고 있었습니다. 그러던 올해 9월, 자신들을 향한 리눅스 커뮤니티의 비난(+리누스 토발츠의 fxxk you 사건)이 신경쓰였는지 GPU 프로그래밍 문서를 공개했습니다. NVIDIA가 소스를 공개하고 있진 않지만 적어도 독점 드라이버의 성능에 있어서는 칭찬하지 않을 수 없습니다. 윈도우에서의 OpenGL 지원도 AMD와 비교했을 때 언제나 월등했고 결국 그게 리눅스에서도 결실을 맺은 겁니다.

  한편, AMD는 'Mantle'이라는 게임 그래픽 API를 독자적으로 개발하는 중이며 이를 통해 큰 퍼포먼스 상승을 노리고 있습니다. 일단은 멀티 플랫폼이고 리눅스에서도 뛰어난 성능을 발휘할 거라고 광고하고 있긴 한데...그 이전 문제로 신기술임과 동시에 AMD의 GPU만을 위한 기술이라 이런 단점을 감수하면서까지 Mantle을 도입할 개발사는 그리 많지 않을 것이라는 게 제 생각입니다.
2013/12/19 21:56 2013/12/19 21:56
Posted
Filed under 시스템
참조 원문: Life cycle of a process

  시스템에서 뭔가를 하려면 프로세스가 필요합니다. 프로세스는 일반적으로 바이너리 실행 프로그램을 실행했을 때 생성됩니다. 코드가 프로세스로 변환되는 과정, 프로세스가 생성되는 방법, 죽기 전까지 거치는 상태를 이해하는 것은 상당히 중요합니다. 이 글에서는 코드가 실행 파일이 되고 거기서 다시 프로세스로 되는 과정, 프로세스와 관련이 있는 식별 요소들, 프로세스의 메모리 구조, 프로세스의 상태, 리눅스 내에서 프로세스의 전체적인 라이프 사이클에 대한 요약을 알아볼 것입니다.

코드에서 실행 프로그램으로
  소프트웨어 프로그램의 생명은 개발자가 코드를 작성할 때부터 시작됩니다. 여러분이 사용하는 모든 소프트웨어 프로그램은 특정 프로그래밍 언어로 작성됐습니다. 코드 작성이 끝나면 다음 단계로 그것을 실행 프로그램으로 변환합니다. 컴파일 프로세스가 코드를 기계 수준의 명령어(실행 프로그램)로 변환하죠. 그러면 실행 프로그램은 OS가 이해할 수 있는 기계 코드를 갖게 됩니다.

실행 프로그램에서 프로세스로
  프로그램이 실행되면 ps 명령어로 관련 프로세스를 확인할 수 있습니다. 리눅스에서 프로세스와 관련된 주요 식별 요소는 3가지로 프로세스 ID, 부모 프로세스 ID, 그룹 ID가 있습니다.

  init이란 프로세스는 리눅스 시스템에 생성되는 첫 번째 프로세스이며 프로세스 ID는 1입니다. 다른 모든 프로세스는 init의 자식 또는 그 이하입니다. pstree 명령어를 사용하면 활동 중인 프로세스들을 계층 구조로 볼 수 있습니다.

리눅스 프로세스의 메모리 구조
  리눅스 프로세스의 메모리 구조는 아래의 메모리 세그먼트들로 이뤄져 있습니다.

Stack: 지역 변수와 함수 인자(프로그램 코드에 정의되어 있음)가 있는 세그먼트입니다. 이 안에 있는 내용은 LIFO(last in, first out) 순서로 저장됩니다. 함수가 호출되면 새로운 함수와 연관된 메모리는 stack에 할당됩니다. 필요할 경우 메모리가 동적으로 증가하지만 일정한 수준까지만 가능합니다.

메모리 맵핑: 이 영역은 맵핑 파일을 위해 사용합니다. 이것이 존재하는 이유는 메모리에 맵핑된 파일에 대한 입출력 작업은 (일반적으로 파일이 저장된 곳인)디스크에 대한 입출력과 비교했을 때 프로세서(CPU)와 시간을 별로 소모하지 않기 때문입니다. 그렇기 때문에 이 영역은 거의 대부분 동적 라이브러리를 위해 사용합니다.

Heap: Stack에는 2가지 제한이 있습니다. 크기가 그리 넉넉치 못하다는 것과 stack을 생성한 함수가 종료되거나 값을 반환할 때 stack의 모든 변수도 사라진다는 겁니다. 이런 점에 있어서 heap 메모리 세그먼트가 빛을 발합니다. 이 세그먼트를 통해 매우 큰 메모리를 할당할 수 있으며 이렇게 할당한 메모리는 프로그램이 끝날 때까지 사용할 수 있습니다. 그러므로 heap에 할당한 메모리는 프로그램이 종료되거나 프로그래머가 함수 호출을 통해 명시적으로 해제하기 전까지 해제되지 않습니다.

BSS와 데이터 세그먼트: BSS 세그먼트에는 최초에 명시하지 않은 정적/전역 변수를 저장하며, 데이터 세그먼트에는 값을 최초에 명시한 변수를 저장합니다. 참고로 전역 변수란 함수 안에 정의되어 있지 않으며 프로그램과 스코프/라이프타임이 동일한 변수를 말합니다. 유일한 예외는 함수 안에 있지만 static 키워드로 정의된 변수로서 그 스코프는 함수 내로 제한됩니다. Static으로 정의된 변수들은 BSS 또는 데이터 세그먼트에 전역 변수들과 함께 저장합니다.

텍스트 세그먼트: 프로세서가 읽고 실행할 프로그램의 모든 기계 수준 코드 명령어를 보관하고 있습니다. 이 세그먼트는 쓰기 보호가 되어 있어서 수정이 불가능합니다. 만약 그런 시도를 하면 crash나 segmentation fault가 발생합니다.

참조: 실제 메모리 구조는 위의 내용보다 더 복잡하지만 이 정도만으로도 개념을 잡기엔 충분합니다.

리눅스 프로세스의 상태
  리눅스에서 프로세스를 실시간으로 관찰할 때는 top 명령어를 사용합니다. 이 명령어의 8번째 칼럼에는 프로세스의 상태가 적혀 있습니다. 여기에 나오는 용어의 뜻을 이해하는 것은 매우 중요합니다. 리눅스의 프로세스는 다음 중 하나의 상태에 놓입니다.

Running: 프로세스가 실제로 실행되고 있거나 실행되기 위해 스케줄러의 큐에서 대기 중(실행 준비 완료)인 상태입니다. 때문에 경우에 따라 'runnable'이나 R로 표시하기도 합니다.

Waiting 또는 Sleeping: 어떤 일을 발생하는 것을 기다리거나 완료를 위해 특정 리소스가 필요한 작업을 위해 기다리는 상태입니다. Waiting 상태는 상황에 따라 interruptible(S)과 uninterruptible(D)로 나눠지기도 합니다.

Stopped: 멈추라는 신호를 받은 상태입니다. 일반적으로 디버그를 할 때 볼 수 있습니다. 이 상태는 T로 표시합니다.

Zombie: 실행은 끝났지만 부모가 종료 상태를 회수하기 전까지 기다리는 상태입니다. 이 상태는 Z로 표시합니다.

  위 상태들이 끝나면 프로세스는 죽습니다. 정확히 따지자면 죽은 프로세스는 존재 자체가 사라지므로 '죽음'이란 상태는 없습니다.

프로세스의 라이프 사이클
  프로세스는 생성되는 순간부터 종료되기(또는 kill 당하기)까지 다양한 단계를 거칩니다. 여기서는 리눅스 프로세스의 탄생부터 죽음까지의 라이프 사이클 전체를 설명합니다.

  리눅스 시스템이 처음 켜지면 압축된 커널 실행 코드가 메모리에 적재됩니다. 이 실행 코드가 리눅스 시스템의 다른 모든 프로세스를 생성하는 것에 대한 책임을 지는 init 프로세스(또는 시스템의 첫 프로세스)를 생성합니다.

  Running 프로세스는 자식 프로세스를 생성할 수 있습니다. 자식 프로세스는 fork() 함수나 exec() 함수(exec() 함수는 어떤 실행 파일을 실행시키고 그로 인해 생긴 프로세스를 자신에게 덮어씌우는 함수로 자식 프로세스를 생성하는 함수가 아님)로 생성할 수 있습니다. 만약 fork()를 사용하면 해당 프로세스는 부모 프로세스의 주소 공간을 사용하며 부모와 같은 모드에서 실행됩니다. 새롭게 탄생한 (자식)프로세스는 부모로부터 모든 메모리 세그먼트를 복사해서 물려받지만 (부모나 자식이)세그먼트를 수정하려고 하기 전까진 계속해서 같은 세그먼트를 사용합니다. 이에 반해 exec()를 사용하면 프로세스에 새로운 주소 공간이 할당되므로 처음에는 커널 모드에 진입합니다. 참고로 부모 프로세스가 새로운 프로세스를 생성하려면 running 상태(이면서 프로세스에 의해 실제로 실행 중인 상태)여야 합니다.

  커널 스케줄러의 상황에 따라 다른 프로세스가 CPU를 선점하면 그 전에 CPU를 사용하던 running 프로세스는 큐로 쫓겨나 다시 실행되기 전까지 대기하게 됩니다.

  만약 프로세스가 하드웨어 리소스를 확보하거나 파일 입출력 작업을 할 필요가 있다면 프로세스는 일반적으로 시스템 콜을 하여 커널 모드로 진입합니다. 만약 리소스가 이미 사용 중이거나 파일 입출력에 시간이 걸린다면 프로세스는 sleeping 상태로 들어갑니다. 리소스를 사용할 수 있거나 파일 입출력이 끝나면 프로세스는 '프로세스를 깨우는 신호(signal)'를 받고 일어나 커널 모드로 실행을 계속하거나 유저 모드로 되돌아갈 수 있습니다. 참고로 그 프로세스가 즉시 실행을 시작할 것이란 보장은 없으며 그것은 순전히 (실행 준비를 위해 프로세스를 프로세스 큐에 넣는)스케줄러에 달려 있습니다.

  만약 프로세스를 디버그 모드(예: 디버거가 프로세스에 부착됨)로 실행하면 디버그 프레이크포인트를 만났을 때 정지 신호를 받습니다. 이 단계에서 해당 프로세스는 stop 상태에 들어가며 유저는 프로세스의 메모리 상태, 변수 값 등을 가지고 디버그할 시간을 갖게 됩니다.

  프로세스가 정상적으로 값을 반환하거나 종료될 수도 있고 다른 프로세스에 의해 죽을 수도 있습니다. 어느 쪽이 됐든 간에 프로세스는 zombie 상태에 빠지게 되며 그렇게 되면 그 프로세스에 대한 것들 중 (커널에 의해 관리되는)프로세스 테이블에 있는 그 프로세스 항목을 제외한 모든 것이 사라집니다. 그 항목은 부모 프로세스가 자식 프로세스의 반환 상태를 회수하기 전까지 지워지지 않고 남습니다. 반환 상태는 프로세스가 일을 정상적으로 마쳤는지를 나타냅니다. 'echo $?' 명령어를 통해 커맨드 라인로 실행한 마지막 명령어의 상태(기본적으로 반환 상태가 0인 경우만 정상 종료로 취급)를 확인할 수 있습니다. 프로세스가 zombie 상태로 진입하면 다른 상태로 진입하기 위해 필요한 것들이 모두 사라지기 때문에 더 이상 다른 상태로 진입할 수 없게 됩니다.

  만약 자식 프로세스가 죽기 전에 부모 프로세스가 죽으면 자식 프로세스는 고아가 되어 init 프로세스에게 입양되는데 이는 init이 그 프로세스의 새 부모가 된다는 것을 의미합니다.

Load Average란 무엇인가?
  시스템 자원 사용률을 측정하는 프로그램들에서 load average라는 것을 쉽게 볼 수 있는데 이는 실행을 기다리는 프로세스 큐의 현재 길이의 평균값을 뜻합니다. 리눅스의 경우 이 수치는 실제 실행 중인 큐(actual run queue), 실행 가능한 큐(runnable queue), 깨울 수 없는(uninterruptable) sleep 상태에 빠진 프로세스 개수의 조합으로 결정됩니다. CPU 사용률과 load average 값이 함께 높을 때도 있지만 일반적으로 load average 값이 높다는 것은 프로세스들이 입출력 대기 때문에 일을 끝내지 못하고 기다리고 있다는 것을 의미합니다. 그러므로 리눅스의 경우 CPU 사용률과는 무관하게 load average가 높다면 프로세스가 CPU를 사용하기 위해 대기하는 시간이 길어지게 되어 모든 것이 느려지게 됩니다.
2013/12/10 17:50 2013/12/10 17:50
Posted
Filed under 시스템
참조 원문 : LXC vs. OpenVZ

  LXC(Linux Containers)는 리눅스의 컨테이너 기반 기상화의 새로운 주력 솔루션입니다. 아직 기능이 완벽하지 않고, 여전히 많은 사람들이 기존의 메인이던 OpenVZ을 사용하고 있지만 OpenVZ은 사실상 3.x 커널이 더 이상 지원하지 않기 때문에 지금 상태로는 그 생명이 끝나가고 있다고 할 수 있습니다. 이 글에서는 컨테이너 기반 가상화 솔루션의 차이를 비교해보겠습니다. 약간 옛날 데이터라 우분투 12.04가 기준입니다. 참고로 LXC를 가장 잘 지원하는 배포판이 우분투입니다.

                                                                                     OpenVZ                     LXC

리눅스 커널에 포함                                                        X                              O

메모리 사용률 제한 기능                                               O                              O

커널 메모리 제한 기능                                                   O                              X

CPU 사용률 제한 기능                                                  O                              O

디스크 공간 사용량 제한 기능                                      O                        부분/꼼수

디스크 IO 제한 기능                                                       X                              O

체크포인팅                                                                      O                              X

라이브 마이그레이션                                                     O                          X/꼼수

컨테이너 락다운(보안)                                                  O                            부분


리눅스 커널에 포함
  OpenVZ와 달리 LXC는 리눅스 커널에 포함되어 있습니다. 다만 OpenVZ도 커널의 많은 기능을 사용하긴 합니다. LXC는 커스텀 커널을 빌드할 필요가 없기 때문에 설치가 훨씬 쉽습니다. 단, 레드햇이나 수세 계열의 경우 미리 만들어진 OpenVZ 커널 이미지를 다운로드하여 사용할 수 있습니다. 주의할 점은 상당히 오래된 커널을 이용해 만든 OpenVZ 커널 이미지만 있다는 것입니다. 앞서 나왔던 설명처럼 최신 커널을 지원하지 않습니다.

  참고로 OpenVZ는 현재 대부분의 유저스페이스 유틸리티들을 LXC 기반으로 포팅하고 있기 때문에 향후에는 성능이 향상될 것입니다. vzctl 4.3은 OpenVZ가 아닌 컨테이너도 지원하며 CRIU를 통해 라이브 마이그레이션도 가능할 것이라고 합니다.


메모리 사용률 제한 기능
  둘 다 가능합니다. LXC에선 게스트의 사용 메모리를 조정하기 위해 VM-s 설정 파일에서 2개의 cgroup 설정을 사용합니다. 가장 중요한 설정은 메모리를 위한 lxc.cgroup.memory.limit_in_bytes과 스왑을 위한 lxc.cgroup.memory.memsw.limit_in_bytes입니다. 사용하는 커널 버전에 따라 다른 설정이 있을 수도 있습니다. /sys/fs/cgroup/memory/lxc/your-vm-name을 통해 설정 상태를 확인할 수 있습니다.


커널 메모리 제한
  애플리케이션이 커널을 이용하는 동안 커널 메모리를 사용할 수 있습니다. OpenVZ를 사용할 때는 VE 당 이 메모리의 사용을 제한할 수 있습니다.


CPU 사용률 제한
  둘 모두 자신의 CPU 사용률을 제한할 수 있습니다. CPU 대역폭은 지정한 한도 내에서 공유하여 사용하도록 제한됩니다. lxc.cgroup.cpu.shares 설정 값을 조정하여 VM의 CPU 사용량을 설정할 수 있으며, lxc.cgroup.cpuset.cpus로 CPU 코어를 제한할 수 있습니다.


디스크 공간 사용량 제한
  리눅스에서는 디스크 쿼터를 핵심기능으로 두고 있지 않기 때문에 LXC에선 디스크 쿼터를 지원하지 않습니다. VM을 LVM 볼륨에 넣어서 제한을 둘 수 있지만 IO 성능에 제한을 받게 됩니다.


디스크 IO 제한
  IO가 많이 필요한 애플리케이션을 다수 사용할 때는 디스크 IO를 제한하는 기능이 매우 중요합니다. OpenVZ에는 이 기능이 없지만 그것의 상용 버전인 Virtuzzo에는 있습니다. LXC는 lxc.cgroup.blkio이라는 cgroup을 통해 이 기능을 사용할 수 있으며 자세한 건 /sys/fs/cgroup/blkio/lxc에서 볼 수 있습니다.


체크포인팅
  전통적인 최대 절전 모드와 유사한 기능입니다. VM의 상태가 파일로 저장되며 다시 불러올 수 있습니다. 이 기능은 lxc-checkpoint라는 명령어를 통해 사용할 수 있게 될 예정이지만 원문이 작성된 시점(2013년 1월)에서는 구현되지 않았었습니다.


라이브 마이그레이션
  VM을 중단하지 않고 물리적으로 다른 호스트에 넘기는 기능입니다. 그러므로 메모리 내용도 새로운 호스트로 옮길 수 있어야 합니다. OpenVZ는 이미 꽤 오래 전부터 이 기능을 가지고 있었지만 LXC는 아직도 지원하고 있지 않습니다. 정식으로 지원되는 방법은 아니지만 유저스페이스를 이용한 라이브 마이그레이션을 구현하기 위한 프로젝트인 CRIU를 사용하면 가능하긴 합니다.


컨테이너 락다운(보안)
  가상화에서 격리는 중요한 요소입니다. OpenVZ는 이 기능이 잘 구현되어 있지만 LXC는 아직 완벽하지 않습니다. 심지어 우분투에서 AppArmor가 활성화되어 있는 상황에서도 게스트에서 dmesg에 접근할 수 있으며 /proc/kcore와 /proc/sysrq-trigger에도 접근할 수 있어 게스트 VM의 root 사용자가 호스트 머신을 쉽게 리스타트할 수 있습니다. 원문이 작성된 시점에서는 우분투 13.04에서 이 문제가 개선될 계획이었는데 위키에 관련 내용이 업데이트되지 않아서 어떻게 됐는지 모르겠습니다.



결론
  LXC가 유동성에 있어선 좋은 선택이 될 수 있을지 몰라도 위에서 볼 수 있듯이 외부 VM을 호스팅하기엔 아직 부적절한 점이 많습니다. 따라서 그런 종류의 사업에 사용하기엔 좀 더 기다려야 할 필요가 있습니다.


2013/07/25 21:25 2013/07/25 21:25
Posted
Filed under 시스템
참조 원문 : Understanding free command in Linux/Unix
참조 원문 : Help! Linux ate my RAM!

  free 명령어의 출력 결과를 보면 버퍼와 캐시라는 것이 있습니다.
$ free
             total       used       free     shared    buffers     cached
Mem:       4042408    1463740    2578668          0     171752     693644
-/+ buffers/cache:     598344    3444064
Swap:      4190204          0    4190204
  대체 이 버퍼와 캐시가 무엇일까요? 그리고 두 번째 줄(-/+ buffers/cache)에 있는 값은 뭘까요? 먼저 첫 번째 줄부터 살펴보겠습니다.
  • 4042408 : 메모리(물리적인 RAM)의 총량.
  • 1463740 : 시스템에서 사용하고 있는 메모리(RAM)의 총량으로 버퍼와 캐시된 데이터의 크기까지 포함.
  • 2578668 : 남은 메모리의 총량.
  • 0 : 공유된 메모리. 이 칼럼은 더 이상 사용되지 않으며 향후에 사라질 예정.
  • 171752 : 응용 프로그램들에 의해 버퍼된 메모리의 총량.
  • 693644 : 향후를 위한 데이터 캐싱에 사용한 메모리의 총량.
  그렇다면 버퍼와 캐시의 차이가 대체 뭘까요? 버퍼는 응용 프로그램별로 존재하는 임시 데이터 저장 공간으로서 이 데이터는 다른 응용 프로그램이 사용하지 않습니다. 반면 캐시는 더 빠른 접근을 위해 자주 사용하는 데이터를 저장하는 메모리 공간입니다. 캐시는 여러 번 사용될 수 있지만 버퍼는 한 번만 사용합니다. 둘 모두 데이터 처리를 위한 임시 공간이라는 공통점이 있습니다.

  아래는 두 번째 줄에 있는 값의 의미입니다.
  • 598344 : 실제 사용 중인 메모리의 총량. 사용하고 있는 메모리의 총량에서 버퍼와 캐시에 사용하고 있는 양을 뺀 값. 1463740 - (171752 + 693644) = 598344.
  • 3444064 : 실제 남은 메모리의 총량. 메모리의 총량에서 실제 사용 중인 메모리의 총량(위의 값)을 뺀 값.
     4042408 - 598344 = 3444064
  리눅스는 사용하고 있지 않는 메모리를 빌려서 디스크 캐싱에 사용합니다. 만일 메모리의 여유 공간(첫 번째 줄의 세 번째 값)이 없는 상태에서 어떤 응용 프로그램이 메모리를 할당받으려고 하면 리눅스는 즉시 버퍼/캐시가 여유 부리며 빌린 공간을 빼서 그 응용 프로그램에게 할당해줍니다. 즉, 실제 여유 공간은 첫 번째 줄의 세 번째 값이 아니라 두 번째 줄의 두 번째 값입니다. 이에 대한 더 자세한 내용은 이곳을 참조하시기 바랍니다.


2013/07/15 22:20 2013/07/15 22:20
Posted
Filed under 시스템
참조 원문 : All About inodes, Hard Links and Soft Links

  터미널로 ls -i 를 실행하면 각 파일에 번호가 붙은 걸 볼 수 있습니다.
$ ls -i
807337 Ubuntu One        808148 다운로드  808154 비디오  808149 템플릿
807981 examples.desktop  808151 문서      808153 사진
808150 공개              808147 바탕화면  808152 음악
  • 이 번호는 무엇인가?
  • 파일을 지우면 무슨 일이 벌어지나?
  • 시스템은 파일의 주인이나 파일의 마지막 변경 시간을 어떻게 알고 있나?
  • 하드 링크는 무엇인가?
  • 하드 링크와 소프트 링크의 차이는 무엇인가?
  이 글에서는 위의 내용을 알아보겠습니다. 연결된 각종 장치와 디렉토리를 포함하여 리눅스에 있는 모든 것은 파일입니다. 파일시스템(여기서는 ext3/ext4로 가정)이 디스크에 생성되면 특수한 데이터 구조가 만들어집니다. 이것을 inode 테이블(기술적으로 말하자면 구조체의 배열)이라고 합니다. 이것은 1번부터 파일시스템의 inode 최대 개수까지 번호가 매겨있습니다. inode의 최대 개수는 일반적으로 파일시스템을 생성할 때 정합니다. df -i 명령어를 통해 현재 사용 중인 inode 개수와 남은 inode 개수를 볼 수 있습니다.

  파일이나 디렉토리를 만들면 사용 중이지 않은 inode 번호가 하나 할당되며 그 안에 그 파일이나 디렉토리에 대한 정보들이 저장됩니다. POSIX 표준은 inode에 최소한 다음과 같은 정보들이 있어야 한다고 정의하고 있습니다.
  • 파일의 크기(바이트 단위)
  • 디바이스 ID(파일을 담고 있는 디바이스를 식별하는데 사용)
  • 파일의 소유주의 User ID
  • 파일의 Group ID
  • 파일의 타입과 파일의 소유주, 소유 그룹, 그 외의 사용자가 그 파일에 접근할 수 있는지를 정하는 파일 모드
  • 파일을 보호하기 위한 추가적인 시스템과 유저 플래그(사용과 변경을 제한)
  • inode 자체가 마지막으로 변경된 시간(ctime, inode change time), 파일 내용이 마지막으로 변경된 시간(mtime, modification time), 마지막 접근 시간(atime, access time)의 타임스탬프
  • 얼마나 많은 하드 링크가 이 inode를 가리키고 있는지를 나타내는 링크 개수
  • 파일의 내용이 저장된 디스크 블록을 가리키는 포인터
  참고로 위를 보면 파일명이 없습니다. 사실 inode는 파일명을 전혀 다루지 않습니다. 그럼 대체 우리가 파일을 열 때 시스템이 그 파일의 inode를 어떻게 아는 걸까요? 이걸 이해하려면 디렉토리라는 게 정확히 무엇인지 알 필요가 있습니다. 처음에 앞서 말했듯 리눅스의 모든 것은 파일입니다. 심지어 디렉토리 조차도 다르지 않습니다. 모든 디렉토리는 데이터 구조체의 집합입니다. 각 구조체의 첫 번째 부분에는 inode 번호가, 두 번째 부분에는 파일명이 담겨있습니다. 그래서 우리가 파일에 어떤 작업을 하면 파일명에 해당하는 inode 번호를 찾는 일이 발생하며 이것이 inode를 얻는 방법입니다.

  inode에 있는 정보 중 링크 개수와 파일 크기는 지속적인 관리 대상에 속합니다. 파일을 삭제하면 링크 개수는 감소하며 이 숫자가 0이 되면 파일의 크기도 0이 됩니다.
$ ls -i abc
802017 abc

$ sudo istat /dev/mapper/ubuntu--vg-root 802017
(생략)
num of links: 1
(생략)

$ ln abc def
$ sudo istat /dev/mapper/ubuntu--vg-root 802017
(생략)
num of links: 2
(생략)

$ rm abc
$ sudo istat /dev/mapper/ubuntu--vg-root 802017
(생략)
num of links: 1
(생략)
  위 결과를 보면 ln 명령어로 하드 링크를 만들었을 때 "num of links"가 1 증가하는 것을 알 수 있습니다. rm 명령어로 파일을 삭제하면 반대로 값이 1 감소합니다. 만약 def 파일도 삭제한다면 링크 개수와 파일 크기가 모두 0이 됩니다.
$ rm def
$ sudo istat /dev/mapper/ubuntu--vg-root 802017
inode: 802017
Not Allocated
Group: 97
Generation Id: 1113877821
uid / gid: 1000 / 1000
mode: rrw-rw-r--
Flags:
size: 0
num of links: 0

Inode Times:
Accessed:    Wed Jul 10 20:25:24 2013
File Modified:    Wed Jul 10 20:31:49 2013
Inode Modified:    Wed Jul 10 20:31:49 2013
Deleted:    Wed Jul 10 20:31:49 2013

Direct Blocks:
  다만 파일을 삭제해도 가끔 "num of links" 값이 0이 되지 않을 때가 있는데 이것은 보통 그 파일을 잡고 있는 프로세스가 있을 때 발생합니다. 서비스가 작동하고 있는 상태에서 그 서비스의 로그 파일을 삭제했을 때 자주 볼 수 있는 현상입니다.

  그렇다면 하드 링크는 무엇이며 소프트 링크는 무엇일까요? 어떤 파일의 하드 링크는 그 파일의 inode 값을 가지고 있는 반면 어떤 파일의 소프트 링크는 그냥 그 파일을 가리키기만 합니다. 만약 원본 파일을 지웠더라도 그 파일에 대한 하드 링크가 있었다면 그 하드 링크를 이용해 파일의 내용에 여전히 접근하는 것이 가능합니다. 하지만 소프트 링크의 경우 inode를 담고 있는 원래 파일을 가리키는 것이 전부이기 때문에 원본 파일을 삭제하면 아무 쓸모가 없어집니다. 이를 간단히 나타내면 아래와 같습니다. "원본명"과 "하드 링크"는 모두 inode를 가리키지만 "소프트 링크"는 그렇지 않은 것을 확인할 수 있습니다.
원본명 ---------> inode <--------- 하드 링크
소프트 링크 ----------> 원본명 -----------> inode
  하지만 소프트 링크도 소프트 링크만의 장점이 있습니다. 하드 링크는 다른 파일시스템에 있는 파일을 가리킬 수 없지만 소프트 링크는 가능합니다. 또한 여러 버전의 파일들을 하나의 이름으로 관리할 때도 아주 좋습니다. 아래는 /usr/bin/python 파일이 사실은 다른 바이너리 파일을 가리키고 있다는 것을 보여주고 있습니다.
$ ls -l /usr/bin/python
lrwxrwxrwx 1 root root 9  6월 17 14:10 /usr/bin/python -> python2.7
  또 다른 활용법은 실행한 파일의 이름을 담고 있는 변수를 이용하는 것입니다. 하나의 파일에 여러 소프트 링크를 만들고 어떤 소프트 링크를 통해 실행했는지 판단하여 그에 맞는 처리를 하는 방법입니다. 아래의 소프트 링크 파일들이 그 예입니다.
$ ls -al /sbin/mkfs.ext*
lrwxrwxrwx 1 root root 6  6월 17 14:10 /sbin/mkfs.ext2 -> mke2fs
lrwxrwxrwx 1 root root 6  6월 17 14:10 /sbin/mkfs.ext3 -> mke2fs
lrwxrwxrwx 1 root root 6  6월 17 14:10 /sbin/mkfs.ext4 -> mke2fs
lrwxrwxrwx 1 root root 6  6월 17 14:10 /sbin/mkfs.ext4dev -> mke2fs






2013/07/10 20:57 2013/07/10 20:57
Posted
Filed under 시스템
참조 원문 : UUIDs and Linux: Everything you ever need to know

UUID란?
  UUID는 32개의 16진수로 표현하는 128비트 값이며 유일 식별 정보로서 소프트웨어 개발에 사용합니다. RFC 4122로 정의되었으며 아래는 UUID의 예입니다.
13152fae-d25a-4d78-b318-74397eb08184
  리눅스에서는 블록 디바이스의 식별자로 쓰이는 것으로 유명합니다. Windows에서는 Component Object Model에서 GUID(Globally Unique Identifier)라는 이름으로 사용합니다. UUID는 많은 변종이 있는데 대부분은 컴퓨터의 MAC을 기반으로 만들었습니다.


fstab에서의 사용
  USB로 연결하는 하드 디스크가 있는데 고정된 디바이스명이 없고 연결할 때마다 이름이 sda, sdb 이런 식으로 달라진다면 여러가지 문제가 생길 수 있습니다. 이런 문제를 방지하기 위해 /etc/fstab에서는 아래와 같이 유일한 이름을 사용합니다.
UUID=9043278a-1817-4ff5-8145-c79d8e24ea79 /boot ext3 defaults 0 2
  UUID는 슈퍼블록에 저장됩니다.


리눅스에서 활용 및 생성
  proc을 통해 새로운 UUID를 생성하는 방법은 아래와 같습니다.
$ cat /proc/sys/kernel/random/uuid
eaf3a162-d770-4ec9-a819-ec96d429ea9f
  libuuid 라이브러리를 사용하는 uuidgen 명령어를 통해 생성하는 방법도 있습니다. 특히 ext2~4 파일시스템 유틸리티 패키지인 e2fsprogs가 UUID를 생성할 때 이 라이브러리를 사용합니다.
$ uuidgen
f81cc383-aa75-4714-aa8a-3ce39e8ad33c


UUID를 알아내는 방법
  하드 디스크의 현재 UUID를 알아내는 방법은 크게 2가지가 있는데 하나는 특수 디렉토리를 ls 명령어로 출력하는 것이고, 나머지 하나는 blkid 툴을 사용하는 것입니다.

  ls를 이용하는 방법은 /dev/disk/by-uuid 디렉토리를 이용하면 됩니다. 이 디렉토리는 이름이 UUID이며 실제 블록 디바이스 파일로 연결된 링크 파일들을 가지고 있습니다.
$ ls -l /dev/disk/by-uuid
합계 0
lrwxrwxrwx 1 root root 10  7월  8 12:30 16b18fc2-bf33-41c1-af7b-a21e9c848b4c -> ../../dm-1
lrwxrwxrwx 1 root root 10  7월  8 12:30 5aed7aad-ada9-44cf-89dd-0da2df853a34 -> ../../dm-0
lrwxrwxrwx 1 root root 10  7월  8 12:30 ef3c61f8-8119-49db-a55a-ca0ae5cd5f86 -> ../../sda1
  blkid는 util-linux 패키지에 속한 툴로 특정 디바이스에 대한 질의를 할 수 있는 인터페이스를 제공하며 라벨도 볼 수 있습니다.
$ blkid /dev/sda1
/dev/sda1: UUID="ef3c61f8-8119-49db-a55a-ca0ae5cd5f86" TYPE="ext2"


UUID 설정하기
  UUID는 슈퍼블록에 있기 때문에 이를 설정하는 방법은 파일 시스템에 따라 다릅니다. ext 파일 시스템은 tune2fs로 설정할 수 있습니다.
# tune2fs -U 원하는_UUID /dev/sda1
2013/07/10 16:04 2013/07/10 16:04