맛있는 핫도그 ㅋ

'Mobile ' 카테고리의 다른 글

[여행-신도림] 디큐브시티 뽀로로 파크 방문기  (1) 2013.10.23
자연 캠핑장 - 과천  (1) 2013.10.08
서울 대공원 - 동물원  (0) 2013.10.05
1. Process Management : Namespace 내용
   Namespace의 기본 개념을 번역함. 
   Namespace concept (Professional Linux kernel architecture)

2. namespace 실습
  // 검색을 해봤는데, 와닿을 만한 예제를 찾지 못했다. 검색어를 잘못 선정했나.. 
 // unshare() 함수 사용의 예제 임.

 Reference site : http://glandium.org/blog/?p=217

                        http://www.debian-administration.org/articles/628
 

unshare() system call로 새로운 namespace를 만들고 확인해보는 실습이다. 


위의 소스를 살짝 설명을 하자면, 
일단 unshare system call은 root permission이 없으면 수행을 하지 못한다.  현재 실행하고 있는 UID의 값이  root(UID == 0)가 아니면 실행을 중단한다. 
shell 에서 (geteuid 는 effective uid 값을 가져오는 함수임)
$ man 2 geteuid
하면 자세한 정보가 나온다. 

일단 root permission으로 실행되었다면, unshare system call에 CLONE_NEWNS flag와 함께 호출한다. 새로운 namespace를 생성하는 과정임(현재 process에서 fork 하여 생성된 child process인 경우에만 아래의 코드를 실행한다.)
 
코드를 구현하고,
$ gcc -o newns newns.c (위의 소스 파일 이름이 newns.c 이다)

 
위의 terminal의 명령 순서를 설명하면,
나의 경우에 ~/work/namespace/ 하위에 first와 second file을 만들고 각각 first 에는 "FIRST" 문자열을 second 에는 "SECOND" 문자열을 기록 해두었다.

$ sudo ./newns 를 통해 새로운 namespace를 만들고
$ mount -n --bind second first

(참고로, mount 의 --bind 옵션은 심볼릭 링크 파일을 파일로 인식하는 FTP 에서 링크 대신 마운트를 시킴으로써 링크와 비슷한 역할을 할 수 있도록 하는 것이다.)

$ cat first

first 파일의 내용을 보면 "SECOND"라고 나온다. 하지만 또 다른 터미널을 하나 더 연 다음에,
같은 디렉토리로 이동 후 같은 파일의 내용을 보면,

<another terminal>
$ cat first
FIRST
라고 나온다.

Namespace의 간단한 예제 이며, 조금 더 참고하거나 해볼 만한 예제가 있다면 올리도록 할 것이다.  

VMware Server version을 깔고 screen size 조정 및 vmware와 host 간에 copy & paste(사실 이게 가장 불편하다.) 같은 것들이 되려면, vmware-tools를 설치해야 한다. 
OS 는 ubuntu 10.10 이다.

그럴려고 install vmware tools 를 클릭해서 CD가 mount되면 VMware...tar.gz 를 복사하고 압축불면, 인스톨 script를 실행한다. 물론, 

 
https://help.ubuntu.com/community/VMware/Server 이 사이트를 참조해서 kernel header 설치를 해주었다. 
 $ sudo apt-get install build-essential linux-headers-`uname -r`
하지만,
The directory of kernel headers (version @@VMWARE@@ UTS_RELEASE) does not match
your running kernel (version 2.6.35-22-generic). Even if the module were to
compile successfully, it would not load into the running kernel.
 
에러가 뜨길래, /usr/src/ 디렉토리를 보니, linux-headers-2.6.35.22 와
linux-headers-2.6.35.22-generic 만 있었다. 그래서 install tool이 요구하는데로 /usr/src/linux/include 를 맞춰주기 위해 위의 디렉토리를 linux로 링크 해줬다. 물론 /usr/src/ 하위에 디렉토리는 결국 같은 거니깐,
$ cd /usr/src $ sudo ln -s /usr/src/
headers-2.6.35.22-generic linux
를 해줬음에도 불구하고 또!!! error가 나는 것이다. 검색을 하다보니, VMware workstation 7.1.3 버전 부터는 알아서 해준다는 말이 있긴한데 더 검색을 해보았다.
다른 해결책이 있었다. ubuntu 10.10 을 설치했다면, apt-get 으로 vmware tools를 설치 할 수 있는 것이다. ㅋ
명령어는,  $ sudo apt-get install --no-install-recommends open-vm-dkms $ sudo apt-get install open-vm-tools $ sudo reboot
요렇게 해주면, vmware에서 내가 가장 원하던 copy & paste 가 잘된다!  

