'Tips/Kernel development'에 해당되는 글 3건

  1. 2012.09.30 VFS : Virtual File System - Introduction
  2. 2012.03.15 PID Namespace
  3. 2012.01.31 Linux Kernel : 커널이란
Tips/Kernel development2012. 9. 30. 01:21

Virtual File System


리눅스를 비롯한 대부분의 유닉스 계열 운영체제는 VFS라는 레이어를 제공한다. 이것은 표준의 SCI(System Call Interface)와 ext2, ext3 를 비롯한 실제 파일시스템 구현 사이에 존재하는 일종의 인터페이스이며, 커널은 이 인터페이스를 통해서 파일시스템 수준에서 동작해야 하는 작업을 처리하기 때문에 가상 파일 시스템(VFS)라는 이름이 붙게 되었다.


그렇다면 왜 VFS가 존재하게 되었는가?


컴퓨터 기술의 발전과 동시에 이를 관리하기 위한 시스템 기술들도 발전하게 되었다. 커널은 비선점형 커널에서 선점형 커널로 발전하였고, 멀티 코어를 지원하기 위한 개념들도 등장하게 되었다. 이는 저장장치와 이 저장장치를 다루는 드라이버 레벨의 소프트웨어, 그리고 보다 추상적인 관점에서 운영체제와 저장장치간의 교두보 역할을 하게 되는 파일 시스템도 마찬가지이다. 기존의 UFS에서 도스 기반의 FAT, 리눅스의 등장과 함께 그 발전을 함께한 ext 계열의 파일 시스템들이 바로 그 맥락에서 발전해온 파일 시스템들이다. 


파일 시스템은 사용자 어플리케이션을 대신하여 파일 레벨의 작업을 수행한다. 사용자 어플리케이션이 표준 라이브러리의 함수를 호출하여 특정 파일에 '쓰기'작업을 한다고 치면, 라이브러리는 커널의 write() 시스템 콜을 호출할 것이다. 커널은 해당 시스템 콜에서 타겟으로 하는 파일이 존재하는 파일시스템에게 write() 시스템 콜에서 정의되어 있는 루틴대로 작업을 시킬 것이고, 파일 시스템은 작업을 처리한 후 커널에게 다시 적절한 값을 리턴할 것이다. 최종적으로 사용자는 커널과 표준 라이브러리로부터 리턴값을 돌려받아 작업이 제대로 처리되었는지를 확인하게 될 것이다.


이는 파일 시스템이 하나만 존재하는 경우에만 성립한다 할 수 있다. 파일 시스템이 둘 이상 존재하게 될 경우, 모든 파일 시스템이 동일한 함수를 제공하지 않는 이상 시스템 콜도 그에 맞추어 서로 다른 루틴으로 작성되어야 할 것이다. 이렇게 되면 새로운 파일 시스템이 생길 때마다 새로운 시스템 콜이 작성되어야 할 것이고, 운영체제도 다시 컴파일 되어야 할 것이다.


이런 문제점을 해결하기 위해서 커널은 모든 파일 시스템이 지켜야할 일종의 표준 모델을 제시하였다. 앞으로 살펴볼 VFS상의 컴포넌트들이 바로 그것인데, 리눅스 커널은 이 모델을 정의하며 객체 지향 모델의 특징을 가져왔다. 하나의 자료구조에 관리를 위한 변수 뿐 아니라 함수의 포인터들의 선언으로 이루어진 테이블을 정의한 것이다. 다음은 표준 모델 중 하나인 struct file의 간략한 예시이다. 


struct file {

struct list_head f_list;

struct dentry * f_dentry;

struct vfsmount * f_vfsmnt;

struct file_operations * f_op;

...

};


struct file_operations {

int (*llseek) (struct file*, int, int);

int (*func2) (int, void *);

...

};


file_operations는 해당 함수의 원형을 정해놓고, 포인터의 형태로 선언한 것이다. 파일 시스템은 이러한 구조체로 제시된 함수의 형식에 맞추어 그 세부사항을 구현하면 된다. 그렇게 되면 커널은 VFS 수준에서 해당 파일시스템의 함수 포인터를 이용한 호출로 작업을 완료할 수 있게 된다. 마치 객체 지향 모델의 인터페이스(혹은 추상클래스)와 같은 모습이라 할 수 있겠다. 


이러한 표준 모형을 제시하기 위해서 VFS는 4개의 객체를 정의한다. 각각은 다음과 같다.

  1. super_block
  2. inode
  3. dentry
  4. file
