'Embedded Lab/linux, x86'에 해당되는 글 108건

  1. 2012.01.26 [9장 커널 동기화 방법]
  2. 2012.01.26 [8장 커널 동기화 개요]
  3. 2012.01.26 [Top-Half와 Bottom-Half]
  4. 2012.01.11 [인라인(inline) 함수]
  5. 2012.01.11 [커널의 종류]
  6. 2012.01.04 [프로세스의 상태 정리]
  7. 2012.01.04 [Slab Allocator]
  8. 2012.01.03 [커널컴파일]
  1. 원자적 동작(Atomic Operation)

    • 중단됨이 없이 한번에 실행되는 명령. 원자(Atom)가 더 이상 쪼갤 수 없는 원소를 의미하듯 원자적 동작은 나눠지지 않는 명령등을 의미한다.
  2. 원자적 정수연산, 원자적 비트연산

    • 원자적 정수연산은 특별한 자료구조인 atomic_t를 사용한다.

      1. 원자적인 함수들이 다른 자료형에 잘못 사용되는 것을 방지.
      2. 원자적동작이 엘리어스(alias)가 아닌 실제 메모리 주소를 사용하게 한다.
      3. 컴파일러가 이 자료형으로의 접근을 잘못 최적화하지 않도록 방지.
      4. 아키텍처에 따라 다른 구현을 감춰주는 역할.
    • 커널코드 작성시 모든 아키텍처에서 사용가능한 함수를 확인해 보아야 한다.
  3. 스핀락(Spin Lock)

    • 최대한 하나의 스레드에 의해 잠길 수 있는 락을 말한다.

      1. 만약 어떤 스레드가 이미 잠겨진 스핀락을 다시 잠그려 시도한다면 그 스레드는 루프(Busy Loop)를 돌면서(Spin)락을 잠글 수 있을때 까지 기다린다.
      2. 이러한 스피닝(Spinning)은 동시에 하나 이상의 스레드가 같은 위험구역에 진입하는 것을 방지해 준다.
    • 다른 스레드들을 스핀하도록(프로세스 시간을 소모함) 하므로 두번의 컨텍스트 스위칭 시간보다 짥게 잡고 있도록 하는 것(휴면방식을 사용하는것) 이 중요하다.
    • 프로세서가 하나인 시스템 에서도 인터럽트 핸들러가 공유 데이터를 접근하는 것을 방지하기 위해 인터럽트를 비활성화해야 한다.
    • 실제로 보호가 필요한 것은 코드 자체가 아닌 위험구역 안에 있는 데이터이므로 락을 특정한 데이터와 관련시키는 것이 좋다. "struct foo 는 foo_lock 으로 잠김"
  4. 스핀락과 보톰하프(Bottom Half)

    • 보톰하프는 프로세스 컨텍스트 코드를 선점할 수 있으므로, 만약 어떤 데이터가 보톰하프와 프로세스 컨텍스트간에 공유된다면 락을 사용함과 함께 보톰하프를 비활성화시켜 데이터를 보호해야 한다.

      • 프로세스 컨텍스트란 ? 프로세서 고유 컨텍스트(Processor Specific Context) 프로세스는 시스템의 현재 상태의 총합 으로 생각할 수 있다. 프로세스는 실행될 때마다, 프로세서의 레지스터와 스택 등을 사용 한다. 이것이 프로세스 컨텍스트이며, 프로세스가 중단될 때 CPU 고유의 컨텍스트들은 모두 그 프로세스의 task_struct에 저장되어야 한다. 스케쥴러가 이 프로세스를 다시 시작할 때, 이 컨텍스트는 이 정보로부터 복구된다.
  5. Reader 와 Writer 스핀락

    • 리스트가 갱신(쓰기)되는 경우에는 다른 코드가 동시에 리스트에 쓰거나 읽지 않도록 해야 한다. 상호배제(Mutual Exclusion)가 필요하다.
    • 리스트를 탐색(읽기)하는 경우에는 다른 코드가 동시에 리스트에 쓰는 것만을 방지하면 된다. 쓰기작업이 없다면 동시에 여러 곳에 탐색이 가능하다.
    • 자료구조의 사용이 Reader/Writer로 확연히 구분되는 경우(생산자/소비자)에는 락킹 메커니즘은 Reader/Wrtier 스핀락을 제공한다.
    1. rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;
    2. read_lock(&mr_rwlock);
    3. /* 위험 구역(읽기 전용) */
    4. read_unlock(&mr_rwlock);
    5. write_lock(&mr_rwlock);

    6. /* 위험 구역(읽기, 쓰기 가능) */
    7. write_unlock(&mr_rwlock);
    • 대기중인 writer는 모든 Reader가 락을 해제할 때까지 락을 잠그지 못하게 되므로 리더가 상당 수 있는 경우 기아상태가 발생하게 될 수 있다.
  6. 세마포어

    • 락을 잡고 있는 시간이 길어지거나 락을 잡은 채 휴면해야 하는 경우에 사용한다.
    • 동작시나리오

      1. 어떤 태스크가 이미 잠겨진 세마포어를 잠그려 하는 경우, 세마포어는 그 태스크를 대기큐로 삽입하고 해당 태스크를 휴면 상태로 만든다.
      2. 프로세서는 다른 코드를 실행할 수 있게 된다.
      3. 세마포어를 잡고 있는 프로세스가 락을 해제하면, 대기큐에 있는 하나의 태스크가 깨어나서 세마포어를 잡게 된다.
    • 바쁜 루프로 시간을 소모하지 않기 때문에 스핀락보다 더 나은 활용도를 보여주지만 스핀락에 비해 세마포어는 훨씬 많은 부가작업이 필요하다.( 인생은 Trade-Off -_ㅡ;; )
    • 세마포어의 휴면 동작이 주는 의미

      1. 락을 기다리는 태스크들이 휴면하게 되므로 세마포어는 락을 오랫동안 잡게 되는 상황에 적합하다.
      2. 락을 잡고 있는 시간이 짧을 경우 휴면하고 대기큐를 관리하고 다시 깨워주는 추가작업들이 락을 잡고 있는 시간보다 길어질 가능성이 있다.(비효율적.)
      3. 스레드의 실행은 락 경쟁에서 휴면 상태가 될 수 있고 인터럽트 컨텍스트는 스케줄이 불가능하기 때문에 세마포어는 오직 프로세스 컨텍스트에서만 얻을 수 있다.
      4. 세마포어를 잡은채로 휴면할 경우 다른 프로세스가 같은 세마포어를 잡으려 하더라도 데드락에 빠지지 않는다.( 두번째 스레드 역시 휴면되므로 결국 첫번째 스레드가 실행)
      5. 세마포어를 사용할 경우 스핀락을 잡고 있어서는 안되는데, 왜냐하면 세마포어를 잡으려면 휴면해야 하는데 스핀락을 잡고 있는 상태에서는 휴면해서는 안된다.
    • 세마포어 VS 스핀락

      1. 락을 잡고 있는 시간을 근거로 결정을 내려야 한다.
      2. 세마포어는 커널 선점을 비활성화하지 않으므로 세마포어를 잡고 있는 코드는 선점될 수 있다.( 스케줄링에 불리하게 작용하지 않는다. )


        요구사항 추천
        락 부담이 적어야 하는 경우 스핀락
        락 기간이 짧은 경우 스핀락
        락 기간이 긴 경우 세마포어
        인터럽트 핸들러에서 락을 해야 하는 경우 반드시 스핀락(스케줄링)
        락을 소유한 채 휴면해야 하는 경우 반드시 세마포어
    • 세마포어는 동시에 여러 스레드가 같은 락을 잠글 수 있다. 선언시 그 숫자를 지정할 수 있다.

      1. 락의 갯수를 1로 지정하여 하나의 스레드만이 이 락을 잡을 수 있도록 한것을 바이너리 세마포어, 상호배제 관점에서의 뮤텍스라고 부른다.
      2. 카운팅 세마포어는 다수의 스레드가 동시에 같은 위험구역에 진입할 수 있도록 하므로 상호배제를 보장하지 않는다.
    • Reader-Writer 세마포어

      1. 모든 Reader-Writer 세마포어는 뮤텍스이다.
      2. Wirter 가 없는 한 다수의 Reader가 락을 소유할 수 있고 Reader 가 없는 상황에서 오직 하나의 Writer 만 락을 소유할 수 있다.
  7. 완료 변수( Completion Variable )

    • 커널의 두 태스크를 동기화시키기 위해 사용, 한 태스크가 이 변수를 통해 다른 태스크로 이벤트를 알려주는 식으로 동작한다.
    • 세마포어를 대신하여 간단히 사용하기 위해 제공되는 방법이다.
    • complete() 을 호출하여 완료변수에 시그널 되기를 기다리는 대기중인 태스크들을 깨어나도록 하는 방법.
  8. 큰 커널 락(BKL, Big Kernel Lock)

    • 특성

      1. 소유한 상태에서 휴면할 수 있다.
      2. BKL이 잠겨있는 경우 커널 선점은 비활성화 된다.
      3. 재귀적인 락이다.
      4. 오직 프로세스 컨텍스트에서만 사용가능하다.
      5. 이것은 필요악이다. 악마의 현신!!
    1. lock_kernel();
    2. /*
    3. 다른 모든 BKL 사용자들과 동기화되는 위험 지역..
    4. 여기서는 안전하게 휴면할 수 있으며, 휴면할 경우 락이 자동적으로 해제된다. 또 휴면했다가 다시 스케줄링되면 자동적으로 락을 얻는다.
    5. 즉, 어느 경우이든 데드락은 피할 수 있지만, 정말로 여기서 데이터를 보호할 생각이라면 휴면하지 말아야 한다.!!!!
    6. */
    7. unlock_kernel();
  9. seq 락

    • 공유 데이터를 읽거나 쓰기 위한 아주 간단한 메커니즘을 제공.
    • 많은 Reader와 적은 Writer가 있는 경우를 위한 매우 가볍고 확장성이 좋은 락이다.( Writer를 선호, 다른 Writer가 없을경우 항상 락을 잠글 수 있다. )
  10. 선점의 비활성화

    • 커널이 선점형이므로 새로 실행되는 태스크가 선점된 태스크와 동일한 위험구역에 진입할 수 있다 .그러므로 커널 코드는 스핀락을 사용하여 선점 불가능한 코드 구역을 표시해야 한다.
    • 하나의 변수가 프로세서에 고유한 변수라면 락이 필요치 않게 되지만 프로세서간 선점으로 인해 유사 동시적으로 접근될 수 있다.

      1. preempt_disable();
      2. /* 선점이 비활성화됨 ..*/
      3. preempt_enable();
      • 커널 선점을 비활성하여 한다.
  11. 오더링과 배리어

    • 프로그램 코드에 정의된 순서대로 행해야 하는 경우가 있다.

      • 하드웨어를 가지고 작업할 때는 어떤 읽기 작업이 다른 읽기나 쓰기 작업 이전에 행해져야 한다는 식의 요구조건.
    • 컴파일러와 프로세서 모두가 최적화를 위해 읽기/쓰기(인텔x86예외) 명령의 순서를 마음대로 뒤바꿀수 있기 때문에 별도의 방법이 존재한다.

      • 읽기와 쓰기 명령의 순서를 바꾸는 프로세서들은 명령의 순서 요구조건을 만족시킬 수 있는 기계어 명령을 제공한다.
      • 컴파일러에게 특정 지점에서는 명령어의 순서를 바꾸지 말도록 지시할 수도 있다. 배리어(Barrier) !!
    1. a = 1;
    2. b = 2;

      // 프로세서는 a보다 먼저 b에 새로운 값을 저장할 수도 있다. 컴파일러와 프로세서는 a와 b 사이에 어떠한 관련성이 있음을 알 수 없다.

    3. // a와 b사이에 명백한 연관이 존재하지 않기 때문에 재배열이 발생한다.
    4. a = 1;
    5. b = a;
    6. // a와 b사이에 명확한 데이터 의존성이 존재하기 때문에 재배열하지 않는다. a와 b사이에 명확한 데이터 의존성이 존재.
    • barrier() 함수를 통해 컴파일러가 로드와 스토어 명령을 최적화하는 것을 방지 할 수도 있다.
  12. 요약

    1. 원자적 연산 : 동기화를 담보하는 가장 단순한 방법.
    2. 스핀락 : 해당 락에 오직 하나의 보유자만이 존재할 수 있는 가벼운 락으로 경쟁이 발생하면 바쁜 대기를 수행한다.
    3. 휴면락 : 세마포어와 완료변수, seq락
    4. 경쟁상태를 유발하지 않으면서 훌륭한 동기화를 보장할 수 있는 커널코드를 작성하자!! 심플하게~!

      출처 : http://dblab.co.kr/category/Study/System?page=1 