'Development Tip' 카테고리의 다른 글

Android git mirror site  (0) 2011.09.30
Per-process Namespace  (0) 2011.03.16
Kernel source 보는 방법(site 및 tool)  (0) 2011.02.24
Eclipse Git Repository Plugin (Egit)  (0) 2010.12.31
Free Repository 제공 사이트 소개(SVN, Git)  (0) 2010.12.30
내용이 하나의 글로 하기엔 너무 길어기 때문에, "Concept", "Implementation" 등으로 구분하여 쓰고, 관련 실습을 추가할 예정이다. 

2.3.2 Namespaces
 Namespace는 하나의 수행되는 시스템에 서로 다른 관점을 제공하는 것처럼 하는 lightweight 한 가상화의 형태를 제공하는 것이다. 이 매커니즘은 FreeBSD 의 jail 이나 Solaris의 zone과 비슷한 것이다. 

Concept
 전통적으로, Unix 계열의 시스템 뿐만아니라 Linux에서는 시스템이 가지고 있는 많은 자원을 전체적으로 관리한다. 예를 들어, 시스템에 있는 모든 process들은 그것들이 가지고 있는 PID 숫자로 확인되며, 이 PID 리스트는 커널에서 관리되어야 한다. 마찬가지로, uname system call로 반환된 시스템에 관한 정보는(kernel에 관한 약간의 정보와 system의 이름을 반환) 호출한 모든 사용자가 같은 값을 볼 수 있을 것이다. User ID 또한 이와 비슷한 방법으로 관리된다 : 각 user는 시스템에 유일한 UID 값을 가진다. 

uname -r : kernel version 확인
uname -a : system 정보 및 kernel 정보

User 의 ID는 kernel이 선택적으로 특정 권한에 대한 행동을 승인 혹은 거부를 한다. UID 0을 가진 root user는 기본적으로 모든 명령 및 행동이 가능하지만 0 이상의 값을 가진 UID는 제한적 기능만을 제공한다. PID n 의 값을 가진 user가 있다면, 자신의 pid n과 다른 m의 user가 실행 시킨 process는 시스템에서 제거할 수 없다. (ps -ef 명령으로 각 process의 pid와 uid를 확인할 수 있다). 물론 ps 명령어로 다른 사용자가 실행한 process는 확인 가능하다. User N은 다른 User M이 이 시스템에 활성화(사용하고 있는지)가 되어 있는지 볼 수 있다. 이것은 사용자가 자신이 가지고 있는 process들만 가지고 놀 수(?) 있는 한 다른 사용자가 가지고 있는 process를 관찰하는 것까지 막을 필요가 없기 때문에 아무 문제가 되지 않는다. 

 그러나 위의 경우를 원치 않은 경우가 있다. web 공급자가 고객들에게 Linux 시스템에 root 권한을 비롯한 모든 접근 권한을 주는 경우를 생각해 보자. 그렇다면 web service를 제공하는 고객들 한명당 하나의 linux 머신을 제공해야 하기 때문에 엄청난 비용이 든다. 그래서 KVM이나 VMware같은 가상화 환경으로 제공하면 이같은 문제를 해결 할 수 있지만, 이 가상화 방법은 시스템의 자원을 원할하게 분배하지 못하는 단점이 있다. 가상화 시스템은 각 고객들에게 분리된 kernel을 제공해야하는 것이 요구되며, 각 가상화 머신에 리눅스를 각각 설치를 해주고 설정을 완료해 줘야 한다. 

 다른 해결책으로는 namespace를 통해 가상화보다 적은 자원을 들여 같은 서비스를 제공할 수 있다. 하나의 물리적인 머신에 여러 커널을 수행하는 가상화 시스템(물론 서로 다른 운영체제를 수행하는데는 이 방법이 더 좋다)을 제공하는 대신에 하나의 물리적인 머신에 하나의 커널이 수행되고 namespace내부에 미리 모든 시스템의 자원을 추상화 해놓는 것이다. 이것은 하나의 container 에 process 그룹을 넣어두고 다른 container(물론 여기도 process 그룹이..)와는 완벽히 분리 해놓은 것이다. 이러한 분리는 하나의 container에 묶인 사용자들이 다른 container로의 연결을 할 수 없다. 그렇지만 container가 유지되는 동안 특정 경우에 다른 container와 공유하기 위해 그 container의 분리를 느슨하게(?) 할 수 있다. 예를 들어 container안의 PID 의 셋을 가지고 운영되지만, 서로 다른 container와 filesystem의 부분은 여전히 공유 될 수 있다. 