이 다음부터는 각각의 자료구조와 역할에 대해서 알아보기로 한다.


'Tips > Kernel development' 카테고리의 다른 글

PID Namespace  (0) 2012.03.15
Linux Kernel : 커널이란  (0) 2012.01.31
Posted by 곰푼
Tips/Kernel development2012. 3. 15. 22:50
lwn.net의 PID Namespace 관련 글 하나를 번역해보았다.

Namespace는 커널 2.6.24버전부터 도입된 것으로, 일종의 독립적인 PID 공간이라고 볼 수 있다. Namespace들 간에 부모-자식 관계가 있으며, 각 Namespace별로 PID가 따로 관리되기 때문에 동일한 PID를 Namespace별로 사용할 수 있게 된다.

다음은 글의 원문이다.

A pid namespace is a "view" of a particular set of tasks on the system. They work in a similar way to filesystem namespaces. A file (or a process) can be accessed in multiple namespaces, but it may have a different name in each. In a filesystem, this name might be /etc/passwd in one namespace, but /chroot/etc/passwd in another.

For processes, a process may have pid 1234 in one namespace, but be pid 1 in another. This allows new pid namespaces to have basically arbitrary pids, and not have to worry about what pids exist in other namespaces. This is essential for checkpoint/restart where a restarted process's pid might collide with an existing process on the system's pid.
In this particular implementation, pid namespaces have a parent-child relationship, just like processes. A process in a pid namespace may see all of the processes in the same namespace, as well as all of the processes in all of the namespaces which are children of its namespace. Processes may not, however, see others which are in their parent's namespace, but not in their own. The same goes for sibling namespaces.

The know issue to be solved in the nearest future is signal handling in the namespace boundary. That is, currently the namespace's init is treated like an ordinary task that can be killed from within an namespace. Ideally, the signal handling by the namespace's init should have two sides: when signaling the init from its namespace, the init should look like a real init task, i.e. receive only those signals, that is explicitly wants to; when signaling the init from one of the parent namespaces, init should look like an ordinary task, i.e. receive any signal, only taking the general permissions into account.
The pid namespace was developed by Pavel Emlyanov and Sukadev Bhattiprolu and we eventually came to almost the same implementation, which differed in some details. This set is based on Pavel's patches, but it includes comments and patches that from Sukadev.
Many thanks to Oleg, who reviewed the patches, pointed out many BUGs and made valuable advises on how to make this set cleaner.



pid namespace는 시스템 상의 태스크의 특정 집합의 "View"이다. 
그들은 파일시스템의 namespace와 유사한 방법으로 동작한다. 파일(혹은 프로세스)은 다양한 namespace에서 접근될 수 있다. 그러나 파일(혹은 프로세스)은 각 namespace에서 다른 이름을 가져야 할 것이다. 파일시스템에서, 한 namespace에서 이름이 /etc/passwd가 될 수 있다. 하지만 다른 namespace에서는 /chroot/etc/passwd가 되어야 한다.
 프로세스들을 위해서, 프로세스는 한 namespace에서 pid 1234를 가질 수 있지만 다른 곳에서는 pid 1이 될 수 있다. 이는 다른 namespace에 어떤 pid가 있는지 고려하지 않고 새로운 pid namespace가 기본적으로 임의의 pid들을 가질 수 있도록 해준다. 이는 재 시작된 프로세스의 pid가 시스템의 pid상에서 존재하는 프로세스와 충돌할 때, 
checkpoint/restart를 위해서 필수적이다
.
 특정 구현에서, pid namespace는 마치 프로세스처럼 부모-자식 관계를 갖는다. pid namespace 내의 프로세스는 같은 namespace안의 모든 프로세스 뿐만 아니라 그 namespace의 자녀 관계인 namespace들 안의 모든 프로세스들도 볼 수 있을 것이다. 그러나 프로세스는 그들의 부모 namespace의 프로세스들을 볼 수 없을 것이고, 사촌관계에 있는 namespace의 프로세스들도 볼 수 없을 것이다.
 곧 해결될 이슈는 namespace 경계에서 시그널 처리이다. 이것은 현재 namespace의 init이 namespace에서 kill될 수 있는 일반적인 태스크처럼 다루어지기 때문이다. 이상적으로, namespace의 init에 의한 시그널 처리는 두 가지 측면을 가져야만 한다. : 그것의 namespace로부터 init에 시그널이 도착했을 경우, init은 실제 init 태스크처럼 보인다. 즉 시그널을 받았을 때, 그것은 확실히 받길 원하는 것이어야 한다. 부모 namespace의 하나로부터 init이 시그널을 받았을 때, init은 일반 태스크처럼 보여야 한다. 즉 어떤 시그널을 받던지, 일반적인 권한이 고려되어야 한다.