'Embedded Lab > linux, x86' 카테고리의 다른 글

[VFS]  (0) 2012.02.15
[시너지]  (0) 2012.01.26
[8장 커널 동기화 개요]  (0) 2012.01.26
[Top-Half와 Bottom-Half]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
Posted by cyj4369
,
  1. 커널 동기화 ?

    • 메모리를 공유하는 응용 프로그램은 항상 동시적인 접근으로부터 공유된 자원을 보호해야 한다.
    • 다수의 실행중인 스레드가 동시에 데이터를 변경할 경우 다른 스레드가 변경한 부분을 또 다른 스레드가 잘못 덮어써버릴 가능성이 있다.
    • 멀티프로세싱, 선점형 스케줄링 환경에서는 다양한 동시성 문제가 발생할 수 있다.


  2. Critical Region(위험구역) and Race Condition (경쟁 상태)

    • 위험구역이란 공유된 데이터를 접근하여 조작하는 코드 부분을 가리킨다. 원자적 실행을 보장해야 한다.
    • 경쟁상태란 스레드들이 위험구역에 들어가기 위해 경쟁하는 상태.


  3. 락킹(Locking)

    • 한번에 오직 하나의 스레드만이 공유하는 자료구조를 조작할 수 있다는 것을 확실할 방법.
    • 특별한 구역에서 다른 스레드가 동작하고 있을 때 해당 자료구조를 접근하지 못하게 하는 방법.
    • 락은 동시성을 방지하여 경쟁상태로부터 큐를 보호할 수 있다.

      1. 스레드는 방에 들어서면서 방문을 잠근다. 공유 데이터의 사용이 끝나면 스레드는 자물쇠를 열고 방을 떠난다.
      2. 만약 다른 스레드가 방문에 도착했을 때 문이 잠겨져 있다면, 안에 있는 스레드가 문을 열고 나올 때까지 기다린 후에 방에 들어가게 된다.
      3. 스레드는 락을 잠그고, 락은 데이터를 보호한다.


  4. 동시성

    • 프로그램들이 선점되면서 스케줄링 된다는 사실에서 비롯된다. 어떤 프로세스가 위험지역에 있을 때 비자발적으로 선점돼 버리는 일이 발생할 수 있다.

      • 유사동시성(peudo-concurrency) - 실제로는 동시에 발생하지 않지만 서로 엇갈려서 실행돼 마치 동시에 실행되는 것과 같은 효과가 발생.
      • 진정한동시성(true-concurrency) - 대칭형 멀티프로세싱 시스템에서 두 프로세스는 정확히 가튼 시간에 하나의 위험지역에 진입 할 수 있다.
    • 커널에서의 동시성의 원인

      1. 인터럽트 - 비동기적으로 어느때나 발생하여 현재 실행중인 코드를 중단시킨다.
      2. softirq와 태스크릿 - 커널은 현재 동작중인 코드를 중단하기 위해 거의 언제라도 softirq나 태스크릿을 레이즈하거나 스케줄할 수 있다.
      3. 커널 선점 - 커널도 선점형이므로, 커널에 있는 한 태스크가 다른 태스크를 선점할 수 있다.
      4. 유저공간에서의 휴면과 동기화 - 커널의 태스크는 휴면할 수 있으며 따라서 스케줄러가 새로운 프로세스를 실행하게 된다.
      5. 대칭형 멀티프로세싱 - 2개 이상의 프로세서가 코드를 동시에 실행할 수 있다.
    • 동시성으로 인해 문제가 발생되는 경우 (락이 없다면..) : 경쟁상태가 발생

      1. 커널에서 어떤 자원을 조작하고 있는 도중에 인터럽트가 발생하여 같은 자원에 접근하는 경우.
      2. 커널이 공유 자원을 사용하고 있는 동안 커널 코드가 선점되는 경우.
      3. 위험지역을 실행하는 도중 커널 코드가 휴면하는 경우.
      4. 두 프로세서가 동시에 공유데이터에 접근하는 경우.


  5. 보호영역의 결정

    • 동시에 접근될 수 있는 모든 코드는 보호가 필요로 하므로, 사실 보호가 필요없는 코드를 먼저 찾아내는 법도 있다.

      1. 특정스레드에 로컬한 데이터가 있을 경우.( 로컬자동변수, 스택에서만 존재하는 자료구조들.. )
      2. 특정 태스크에 의해서만 사용되는 데이터.
    • 보호영역의 선정 ( 커널의 거의 모든 전역 데이터와 공유 데이터는 어떠한 형식으로든 동기화. )

      1. 데이터가 전역적인가 ? 다른 스레드가 이 데이터에 접근 가능한가?
      2. 데이터가 프로세스 컨텍스트와 인터럽트 컨텍스트간에 공유되는가?
      3. 데이터를 사용하는 도중 프로세스가 선점되는 경우, 새로 스케줄된 프로세스가 같은 데이터에 접근하는가?
      4. 현재 프로세스가 휴면(or 블록)하는 경우가 있는가? 만약 그렇다면 휴면(블록)시 공유 데이터가 어떤 상태에 놓이게 되는가?
      5. 다른 곳에서 이 데이터가 해제되지 않으려면 어떻게 해야 하는가?
      6. 이 함수가 다른 프로세서에서 호출되면 어떤 일이 벌어지는가?


  6. 데드락(Deadlock)

    • 어떠한 스레드도 더 이상 진행할 수 없는 상태

      • 각 스레드가 어떤 자원을 얻으려 대기하지만 이미 모든 자원의 락이 잡혀있을 때 발생한다. 모든 스레드가 서로에 대해 대기하므로 이미 잡고 있는 자원을 해제할 수도 없다.
    • 셀프 데드락(self-deadlock) 이란 어떤 스레드가 자기 자신이 이미 잡고 있는 락을 다시 얻으려 시도할려고 할때 발생.
    • 죽음의 포옹(deadly embrace) or ABBA 데드락 이란 2개의 스레와 2개의 락이 있는 경우 발생.

      • 스레드1이 락 A를 얻음 / 스레드2가 락 B를 얻음
      • 스레드1이 락 B를 얻으려 함 / 스레드2가 락 A를 얻으려 함
      • 스레드1이 락 B에 대해 대기 / 스레드2가 락 A에 대해 대기
    • 데드락 방지

      1. 중첩된 락은 반드시 같은 순서로 잠겨져야 한다. 죽음의 포옹을 방지.

        • 서로 다른 구조체를 보호하는 cat, dog, fox 라는 3개의 락이 있을 때 어떤 함수가 cat->dog->fox 순서로 접근을 하였다.
        • 다른 모든 함수 역시 같은 순서로 락들을 잠가야 한다.
      2. 기아현상(starvation)을 방지해야 한다. 코드가 종료하는가를 되짚어 봐야 한다. 어떠한 코드도 무한대기가 일어나서는 안된다.!

        • 락이 풀리기를 대기중인 스레드들은 적당한!! 시간에 락을 얻을 수 있어야만 한다.
      3. 같은 락을 두 번 잠그지 않아야 한다.( 리눅스에서는 재귀적 락을 제공하지 하는다. )
      4. 락은 최대한 단순하게 설계해야 한다.


  7. 경쟁과 확장성

    • 현재 사용되고 있는 어떤 락을 다른 스레드가 얻으려 하는 상황을 락경쟁(Lock Contention) 혹은 경쟁이라고 한다.

      • 경쟁이 심한 락일수록 시스템 성능 저하에 더 큰 영향을 미친다.
    • 확장성이란 어떤 시스템이 얼마나 잘 확장될 수 있는가를 가리킨다.
    • 락킹의 세세함(granularity) 이란 그 락이 보호하는 데이터의 크기를 고려하는 것을 의미한다.
    • 정확하지않은(coarse)락은 많은 양의 데이터, 전체 서브시스템의 자료구조를 보호하는 경우이다.

      • 락경쟁이 심할 경우 확장성의 저하로 이어진다.
    • 매우 촘촘한(fine grained)락은 매우 적은 양의 데이터, 큰 구조체에 속한 하나의 항목만을 보호한다.

      • 충분한 락 경쟁이 없는 경우 소모적인 부하로서 작용한다. 


        출처 : http://dblab.co.kr/category/Study/System?page=1
          