Namespace는 기본적으로 시스템의 다른 view를 생성한다. 모든 이전에 생성된 자원은 container data 구조체로 싸여져 있어야 하고 자원의 리스트 셋과 namespace에 포함하는 내용은 시스템 내부에서 유일해야 한다. 주어진 container 안에서 그 자원이 충분히 활용하고 있지만 외부에 그 자원의  고유 identity(예를 들어 PID, 아래의 예제확인)를 제공하지 않는다. (내부에서만 사용하고 운영한다는 얘기인듯.) 그림 2-3이 상황을 개략적으로 볼 수 있다. 

//그림 2-3  --> 나중에...

세 개의 서로 다른 namespace가 시스템이 있다고 생각해 보자. namespace는 계층적으로 연결될 수 있다고 고려되었다. 하나는 parent namespace이고 이는 두개의 child namespace를 생성했다. 이 container들은 각각 하나의 linux 머신에서 제공되는 것처럼 보이도록 하여 web 호스팅 설정을 할 수 있게 제공한다고 가정하자. 각 container에서는 각각 pid 가 0 인 init task를 가지고 있어야 하며 오름차순으로 생성된 다른 task들을 가지고 있어야 한다. 두 child namespace 내부에는 init task(PID == 0)인 것과 2, 3의 pid를 가지는 task가 있다.(그림 2-3) PID 값은 하나의 시스템에서 고유의 값을 가지므로 이런 식으로 container 내부에서 가지는 pid의 값은 시스템 전체에서 고유의 값이 될 수 없다. 

child container는 시스템의 다른 container에게 자신의 상태를 알려주거나 연결이 되지 않기 때문에 parent container에서 child 관련 정보를 취급해서 child 내부에서 실행되는 모든 process를 볼 수 있어야 한다. 그림 2-3 에서 parent 4~9번 process는 child의 process와 대응되어 있다. 비록 시스템에는 9개의 process들이 있는 것이지만 4~9번의 PID를 가진 process는 하나 이상의 PID를 가지기 때문에 실제적으로 15 개의 PID가 요구된다. 

Namespace는 만약 간결한 분량의 container를 포함하는 경우 비계층적 구조(위의 계층적 구조와는 다른)를 가질 수 있다.(UTS Namespace의 예제를 보면서 확인하자)

꽤나 오래전에 linux는 chroot 시스템 콜을 이용한 간단한 형태의 namespace를 지원하고 있었다.  이 방법은 filesystem의 특정 부분을 동작중인 process들이 root 디렉토리로 인식함으로써 설정된 디렉토리 밖에서 접근 하지 못하도록 진행하는 것이어서 이것 또한 namespace의 한 형태라고 볼 수 있다. 하지만 진정한 namespace는 단지 filesystem을 제어하는 것 이외에도 많은 것을 컨트롤 할 수 있도록 만들어 주는 것이다. 

namespace를 만드는 방법은 두 가지가 있다. 
1. 새로운 process가 fork나 clone 시스템 콜로 생성될 때, 특정 option으로 parent process와 namespace가 공유될 수 있도록 만들어 질 수 있다. 또는 새로운 namespace 가 생성될 수 있다. 

2. unshare 시스템 콜로 parent 로 부터 생성된 process를 분리하고 새로운 namespace를 할당 할수 있다. manual page 를 확인 하자(unshare(2))

관련 자료를 검색 중 찾은 간단한 예제로 확인해 보자

http://woodz.tistory.com/23 <-- namespace 의 간단한 실습 내용.
2.3.1 Process Types
 일반적인 Unix process는 binary code로 구성되고 chronological(연대순의, 번역하기가 어려운 단어라..) thread (컴퓨터는 한시점에 코드를 통해 한시점에 하나의 경로로 실행하는 의미의 말) 그리고 application에게 할당된 자원의 셋(메모리, 파일 등)을 가진 것이다. 새로운 process들은 fork exec 시스템 콜의 조합으로 생성된다. 

fork 는 현재 process를 복제하여 생성한다. 이 복사본은 child process라 불린다. 원래의 process의 모든 자원은 적절한 방법으로 복사되어 시스템 콜 이후에 최초 process의 독립적인 두개의 객체가 있게 된다. 이 객체들은 어떤 방법으로 연결되어 있진 않지만, 열린 파일, 같은 작업 디렉토리, 메모리의 같은 데이터(data의 복사본을 각각 가지고 있게됨) 등을 가지고 있다. 