pid namespace는 Pavel Emlyanov와 Sukadev Bhattiprolu에 의해서 개발되었다. 우리는 거의 같은 사양으로 구현하기로 결정하였고, 몇몇 세부사항만이 다를 뿐이다. 이는 Pavel의 패치에 기초하였으나, 그것은 Sukadev로부터의 패치와 코멘트를 포함하고 있다.
원문주소 : http://lwn.net/Articles/245104/

'Tips > Kernel development' 카테고리의 다른 글

VFS : Virtual File System - Introduction  (0) 2012.09.30
Linux Kernel : 커널이란  (0) 2012.01.31
Posted by 곰푼
Tips/Kernel development2012. 1. 31. 16:10
 컴퓨터는 CPU, 메모리, 디스크 등의 다양한 장치들로 구성되어 있다. 이 장치들을 추상화하여 사용자들이 혹은 응용프로그램이 사용하기 쉽도록 해주는게 바로 운영체제이며, 그 운영체제의 핵심이 바로 커널이다.

 커널은 컴퓨터에 부착된 장치들을 효율적으로 관리하도록 해주는 관리자의 역할을 한다. 각 장치들은 추상화를 통해 사용자들이 접근할 수 있게 된다.

커널은 크게 두 가지 타입으로 나뉠 수 있다. (하이브리드, 엑소 커널은 여기서는 논외로 하자.)

1. 모놀리식 커널 Monolithic Kernel

 이 커널은 시스템을 관리하기 위한 기능들이 하나의 이미지에 내장된 커널을 의미한다. 하드웨어 위에 고수준의 가상 계층을 가지고 있으며, 어플리케이션 영역의 프로그램 구현을 위한 서비스를 제공한다. 이 서비스에는 프로세스 스케줄링, 메모리 관리, 디스크 관리, 장치 관리 등이 있으며, 이를 위하여 시스템 콜(System Call)의 형태로 서비스들을 제공한다. 
 커널이 하나의 프로세스로써 단일 주소 공간에서 실행되도록 구현되어있으며, 커널 이미지는 일반적으로 단일 정적 바이너리로 존재한다. 


2. 마이크로 커널 Micro Kernel
 
 커널의 기능들을 서버(Server)라 불리는 분리된 프로세스로 조각내어서 커널 자체의 크기를 줄인 커널이다. 각 서버들은 다른 주소공간에서 실행되도록 분리되어 있으며, 오직 서버만이 각 기능들을 특권 실행 모드(Privileged execution mode)에서 실행할 수 있다. 그러므로 모놀리식 커널에서와 같은 직접적인 함수 호출이 불가능하고, 대신 IPC와 같은 메시지 패싱 기법으로 호출할 수 있다. 
 IPC 매커니즘이 일반적인 함수 호출에 비해 꽤 큰 오버헤드를 갖고 있고, 또 커널 공간과 사용자 공간의 컨텍스트 전환(Context Switch)이 자주 발생하기 때문에, 모놀리식 커널에서 볼 수 없는 추가적인 처리량을 내재하고 있다.

 

Features of Linux Kernel::

 

리눅스 커널은 모놀리식 커널이지만, 모듈을 동적으로 적재할 수 있도록 지원한다. 모듈은 필요에 따라 그 코드가 적재(Load) 혹은 제거(Unload)될 수 있다.

SMP(Symmetric MultiProcessor)를 지원한다. SMP는 두 개 또는 그 이상의 프로세서가 하나의 메모리 공간을 공유하여 사용하는 다중 프로세서 아키텍쳐이다.

선점형 커널이다. 선점형 커널에서는 시스템 콜 루틴 수행 중간에 인터럽트를 체크해서 인터럽트의 수행을 우선시한다. 비선점형 커널에서는 시스템 콜을 우선시하여, 해당 호출이 끝난 후에 인터럽트를 수행한다.

리눅스에서는 스레드와 프로세스가 서로 다르지 않다. 이는 리눅스에서 스레드의 구현을 light weight process로 구현하기 때문이며, 이에 대해서는 나중에 논하기로 하겠다.

'Tips > Kernel development' 카테고리의 다른 글

VFS : Virtual File System - Introduction  (0) 2012.09.30
PID Namespace  (0) 2012.03.15
Posted by 곰푼