'Embedded Lab > linux, x86' 카테고리의 다른 글

[시너지]  (0) 2012.01.26
[9장 커널 동기화 방법]  (0) 2012.01.26
[Top-Half와 Bottom-Half]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
[커널의 종류]  (0) 2012.01.11
Posted by cyj4369
,
LDD에서 발췌..
~~~
Interrupt Handlers need to finish up quickly and not keep interrupts blocked for long.
~~~
Linux resolves this problems by splitting the interrupt handler into two halves.
The so-called top half is the routine that actually responds to the interrupt - ~~~
The bottom half is a routine that is scheduled by the top half to be excuted later, at a
safer time.

여기서 this problems은 만약 Interrupt Handler 에서 오랜 시간을 요하는 작업을 수행해야 할경우?
는 어떻게 해야 하는가로부터 시작한다. LDD에서도 언급하였듯이 전체 시스템의 성능을 위해서라도
Interrupt Handler의 수행 시간은 적어야 한다. 이른 Linux에서는 두개의 Interrupt 루틴으로 나누고
처리를 한다. 즉 긴급을 요하는 작업은 Top-Half 그리고 이후는 Bottom-Half.....

NIC를 예로 들자면 패킷이 도착시, 커널은 최소한의 작업(패킷의 메모리 복사, 패킷 도착 알림, 재 초기화)
등을 한후 나머지 네트워크 프로토콜 레이어 작업은 이후 Bottom Half에서 처리한다.