exec 는 수행중인 process를 실행 가능한 binary 파일로 부터 다른 application 을 로드한다. 결국 새로운 program을 로드한다는 말이다. exec 은 새로운 process를 생성하지 못하기 때문에 fork 시스템 콜로 process를 새로 복사한 후, 시스템에 추가적인 새로운 application을 생성하기 위해 exec을 호출한다. 

Linux는 위 두개의 system call 이외에 추가적인 clone 시스템 콜을 제공한다. 원칙적으로는 clone 은 fork와 같은 방식으로 구동된다. 하지만 새로 생성된 process는 그것의 parent process와 완전히 독립적이지 않으며 parent와 몇몇 자원은 공유한다. 이 시스템 콜은 어떤 자원은 복사되고, 어떤 자원은 공유하게 하는지에 정의가 가능하다.-예를 들면, memory에 있는 data, 열린 파일들, signal handler등이 있다. 

clone은 tread를 구현할 때 사용된다. 그렇지만 thread를 수행하기 위해서는 이것만 가지고는 할 수 없다. user level에서 완전히 실행되기 위해서는 라이브러리들이 필요하다. 예를 들면, Linuxthreads Next Generation Posix Threads와 같은 라이브러리 들이다. 
검색하여 찾다보니, 얻은 내용

이걸 참고하여 적용해봤더니 일단 글에 블럭은 잡히지 않아 좋다. ^^

'BlogTip' 카테고리의 다른 글

Google 애드센스 신청 TIP  (2) 2013.10.16
Ubuntu 에서 우 클릭(Right-Click) 메뉴 screen shot  (0) 2012.02.20
Tag Cloud 만들기  (0) 2010.12.22
Syntax highlight test  (1) 2010.12.14
아이 엠 넘버 포
  • 운명에 맞서지 않는 한
    이번이 내가 죽을 차례다!

    할리우드 최고의 흥행사들이 격찬한 최고의 스토리
    <.. 더보기
이미지 출처 : 다음 영화

가끔 보는 영화를 포스팅 시작을 하기 위해 혹시 모를 저작권에 관련해서 찾아보니, 영화 포스팅에 스틸컷이나 포스트를 넣어도 되는 건지 안된다는 건지 정확히 알수가 없었다.

검색을 하다 보니, "다음 영화"에서 영화 검색 후 퍼가기 기능으로 블로그에 써본다.(이건 확실 한듯, 이미지가 좀 작고 스틸컷을 올리지 못하는 아쉬움이 있지만...) 

퍼가기 방법을 써 주신 블로그 : http://wezard4u.tistory.com/804 

아, 영화는 재미있었다.(평점도 괜찮고 실제로 봤을 때 재미도 있었지만, 그 시간에 같이 영화를 보는 사람이 별로 없었다. 인기없는 극장이라 그런가? ㅋ) 액션 신도 멋있고 이런 영화류를 내가 좋아해서 그런걸지도..(이 세상에 존재 할 것 같지 않은 능력을 쓰는 영화들을 좋아하는 편이다)

주인공의 생김세와 능력은 "영화 푸쉬(2009)"에 나온 "무버" 의 능력에 추가 기능(?)이 있는 듯하다.
(능력은 물건을 마음대로 옮기거나 공격을 막는 등-소위 염력..) 이젠 초능력자들의 기능(?)은 "Heros"나 다른 기타 영화에서 다 정립이 된듯. ㅋ 사실 예고편을 봤을 땐 왠지 기존에 봤던 능력과는 다른 느낌이었는데... 

영화에서 중반에는 조금 지루한 감이 없진 않았으나 대체적으로 만족스러운 영화였다. 중반에 자신의 능력을 하나하나 알아가는 과정은 부드러웠으나 외계인에게 아버지를 납치당한 친구녀석의 동행과 사랑의 감정을 느끼는 여자와의 관계의 과정중의 일부가 살짝 빠진 듯한 느낌이 있었다. 나머진 좋은 액션, 긴장감을 느낄 수 있어서 좋았다. 그리고 마지막엔 다음편을 기다하게 하는 다른 "번호"의 친구들을 찾아 나서는데..(6번은 이미 만나 함께하면 능력이 배가 된다는 걸 알게됨) 

마지막 장면을 보고 나오는데, 갑자기 예전에 본 "에라곤(2006)"이 생각났다. 영화를 보고 나서도 재밌게 봤던 영화라 케이블의 영화채널에서 나오면 다시 보곤 했었다. 근데 이 영화도 마지막에 막판 보스가 자신의 소중한(?) 부하를 잃고 전쟁에서 지자 분개하며 끝났었는데.. 난 바로 다음해에 2편이 나올 줄 알았다. 기대도 하고 있었고. 
근데 5년이 지난 지금.. 아직도 소식이 없으니 답답할 노릇이 아닐 수 없다. 

왠지 다음 후속편이 나올 것 같은 기대를 주는 영화가 다음편이 안나온다면 내가 너무 재미있게 봐서 그런가 하는 고민에 빠질 수 있지 않을까? ㅋ 


'Etc.' 카테고리의 다른 글

Youtube streaming 을 PC 로 download  (0) 2012.08.09
Ubuntu Video 가 푸르게(blue)로 나오는 현상 제거  (0) 2012.08.09
Ubuntu 12.04 Upgrade 이후 client error  (0) 2012.05.01
Christmas 분위기???  (0) 2010.12.22
Best Diff Tools  (0) 2010.12.22
1. Linux Cross Reference site 이용
 
사이트에 접속하면 빨간 박스를 클릭하여 최신 버전의 소스 최상위로 진입할 수 있다. 

선택후, 

빨간 동그라미 부분을 클릭하면 버전별 소스 트리를 선택할 수 있다. 일단 2.6.37.1 최신버전을 선택
그리고 바로 옆 search 박스에서 테스트로 "task_struct" 를 입력하고 search 버튼을 누른다. 

찾은 "task_struct" 두가지로 분류되어 있다. "Extern or forward variable declaration"(위의 그림) 과 "Structure"(아래 그림)
include/linux/sched.h 를 클릭하여 소스를 보도록 하자.

위와 같이 소스를 볼수가 있다. include file이나 각종 변수 및 선언된 내용(파란색 글)은 모두 클릭하여 연결된 소스를 웹에서 볼수가 있다. 

2. Program의 이용
분석툴로는 Linux 에서는 vim + ctags + cscope 방법과 Window에서 사용하는 SourceInsight 가 있다.(물론 유료버전임.. 30일 무료버전을 다운받아 사용해보는 것을 추천한다.) 

이미 내용을 잘 써놓은 블로그가 검색하면 쫙 나오기에.. 검색해보고 찾은 것중 참고할 만한 글을 링크합니다. 

a. http://sosal.tistory.com/11 커널 분석기(vim+ctags+cscope) 정리한 블로그 입니다. 
b. sourceInsight 사용법 : http://wizlog.net/60 (시작하기에 좋은 참고 블로그입니다.)
  - 한글 주석 입력방법 : http://jany.tistory.com/47

3. Get Linux Kernel Source
Web Browser : www.kernel.org
빨간 박스는 최신버전을 바로 다운로드 할 수 있는 링크임.

국내 미러 사이트의 주소는 
여기서 v숫자(ex. v2.6) 를 클릭하여 들어가면 관련 버전의 소스를 다운받을 수 있다. 