Top-Half와 Bottom-Half의 차이점은 Bottom-Half시에 모든 Interrupt는 Enable 상태라는 것...

'Embedded Lab > linux, x86' 카테고리의 다른 글

[9장 커널 동기화 방법]  (0) 2012.01.26
[8장 커널 동기화 개요]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
[커널의 종류]  (0) 2012.01.11
[프로세스의 상태 정리]  (0) 2012.01.04
Posted by cyj4369
,


인라인함수(inline)



정의:

매크로 함수와 마찬가지로 치환함수입니다.




원형:

inline 반환형식 이름 ( 인자)

ex)

inline int abc(int x,int y)
{
return x+y;
}




설명:

함수정의 부분앞쪽에 inline 키워드를 준거빼곤 일반 함수정의와 다를게없습니다

하지만 함수와 큰차이점이잇습니다

인라인이라는 점에서 알수있듯이

인라인함수를호출한 함수내에서 벗어나지않고 값을 치환하여 작동합니다.

반대로 함수는 함수호출시 기존함수에서벋어나 함수정의한 부분으로 넘어가

처리합니다.

ex)

inline int abc(int x,int y)
{
return x+y;
}
                                      --------->>    
int main()                                                        int main()
{                                                                    {
cout<<abc(1,2)                                               cout<<1+2
}                                                                    }


매크로함수와다르게 무조건 치환이 아니기떄문에

활용하기 좀더 용의하다고 할수잇습니다

ex)

inline int abc(int x,int y)
{
return x*y;
}

int main()
{
cout<<abc(1+2,1+2);
}

출력
9;



정리:

매크로함수와 인라인함수는 비슷하지만

간단한작업이아니라면 인라인함수가 좀더 효율적으로 사용될수있다



다음의 글은 C++ 책에 나오는 인라인 함수 대한 글을 요약한 자료로 일반 함수와 인라인 함수의 차이점, 특징, 사용법을 이야기 한다.

1. 일반 함수의 수행
 프로그램이 함수 호출 명령에 도달하면, 그 프로그램은 다음의 ①-⑥의 흐름을 갖는다.

① 함수 호출 명령 다음의 명령 주소를 메모리에 저장
② 스택에 전달인자를 복사
③ 해당 함수의 시작의 메모리 위치로 점프
④ 함수 수행
⑤ 함수 리턴 값을 레지스터에 저장
⑥ ①에서 저장해둔 주소의 명령으로 복귀


2. 인라인 함수
 인라인 함수는 프로그램의 코드들 가운데 컴파일된 함수 코드가 삽입된다. 이는 컴파일러에 의해 해당 인라인 함수가 함수 코드로 대체됨을 뜻한다. 이렇듯 인라인 함수를 사용하면, 프로그램은 해당 코드를 수행하기 위해 위의 일반 함수 수행처럼 메모리에 있는 함수의 주소를 찾아 점프할 필요가 없어지게 되어, 일반 함수보다 약간이나마 빠른 수행 속도를 갖을 수 있다. 그러나 만약 크기가 큰 코드를 가진 함수를 인라인 함수로 사용하고, 10번을 호출게 된다면, 해당 프로그램 코드 사이에 10개의 복사본을 갖게 됨으로써, 메모리 사용면에서 좋지 않을 수 있다. 또한 함수 수행의 속도에서도 일반 함수 크기가 작다면, 함수 수행을 위해 점프하고, 돌아오는 시간이 적으므로 속도로 얻을 수 있는 이익이 작을 수 있다. 그러므로 인라인 함수 사용 시에는 다음과 같은 특징을 꼭 기억하고 있어야 한다.

 짧은 함수를 인라인 함수로 사용해야 한다.
• 함수 호출 비용을 절약한다.
 짧은 인라인 함수는 함수 호출문에 대해 만들어지는 코드보다 목적 코드가 작아질 수 있다.
 캐시 적중율이 높아진다.

 코드 길이가 긴 인라인 함수는 사용하지 말자! 
• 인라인 함수를 남용하게 되면, 컴파일 시에 코드 대체로 인한 목적 코드의 크기가 증가할 수 있다.

③ 가상 함수를 인라인 함수로 만들지 말자!
• 가상 함수는 컴파일 시가 아닌, 프로그램 수행시 결정되므로 컴파일 시에 코드 대체되는 인라인 함수로는 사용될 수 없다.


3. 인라인과 매크로
간단한 처리를 위해 사용되어온 C의 잔재인 매크로들은 문제점을 안고 있으므로 인라인 함수로 고쳐 사용한다.
다음은 숫자를 제곱하는 매크로 함수이다.

#define SQUARE(X) (X*X)

위의 매크로 함수는 X를 전달인자로 보지 않고, 전달인자에 대한 심벌 레이블처럼 행동하게 하여 문자 대치에 의해 작동되어 다음의 문제점을 유발시킨다.

• a = SQUARE(4.5+7.5);
 SQUARE 매크로가 호출되게 되면 다음과 같이 실행된다.
 4.5 + 7.5 * 7.5 + 4.5
 이는 연산자 우선순위에 의해(*은 + 보다 우선순위가 높다) 전혀 다른 결과를 얻게 된다.

• b = SQUARE(a++);
 a++ * a++
 SQUARE 매크로가 호출되어 단순 문자 대치로 작동되어 위와 같은 결과를 초래한다. 그러므로 가급적 위와 같은 매크로는 사용을 지양하고, 다음과 같이 인라인 함수를 사용하도록 한다.