Console에서는 
wget을 이용한다.(없으면 설치해야함. ubuntu는 "sudo apt-get install wget" 하면됨.

$ wget -c http://<mirror site>/pub/linux/kernel/v2.6/linux-<version>.tar.bz2

version은 linux-2.6.23.7.tar.gz 이런 식으로 입력하면 됩니다. 
Chapter 2, Process Management and Scheduling


2.3 Process Representation
Process와 program에 관련된 Linux Kernel의 모든 알고리즘은 include/sched.h 에 정의되어 있는 task_struct 라는 data 자료구조 내부에 있다. 이 자료구조는 시스템의 중심적 역할은 하는 것들 중에 하나이다. scheduler의 구현부를 다루기 전에, 이 기본적인 자료구조를 알아야 한다. 

task 구조체는 많은 process를 연결하는 요소들을 포함하고 있다. 구조체 내부의 요소들을 잘 알지 못하고는 차후에 나오는 내용을 이해시키기는 어려울 것이다. 

task 구조체는 다음과 같이 정의되어 있다.

task_struct 소스 내용을 모두 넣는 것이 쓰는 사람도 읽는 사람도 불편할 것이니 다른 방법을 사용한다. 물론, 필요한 부분은 넣어야겠지..


task_struct 의 링크는 
이다. 링크에서 보는 바와 같이 2.6.37.1 version 의 소스이다. 책의 내용과 조금 차이가 있을 수 있다. 

소스를 보면 알겠지만, 이 구조체의 많은 정보를 다 소화하기란 어려운 일일 것이다. 그렇지만, 이 구조체를 process의 특정 한 상태를 표현하는 등의 부분 부분으로 나누어 본다면 조금 수월할 것이다. 

Process 상태 및 실행 정보 : 지연된 signal, 사용된 binary 포멧(또한 다른 시스템의 binary 포멧을 위한 emulation 정보 등), process ID(pid), 자신의 부모 process 및 관련 process의 연결 포인터, 우선순위 값, 마지막으로 program을 실행한 시간 정보(CPU time)

□ 할당된 가상 메모리(virtual memory) 정보

process 자격 : user ID, group ID, process가 특정 명령을 수행할 권한 정보 등. System call 을 통해 process 정보등을 확인 하고 변경할 수 있다. 

사용된 file : program code를 포함하는 binary file 뿐만 아니라 process가 다루는 모든 file의 filesystem 정보는 저장해야한다. 

□ Thread 정보, process의 CPU 관련 runtime data 를 기록하게 됨.(그 외 남은 구조체의 field 는 사용된 하드웨어와 의존적이지 않다 - stack 정보같은 것인듯.)

□ 다른 process와 함께 같이 작업할 때, Process간 통신(Interprocess Communication)에 대한 정보

□ process가 signal에 응답하기 위해 등록한 signal handler

task 구조체는 간단하게 값들이 구성되어 있지 않다. 각종 data를 연결하기 위한 포인터 등으로 구성되어 있다. 중요한 변수들 몇몇을 자세히 설명해본다. 



state 는 process의 현재 상태를 기술한다. (volatile long으로 선언됨) 

TASK_RUNNING : Task가 수행 가능한 상태이다. 이것은 실제 CPU에 할당되어 수행중이라는 것은 아니다. scheduler에 의해 선택될 때까지 이 task는 기다릴 수 있다. 이 상태는 process가 실행 가능한 상태이며 외부 event를 기다리고 있지 않다는 것이다. 

TASK_INTERRUPTIBLE : 어떤 event를 기다리는 잠자고 있는(sleeping) process를 위한 설정이다. 기다리던 event가 발생하게 되면, 이 상태는 TASK_RUNNING 으로 변경되면 scheduler에 의해 선택되면 바로 실행이 가능하게 된다. 

TASK_UNINTERRUPTIBLE : kernel의 명령으로 잠들어 있는 process를 disable 시킨 상태. kernel이 직접 해제하지 않는다면, 외부 signal에 의해 깨어나 수행할 수 없다.

TASK_STOP : process가 특정목적을 위해 멈춰있는 경우이다.(예를 들면, debugger의 break point에서 멈추게 함.)

TASK_TRACED : 이 process의 상태는 ptrace 매커니즘을 이용해 process가 특정 시점에서 trace되고 있는 상태로 일반적인 STOP 된 task와 구별하기 위함이다. 

이 다음에 나오는 상수는 종료되는 process의 상태를 나타내준다. 이것은 exit_state 항목에 저장된다.
EXIT_ZOMBIE : 2.2 에서 설명된 zombie 상태를 나타낸다.

EXIT_DEAD : 시스템에서 완전히 제거되기 전에 parent process에서 알맞은 wait system call을 호출한 뒤의 process 상태. 이 상태는 하나의 task 안에서 여러 개의 thread가 수행될 때 중요하게 사용되는 상태이다. 

Linux는 process의 시스템 resource 사용 제한을 위해 resource limit (rlimit) 메커니즘을 제공한다. 이 메커니즘은 task_struct 안에 signal 구조체 포인터가 있다. process signal 관리를 위한 구조체 내부에 rlim이라는 배열이 존재한다. ( 아마 책에는 task_struct 내부에 rlim 배열이 있다고 하는데, 소스를 보니 task_struct --> singal_struct *signal-->struct rlimit rlim[] 로 되어 있다.)

rlimit 구조체는 include/linux/resource.h 에 정의되어 있다. 

이 정의(definition)은 다른 많은 resource를 수용하기 위해 매우 일반적으로(?) 유지된다. 
rlim_cur : process의 현재 자원 제한. 이것은 soft limit 로 참조된다.
rlim_max : process가 허가된 최대 자원의 제한. 이것은 hard limit 으로써 참조된다.

setrlimit system call은 현재 자원제한을 증가시키거나 감소시키는데 사용한다. 그렇지만 이 값은 rlimt_max 값을 초과할 수 없다. getrlimit system call로 현재 limit 값을 확인 할 수 있다. 

이 제한적인 자원은 rlim 배열의 index로 자신의 위치를 확인 할 수 있는데, 이것은 kernel에서 상수값으로 미리 정의를 해두어 연결된 자원과 배열의 위치를 연결했다. Table 2-1을 보면 정의된 상수와 그것의 의미를 기술했다. System programming 책을 보면 자원 제한관련 예제 및 더 상세한 내용을 볼 수 있다. 또한, setrlimit(2) man page를 봐도 조금 더 자세한 내용을 볼 수 있다. 

 Linux 는 특정 유닉스 시스템과 binary 호완성을 제공하기 위한 노력을 해왔기 때문에 아키텍쳐 마다 상수의 값들은 서로 다를 수 있다.

limit은 kernel의 매우 다른 부분과 연관되어 있기 때문에, kernel은 반드시 대응되는 하위 시스템의 limit 값을 확인해야 한다. 

만약 resource type이 limits(거의 모든 자원의 기본 설정임) 설정 없이 사용되었다면, RLIM_INFINITY 의 값으로 rlim_max 가 설정된 것이다. 예외적으로 사용된 경우를 보자, 
□ 열린 파일들의 수(RLIMIT_NOFILE, 기본적으로 1024로 제한한다.)
□ 사용자가 가질 수 있는 process의 개수(RLIMIT_NRPROC)은 "max_thread / 2"로 정의한다. 여기서 max_thread는 global 변수이며, 가용한 RAM의 1/8이 thread 정보를 관리하는데만 사용하고 20개의 thread가 최소의 메모리만을 사용하도록 thread의 생성 개수를 정의한다. (이문장은 번역에 어려움을 겪어 최대한으로 부드럽게 하려고 노력하였음.)

init task를 위한 부팅 때 자원 자한은 include/asm-generic-resouce.h 안에 INIT_RLIMTS 로 정의되어 있다. 

각 process의 proc filesystem을 통해 rlimit 값을 확인 할 수 있다. 
현재 나의 system 정보는 : VMware Server 2.0.1에 Ubuntu 10.10을 설치했다. 10.10의 kernel version은 2.6.35-22 다. 
rlimit 값을 확인 하기 위해, 

proc/self/limits 파일을 읽었다. proc file system의 self 라는 file은 symbolic link 이며 현재 수행중인 process를 가르키고 있다. 

Table 2-1: Process 관련 자원 제한. 
 상수  의미
 RLIMIT_CPU  최대 할당 할 수 있는 CPU 시간
 RLIMIT_FSIZE  사용할 수 있는 file 최대 크기
 RLIMIT_DATA  data segment의 최대 크기
 RLIMIT_STACK  (user mode) stack의 최대 크기
 RLIMIT_CORE core dump file의 최대 크기 
 RLIMIT_RSS  Resident Size Set 의 최대 크기; 다른 말로는 process가 사용할 수 있는 
최대 page frame의 개수이다. 현재 사용되지 않은 것도 포함함.
 RLMIT_NPROC  실제 UID 에 연관된 사용자가 하나의 process를 가지고 생성할 수 있는
process의 최대 개수(fork의 제한 인듯) - 조금 더 알아봐야 할듯.
 RLIMIT_NOFILE  하나의 process가 제어할 수 있는 파일의 개수(open files)
 RLIMIT_MEMLOCK  swap 되지 않도록 할 수 있는 page 의 개수
 RLIMIT_AS  하나의 process가 차지할 수 있는 가상 주소 공간의 최대 사이즈
 RLIMIT_LOCKS  file lock의 최대 개수
 RLIMIT_SIGPENDING  지연된 signal의 최대 개수
 RLIMIT_MSGQUEUE  message queue의 최대 개수
 RLIMIT_NICE  non-real time process들을 위한 최대 nice 레벨
 RLIMIT_RTPRIO  real time 우선 순위의 최대치.




Chapter 2, Process Management and Scheduling


2.2.1 Preemptive Multitasking
 Linux process 관리 구조를 알기 위해서는 process 실행의 두가지 모드를 알아야한다.(kernel mode와 user mode) 요즘 출시되는 CPU들은 최소한 두가지 다른 실행 모드가 존재하며, 한가지는 제한이 없는 권한을 가지고 실행되며 다른 한가지는 다양한 제한이 걸려있는 상태로 실행된다는 것이다.(제한이 있다는 것에 예를 들면, 특정 물리 메모리 영역을 접근하는 것 등이 될 것이다.) 이런 구분은 시스템의 어떤 한 부분을 간섭하는 것을 보호하고 시스템에 존재하는 process들을 잡아(?-다른 process들에게 넘어가거나 접근하는 것을 막는다는 뜻인가) 둘수있는 잠겨진 "새장과 같은" 것을 생성해줘야 한다. 

일반적으로 kernel은 자신이 가지고 있는 data 만 접근 가능하고 시스템에 있는 다른 application에게 간섭할 수 없는 user mode 안에 있다.(이 부분은 무슨 말인지 써놓고 무슨말인지 확실치 않다.)

만약 한 process가 system data나 함수들의 접근을 원한다면(후자는 모든 process들 사이에 공유된 자원을 관리한다, 예- filesystem 영역) 반드시 kernel mode로 변경하여 수행해야 한다. 물론 kernel mode에서 통제되고(만약 그렇지 않으면, 현재 만들어진 보호 매커니즘이 모두 불필요해지는 것이다. ) 명확히 정해진 루틴으로 실행되어야 한다. 이와 같은 것은 system call 이라는 특별한 함수를 통해 이루어진다. 자세한 사항은 13장에서 더 자세히..

user mode로 부터 kernel mode로의 전환은 interrupt에 의해서도 일어난다.(이것은 interrupt 발생시 자동으로 전환된다.) user application에서 의도적으로 호출되는 system call(system data나 함수를 이용 목적을 위해)과는 달리 독단적(?)으로 수행된다. -의도되지 않은 상태에서 발생함- interrupt의 발생은 현재 process실행과 무관하게 처리해 줄 수 있어야 한다. 예를 들면, 외부 블럭(block) 장치에서 요청한 data를 RAM 으로 복사 완료되면 이 data가 시스템의 어떤 process를 위한 것이었던 간에 interrupt는 발생하게 된다. 비슷하게, network 장치에서도 interrupt를 통해 data package 도착을 알려주게 된다. 반면, network으로 들어온 package는 interrupt를 받아 처리함에 있어 그 data는 현재 수행되고 있는 process에게 전달 된다.(외부 블럭 예제와는 다른 경우 인 것이다.) Linux는 interrupt를 다르게 처리를 하지만, 수행되고 있는 process들은 이같은 상황을 모르고 자신의 작업을 진행한다. 

Kernel의 선점 scheduling 모델은 어떤 상태의 process가 interrupt를 받는지에 대한 구조를 만들어 두었다.

□ Normal Process는 항상 interrupt를 받을 수 있다.(다른 process에 의한 interrupt 발생조차도 다 받는다). 중요한 process(오랫동안 keyboard 입력을 기다리는 편집기 등)
가 실행 상태가 되면 scheduler는 즉시 실행 할 것인지에 대한 결정을 내린다. 현재 그 process가 수행중일 때도 그 같은 고려를 한다. 이와 같은 선점은 시스템의 응답시간을 높이는데 중요한 역할을 했다.

□ 만약 kernel mode에서 system call을 수행하고 있을 때, 어떤 process도 CPU 사용을 취소할 수 없다. 즉, scheduler는 다른 process를 선택하기 이전에 system call의 수행을 완료를 해야한다는 것이다. 하지만 system call은 interrupt에 의해 잠시 보류될 수 있다. 

□ Interrupt는 user mode와 kernel mode에 있는 process들을 중지할 수 있다. 그것은 interrupt가 발생한 시점 부터 가능한한 빨리 처리해야 하는 중요한 것이기 때문에 가장 높은 우선순위를 가진다. 

Kernel 선점은 2.5 버전 개발을 진행하면서 선택사항으로(make menuconfig 수행된 메뉴) 추가되었다. 이 선택사항(option)은 kernel mode에서 system call을 수행 중일 때에도 급히(?) 처리해야 하는 다른 process가 생기면 교체될 수 있는 기능인 것이다.(물론 interrupt 핸들러가 수행중일 때는 불가하다.) 비록 kernel이 system call을 최대한 빨리 수행을 마쳐야 함에도 불구하고(빨리 수행해야하는 이유는 scheduler가 system call을 마무리 하여 다른 process의 수행권을 보장하고 진행하기 위함) 신뢰성있는 어떤 application들은 일정한 data 스트림을 요구하여 많은 시간이 필요하게 되는 경우가 있다. kernel 선점은 이와 같은 대기 시간을 줄이고 부드러운(?) program 실행을 가능하게 한다. 하지만 선점 기능은 하나의 CPU를 가진 시스템에서 병렬적인 접근이 많아지고 이것을 보호하기 위해 많은 data structure가 요구되기 때문에 증가된 kernel 복잡성으로 비용이 증가하게 된다. (향후, 2.8.3 장에서 자세히 다룬다.)

+ Recent posts