// Calculator.h
class CCalculator
{
...

public:
    double CalcSquare(const double& dblVaule);
};

inline double CCalculator::CalcSquare(const double& dblVaule)
{
    return (dblVaule*dblVaule);
}

[예제 1] 명시적 inline 함수 (개인적으로 선호)


4. 인라인 사용 예
(1) 정의

• inline 한정자를 사용하여 함수를 선언한다.
• inline 함수의 정의는 그것을 호출하는 어떠한 함수보다도 앞에 있어야 한다.

(2) 구현
위의 CCalcuator 클래스 처럼 inline 한정자를 주어 명시적으로 인라인 함수를 구현할 수 있다. 그러나 암시적으로 다음과 같이 설정해도 컴파일러는 이를 인라인 함수로 처리한다.

// Calculator.h
class CCalculator
{
...

public:
    double CalcSquare(const double& dblVaule) { return (dblVaule*dblVaule); }
};

[예제 2] 암시적 inline 함수


(3) 사용
위의 [예제 1]과 [예제 2] 방법 중에서 개인적인 취향에 따라 구현 방법이 다를 것이라 생각된다. 하지만 개인적인으로는 [예제 1]의 방법을 사용하는데, 이는 선언부에는 선언만!하는게 좋다고 생각하고, 코드가 깔끔해 보이는 이유 때문이다. 


※ 참고 자료 
1. Stephen Prata, C++  기초 플러스, 성안당, pp.366-369 
2. Scott Meyers, Effective C++, Addison-Wesley, Item 30 pp.134-139


'Embedded Lab > linux, x86' 카테고리의 다른 글

[8장 커널 동기화 개요]  (0) 2012.01.26
[Top-Half와 Bottom-Half]  (0) 2012.01.26
[커널의 종류]  (0) 2012.01.11
[프로세스의 상태 정리]  (0) 2012.01.04
[Slab Allocator]  (0) 2012.01.04
Posted by cyj4369
,
커널(Kernel)

컴퓨터의 커널을 운영체제의 핵심이다. 운영 체제의 다른 모든 부분에 여러 가지 기본적인 서비스를 제공한다. 시스템의 자원은 제한되어 있지만 프로그램은 많기 때문에 커널은 프로그램의 수행상태인 프로세스 간의 보안 접근을 책임지는 소프트웨어이다. 커널이 이러한 프로세스마다 얼마만큼의 자원을 사용해야 하는 결정해야 하는데 이것을 스케줄링이라고 한다. 

같 은 종류의 컴포넌트에 대해 다양한 하드웨어 디자인이 가능하기 때문에 하드웨어 직접 접근하는 것은 매우 복잡할 수 있다. 일반적으로 커널은 운영 체제의 복잡한 내부를 감추고 깔끔하고 일관성 있는 인터페이스를 하드웨어에 제공하기 위해 하드웨어 추상화를 지원한다. 이러한 하드웨어 추상화는 프로그래머가 하드웨어의 복잡한 접근을 고민할 필요 없이 쉽게 개발하는 것을 돕는다. 
하드웨어 추상화 계층(HAL)은 제조사의 장비 명세에 대한 특정한 명령어를 제공하는 소프트웨어 드라이버에 의지한다. 

이 렇듯 커널은 운영체제에서 핵심적인 기능을 담당하지만 수행에 필수적인 것만은 아니다. 프로그램은 하드웨어 추상화나 운영체제 지원없이 컴퓨터만으로 읽어 들여져 수행될 수 있기 때문이다. 이러한 방법은 초기 컴퓨터의 운영 방법이었고 다른 프로그램을 실행하고 싶을 때는 컴퓨터는 다시 켜고 다시 읽어 들여야 했다. 그 결과 로더와 디버거 같은 작은 프로그램들이 프로그램을 수행시키는 작업을 해야 했고 이것이 초기 운영체제 커널의 기초가 되었다. 

이러한 커널은 크게 4가지로 구분할 수가 있다. 

  • 모놀리딕커널(Monolithic Kernel)
  • 마이크로커널(Micro Kernel)
  • 하이브리드커널(Hybrid Kernel)
  • 엑소커널(Exo Kernel)


모놀리딕 커널

모 놀리식 커널은 하드웨어 위에 고수준의 가상 층을 가지고 있다. 고수준의 가상층은 기본 연산 집합과 관리자모드에서 작동하는 프로세스관리, 동시성, 메모리관리 등의 운영체제 서비스 구현을 위한 시스템콜(System Call)로 되어있다.

이 러한 연산들을 제공하는 모듈은 같은 주소 공간에서 실행되기 때문에 코드의 집적도는 매우 조밀하고 수정하기 어렵고 한 모듈의 버그는 전체 시스템을 멈추게 할 수도 있다. 그러나 구현이 신뢰할 정도로 완성되면 컴포넌트의 내부 집적이 내부의 시스템 이용을 효과적이게 하여 높은 효율을 보인다. 

모놀리딕 커널의 지지자들은 코드가 부정확한지 그런 코드가 커널에 포함되어 있는지 확인 할 수 있고 그것은 마이크로 커널에 비해 미세한 우위에 있다고 주장한다. 

리눅스, FreeBSD, 솔라리스와 같은 모놀리딕커널은 실행 모듈을 실시간으로 읽어들일 수 있다. 실시간으로 실행 모듈을 읽는 특징은 커널이 허용하는 범위 내에서 손쉽게 확장 가능하도록 커널 공간의 코드의 양을 최소한으로 유지시켜 준다. 

마 이크로소프트 윈도우즈 NT(NT, 2000, XP, 2003 등)는 초창기에는 하이브리드커널이었으나 후기 버전은 모놀리딕커널로 변경되었다. 윈도우즈 NT 시리즈는 상위의 서비스들을 NT executive라는 서버로 구현하였다. Win32 특성은 처음에는 사용자 모드의 서버 형태로 구현되었으나, 최근 버전에서는 관리자 주소 영역으로 이동하였다. 다양한 서버들이 로컬 프로시저 콜(LPC;Local Procedure Call)이라 불리는 주소 영역간 매커니즘을 통해 통신하며, 성능 최적화를 위해 공유메모리를 이용한다. 

모놀리딕 커널을 사용한 운영체제는 다음과 같다. 
  • BSD 커널과 같은 전통적인 유닉스 커널
  • 리눅스 커널
  • 솔라리스 커널
  • 윈도우즈 NT 커널
  • 벨로나2 커널
  • AIX 커널


마이크로 커널


마 이크로 커널은 모놀리딕 커널과 달리 하드웨어 위에 매우 간결한 추상화만을 제공한다.기본 연산 집합과 운영체제 서비스를 구현한 쓰레드 관리, 주소 공간, 프로세스간 통신의 작은 시스템 콜로 구성된다. 일반적으로 커널이 제공하는 네트워킹 같은 다른 서비스들은 사용자 공간 프로그램인 서버로 구현한다. 

운 영체제는 서버를 다른 일반적인 프로그램처럼 간단히 시작하고 끌 수 있다. 예를 들어 네트워킹 지원이 필요 없는 작은 시스템에서는 간단히 켜지 않으면 된다. 이론적으로 마이크로커널에서 시스템은 더 안정적이다. 서버가 중단될 때 커널의 충돌이 아니기 때문에 단 하나의 프로그램만 내려버리면 된다. 

일반적으로 마이크로 커널은 전통적인 디자인의 수행을 잘하지 못할수도 있다. 서버와의 자료교환을 위해 커널을 출입하는 문맥 전환 때문이다. 주의 깊은 조율이 오버헤드를 극적으로 줄여줄 것으로 믿어져 왔으나 90년대 중반부터 대부분의 연구자들은 시도를 포기했다. 최근에 새 마이크로 커널은 성능을 최우선으로 설계하며 이 문제를 넓은 부분에서 다루었다. 그러나 현재 운영체제 시장은 자기 몸 사리며 마이크로 커널 설계에 소극적이다. 

마이크로 커널과 마이크로 커널에 기반한 운영체제는 다음과 같다. 
  • AmigaOS
  • Amoeba
  • ChorusOS
  • EROS
  • Haiku
  • K42
  • LSE/OS
  • KeyKOS
  • L4 마이크로커널
  • Mach
  • MERT
  • Minix
  • MorphOS
  • NewOS
  • QNX
  • Phoenix-RTOS
  • RadiOS
  • Spring operationg system
  • VSTa
  • Symbian OS


하이브리드 커널

하이브리드 커널은 본질적으로 마이크로 커널을 따르나, 사용자 레벨에서 수행될 때 느린 코드들을 커널 레벨에서 수행하도록 수정한 것을 말한다. 

이는 다양한 운영체제 개발자들이 마이크로커널 기반의 설계를 받아들이던 시점에 순수한 마이크로커널의 성능상 한계를 극복해보고자 생각해낸 내용이다. 

 예 를 들어, 맥 오에스 텐의 커널인 XNU는 Mach 커널 3.0 마이크로 커널에 기반을 두고 있지만, 전통적인 마이크로 커널 설계의 지연 현상을 줄이기 위해 BSD 커널의 일부 코드들을 들여와 동일한 주소 영역에서 실행하고 있다. 

하이브리드 커널로는 다음과 같은 것들도 포함된다. 
  • ReactOS
  • BeOS 커널
  • Netware 커널

하이브리드 커널은 모놀리딕 커널과 마이크로 커널 설계 양쪽의 구조적 개념과 작동방법에 대한 것으로 어떤 것은 사용자 공간에 들어가는 반면 어떤 코드는 성능의 이유로 커널 공간에 포함해야 하는지에 대한 선택의 문제이다. 


엑소 커널

엑소커널은 운영체제 설계에 대한 급진적인 신개념으로 수직 구조의 운영체제이다. 

엑 소커널의 구상은 개발자에게 강제적인 추상화를 줄여 하드웨어 추상화에 대한 선택의 폭을 넓혀준다. 엑소커널은 여러 개의 가상화를 실행하는데 각 가상화는 하드웨어 추상화 계층을 통하지 않고 하드웨어 구역에 직접 접근한다. 응용소프트웨어와 추상화는 특정 메모리 주소와 디스크 블록 등을 요구하는데 커널은 단지 자원이 비어있는지만 확인하고 응용소프트웨어에게 접근을 허용한다.

이러한 저수준의 하드웨어 접근은 프로그래머가 개별적인 추상화를 만드는 것을 허용하여 불필요한 부분을 제거할 수 있게 하고 일반적으로 프로그램의 성능을 향상시킨다. 

엑 소커널은 추상화를 제공하는 라이브러리 운영체지(libOSes)를 이용한다. 라이브러리 운영체제는 응용소프트웨어 프로그래머에게 고수준, 전통적인 운영체제 추상화, 맞춤 추상화 구현 등의 더 유동적인 방법을 제공한다. 이론적으로 엑소커널의 체제는 하나의 엑소커널 아래 윈도우즈나 유닉스와 같은 다양한 운영체제를 구동할 수 있다. 

엑소커널의 개념은 1994년에 나왔으며 현재 까지 여전히 학계에서 연구 중이며 대규모의 상용 운영체제는 아직 까지 없다.

'Embedded Lab > linux, x86' 카테고리의 다른 글

[Top-Half와 Bottom-Half]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
[프로세스의 상태 정리]  (0) 2012.01.04
[Slab Allocator]  (0) 2012.01.04
[커널컴파일]  (0) 2012.01.03
Posted by cyj4369
,
  • TASK_RUNNING

    • 프로세스가 CPU에서 실행 중이거나 실행되기를 기다리는 중이다.
  • TASK_INTERRUPTIBLE
    • 프로세스가 어떤 조건에 맞아떨어지기를 기다리면서 보류 중(자는중)이다. 프로세스를 깨울수 있는 조건으로는 하드웨어 인터럽트가 발생하거나, 프로세스가 기다리고 있는 자원이 해지되거나, 프로세스에 시그널을 전달하는 것이 있을 수 있다.
  • TASK_UNINTERRUPTIBLE

    • TASK_INTERRUPTIBLE과 비슷하지만 잠들어 있는 프로세스에 시그널을 전달해도 프로세스 상태가 바뀌지 않는다는 차이가 있다. 이 프로세스 상태는 거의 사용하지 않는다. 그러나 프로세스가 정해진 사건이 발생하기를 기다리는 도중에 방해를 받으면 안 되는 특수한 상황에서 유용하다. 예를 들어, 프로세스가 장치 파일을 열 때 해당 장치 드라이버가 자신이 다룰 하드웨어 장치가 있는지 조사하는 경우에 이러한 상태를 사용할 수 있다. 장치 드라이버는 조사를 완료할 때까지 방해를 받으면 안된다. 그렇지 않으면 하드웨어 장치가 예측할 수 없는 상태에 빠질 수도 있다.
  • TASK_STOPPED

    • 프로세스 실행이 중단 되었다. 프로세스는 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU의 시그널을 받으면 현재의 상태가 된다.
  • TASK_TRACED

    • 프로세스 실행이 디버거에 의해 멈춘 경우이다. 디버거가 테스트 프로그램을 모니터링하기 위해 ptrace()  시스템 콜을 수행하는 것처럼 프로세스가 다른 프로세스에 의해 모니터링 될 때 시그널은 프로세스를 TASK_TRACED 상태에 둔다.
  • EXIT_ZOMBIE

    • 프로세스가 종료되었지만 부모 프로세스가 wait4() 또는 waitpid() 시스템 콜을 호출하여 종료 프로세스의 정보를 반환하지 않은 경우이다. 부모 프로세스가 wait() 계열 시스템 콜을 호출하기 전에는 종료한 프로세스의 프로세스 디스크립터에 들어 있는 데이터를 부모 프로세스가 필요로 할 수 있기때문에 커널은 데이터를 삭제해서는 안된다.
  • EXIT_DEAD

    • 마지막 상태로 부모 프로세스가 wait4() 또는 waitpid() 시스템 콜을 방금 수행하였으므로 시스템에서 제거되는 중이다. EXIT_ZOMBIE에서 EXIT_DEAD로 상태를 바꾸는 것은 같은 프로세스에 대해 다른 스레드가 wait() 콜을 수행함으로써 발생하는 경쟁 조건을 피하기 위해서이다.

'Embedded Lab > linux, x86' 카테고리의 다른 글

[Top-Half와 Bottom-Half]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
[커널의 종류]  (0) 2012.01.11
[Slab Allocator]  (0) 2012.01.04
[커널컴파일]  (0) 2012.01.03
Posted by cyj4369
,

리눅스 커널의 물리 메모리 관리는 페이지 단위로 이루어진다그렇다면 예를 들어 19byte 요청한다고 해서 시스템의 페이지 단위인 4K byte 할당될까그렇지는 않다예를 들어 kmalloc 사용하여 19 byte 요청하게 되면 32byte가 할당된다그렇다면 kmalloc 어떻게 32byte 할당하게 할까이것이 이번 장에서 얘기할 슬랩 할당자 덕분이다.

 

 

커널이 관리하는 페이지 단위는 커널에서 사용하기에 다소 큰단위이다. 4K 응용 프로그램을 개발하는 분들은쉽게 생각할지 모르겠지만 커널의 입장에서 많은 함수들이 4K 사용한다는 것은 시스템의 치명적인 성능저하를 유발할 수도 있으며 메모리 단편화를 너무 많이 일으켜 금방 시스템의 성능저하로 이어지게  것이다그러므로 커널 입장에서는  byte요청을 4K 되돌려 준다는 것은 용납할  없는 일이된다.

예를 들어19byte 요청한 입장에서 4K 할당되었다는 것은 나머지 4077 byte 사용자가 free하지 않는  시스템의 입장에서는 사용하지 못하는 영역이 되버리고 말기 때문이다.

이를 우리는 멋있는 말로 내부 단편화라고 한다내부 단편화문제를 해결하기 위하여 슬랩 할당자가 나오게 되었다.

 

슬랩은 내부 단편화 문제를 해결할 뿐만이 아니라 커널 내에서 흔히 일어나는 dynamic memory 할당의 overhead 줄이기 위하여 캐싱하는 역할을 하여 성능 개선에도  도움을 주고 있다슬랩 할당자의 기본 구조는 다음과 같다하나의 캐시를 나타내는 kmem_cache_s 구조체는 kmem_list3 구조체를 통하여 slab들을 관리하며슬랩 내에는 사용자에게 할당할 object들이 저장되어 있는  구조이다.

 


캐시는 관리가 필요한 오브젝트 종류별로(예를 들면task_struct, file, buffer_head, inode 작성되고  오브젝트의 슬랩을 관리한다슬랩은 하나 이상의 연속된 물리 페이지로 구성되어 있으며 일반적으로 하나의 페이지로 구성된다캐시는 이러한 슬랩들의 복수개로 구성된다.

 

캐시에는 다음과 같은 3가지의 슬랩 리스트가 있다.

 

● slab_full : 슬랩내의 오브젝트가 전부 사용 중인 

● slab_partial : 슬랩내의 오브젝트가 사용중인 것과 미사용중인 것이 혼재되어 있는 

● slabs_empy : 슬랩내의 오브젝트가 전부 미사용인 슬랩 리스트

 

위와 같은 구조를 통하여 자주 사용되는 오브젝트들을 미리 할당하여 놓고 사용자 요구가 있을  마다 바로 반환하는 것이다이것은 물리 메모리를 확보하기 위하여 검색  회수반환과 같은  여행을 떠날 필요가 없으므로 시스템의 성능을 향상시킨다또한  사용된 오브젝트들을 반납받아 커널의 메모리 할당자에게 반환하지 않고 보관했다가 재사용하기 

문에 시스템의 성능을 향상시킬  있게 된다.

 

그렇다면 kmalloc 어떻게 슬랩 할당자를 사용할까그것은 커널이 시스템을 초기화   kmem_cache_init 함수를 통하여 자주 사용되는 커널의 오브젝트들의 크기를 고려하여 일반적으로 사용할 목적으로 추가적인 캐시들을 생성하기 때문이다. 그 크기는 32/64/128/256/512/1024/4096/8192/16384/32768/65536/131072 byte이다

이는  kmalloc 할당   있는 메모리 크기는 128K라는 것을 의미하기도 한다커널은 위의 크기의 object 이루어진 캐시를 미리 할당하여 메모리에 유지하고 있으며 사용자의 요구가 들어왔을 경우 위의 크기  가장가깝게  수로 올림하여 할당하게 되므로 페이지 단위로 관리하는  보다 내부 단편화를 줄이게 되며 시스템의성능을 향상시키게 된다.

 

'Embedded Lab > linux, x86' 카테고리의 다른 글

[Top-Half와 Bottom-Half]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
[커널의 종류]  (0) 2012.01.11
[프로세스의 상태 정리]  (0) 2012.01.04
[커널컴파일]  (0) 2012.01.03
Posted by cyj4369
,
커널이란?

커널이란 운영체제(Operating System)에서 가장 핵심적인 역할인 자원 (메모리, 프로세서등)을 관리하며 시스템이 원활히 돌아갈 수 있도록 제어해 준다. 현재 우리가 리눅스(OS)라고 하는것도 실제적으론 리눅스란 운영체제의 커널 이름을 말하는것인데 이것이 확장된 의미로 사용되어 현재의 '리눅스'란 OS를 지칭하게도 된것이다. 그러므로 Linux = kernel이란 등식이 성립한다.


● 커널 컴파일은 언제 하나?

커널은 시스템을 운영하기 위한 가장 기본적인 코드가 포함되어 있어야 한다. 즉, 장치 혹은 시스템의 기능과 관련된 변화가 있을 경우 새로운 커널을 생성해야 한다.

현재 시스템은 어떠한 장치가 장착되어 있으며, 어떠한 목적으로 시스템을 운영할 것인가에 따라 커널의 구성요소가 달라질 수 있다는 것을 의미하며, 현재 커널에는 어떠한 것들을 지원하는가에 대한 정보는 커널 소스 디렉토리에 존재하는 Documentation 디렉토리에서 해당 정보를 얻을 수 있다.

만약 현재 시스템을 운영하기 위해 필요로 하는 장치에 대한 정보나 기능에 대한 핵심 코드가 현재 커널에 존재한다면 굳이 커널을 업그레이드 하거나 새로 생성할 필요가 없다. 하지만 간혹 커널 자체에 보안적 문제가 존재하기도 하는 데, 그러할 경우 꼭 커널 업그레이드를 해야한다.


● 커널은 어디서 구하나?

-> 최신 버전의 커널을 
www.kernel.org 에서 구할 수 있다.



● 커널 컴파일 방법

여러 가지 방법들이 있지만 저장된 커널 옵션 설정 파일이 있다면 oldconfig를
저장된 파일이 없다면 menuconfig를 추천한다.

make oldconfig 또는 make menucofig

make oldconfig를 하기위해선 다음과 같은 작업이 필요하다. 
예전에 설정한 커널옵션이 kernel.config 란 이름으로 저장되어있다면 이 파일을 새 버전의 커널이 있는 /usr/src/linux 디렉토리에 .config란 이름으로 카피한다.

-> 이 명령어는 새 버전의 커널이 있는 /usr/src/linux 디렉토리에서 하는 것이며, 대게의 경우 이전 버전의 설정파일 이름도 .config 이다.


● 모듈 컴파일 방법

모듈이 생성되는 디렉토리는 '/lib/modules/<커널버전>'이고 만약 현재 커널의 모듈을 다시 생성하려고 한다면 현재 커널의 모듈 디렉토리를 지우고 다시 컴파일 하기 바란다.

1. $make modules 
2. $make modules_install


● Initrd 이미지 만들기

모듈을 만들고, 때에 다라서 initrd이미지도 만들어줄 필요가 있다. (가령 ext2/3 vfs같은 fs를 모듈로 제작했을때) 그럴때엔 mkinitrd 를 사용하자.

$cd /lib/modules 
해서 방을 옮긴후 
$ls 
해보면 2.X.X 식으로 나와있다.
2.X.X인지 정확히 기억해서 <커널버전>에 똑같이 넣어준다.

$mkinitrd /boot/initrd-<커널버전 혹은 원하는 이름>.img <커널버전>

 

●● 실제 컴파일 해보기

  먼저 다운로드한 커널 소스를 /usr/src/ 디렉토리로 복사한다.
커널 컴파일은 /usr/src/<커널버전> 디렉토리에서 진행한다.

1. make mrproper : 이전의 컴파일시 설정되었던 설정을 제거
(최초 커널 컴파일시나 이전 설정한 컴파일 환경을 재사용한다면 생략 가능 )
2. make menuconfig : 텍스트 환경
혹은 make xconfig : x윈도우 환경
혹은 make oldconfig : 기존의 환경을 불러와서 새로운 것만 설정

3.  make dep : 설정한 영역의 의존성 검사
4.  make clean : 이전 컴파일시 생성된 파일을 삭제
( 4. 은 경우에 따라 생략할 수 있음 )

5. make bzImage : 설정한 기준으로 새로운 커널을 생성, 커널이 생성된 이후 생성된 커널을 커널이 위치해야 할 디렉토리(/boot)로 복사하는 과정은 관리자가 cp 명령어를 이용하여 직접 옮겨야 한다.
커널 생성시 또 하나의 파일(System.map)이 생성되며, 이 파일 또한 /boot로 복사한다.
$cp arch/i386/boot/bzImage /boot/<커널 버전>
$cp System.map /boot/System.map
6. mkinitrd : 이 문서 위의 "● Initrd 이미지 만들기" 참조

( 5,6의 과정은 make install을 수행하면 자동으로 수행된다. 단, make install은  "8.make modules_install"명령어 후에 실행해야 정상적으로 동작한다.
이 과정후 /etc/grub.conf의 설정이 올바르게 되었나 확인해 본다. )

7. make modules : 모듈들을 만든다. (시간이 좀 오래 걸린다. -_-)
※모듈 : 부팅시 메모리에 적재되는 것이 아니라 부팅 과정 이후 설정에 따라 혹은 해당 장치 혹은 기능을 사용할 경우에만 메모리에 올려서 사용한 후 사용하지 않을 경우 메모리에서 삭제하므로 효과적으로 메모리를 관리할 수 있다.

8. make modules_install : 만들어진 모듈들을 설치한다. 
모듈이 위치할 디렉토리(/lib/modules/<커널버전>)으로 이동시켜주는 역할도 한다.
※커널 버전마다 지원하는 장치나 기능이 다르므로 모듈의 경우 /lib/modules 디렉토리에 해당 커널 버전 디렉토리를 생성하여 커널 버전별로 관리하게 된다.
   
 < 출처 : Red Hat Linux 9 (한빛미디어)박승규 저 >
 < 수정 : by.arm >
 

● 이 모든 명령어 한번에 실행 시키기

이 모든 명령어들을 한꺼번에 줄 수도 있다.

$make bzImage modules modules_install install
과 같이 한번에 끝낼수도 있다.

그러나 
$make bzImage && make modules && make modules_install && make install
과 같은 방법을 추천한다.
이는 전단계에서 에러가 없을시에만 다음 단계로 넘어가는 방법을 취하기 때문이다.


● 커널 패치 방법

커널 소스 전체를 다운로드 하지 않고 변화된 영역만 제공하는 패치를 다운로드 할 경우 현재 소유하고 있는 커널 소스 이후 버전의 패치파일을 모두 다운로드 해야한다.
ex) patch-2.4.19.gz, patch-2.4.20.gz, ...

$patch -p0 < patch-2.4.19
$patch -p0 < patch-2.4.20
.

.

 

※ 단, 패치 가능한 커널소스는 kernel.org에서 배포하는 기본적인 소스이다.

예) Redhat9.0 의 커널 소스 (2.4.20-8) 과 같은 소스는 레드헷에서 kernel.org에서 배포하는 기본적인 소스를 수정한 것이기 때문에 정상적인 패치가 불가능하다. 즉, kernel.org에서 받은 2.4.20 과 같은 커널소스가 정상적인 패치가 가능한 소스라는 뜻이다.

 


◎ 최종 정리
1. make mrproper(최초 컴파일시 생략)
2. make menuconfig
혹은 make xconfig
혹은 make oldconfig
3. make dep
4. make clean (처음으로 컴파일 과정을 수행한다면 생략)
5. make bzImage

6. make modules
7. make modules_install

8. make install  

 

※ make install의 역할 : initrd 이미지를 생성해주고, vmlinuz 커널이미지와 System.map 맵핑 파일을 /boot에 복사하고 심볼릭 링크 파일 생성, 그리고 grub.conf를 알맞게 수정.

 

 

 

※ 위의 과정을 모두 수행후에 리부팅을 했을 때
kernel panic - not syncing : No init found, Try passing init = option to  kernel 과 같은 에러 메세지와 함께 부팅이 안된다면 2. make menuconfig과정에서 file systems 중 ext3 를 모듈<M>이 아닌 적재<*>로 바꾼 후 위의 과정을 반복한다.

★ 여기서 TIP : 윈도우XP를 마운트 하고 싶다면...
위의 과정중 2. make menuconfig과정에서 file systems중에 ntfs를 모듈<M>이나 적재<*>로 설정한다. 모듈 적재에 대해서 잘 모른다면 속편하게 적재<*>로 하기를 권장한다.

 

 

'Embedded Lab > linux, x86' 카테고리의 다른 글

[Top-Half와 Bottom-Half]  (0) 2012.01.26
[인라인(inline) 함수]  (0) 2012.01.11
[커널의 종류]  (0) 2012.01.11
[프로세스의 상태 정리]  (0) 2012.01.04
[Slab Allocator]  (0) 2012.01.04
Posted by cyj4369
,