반응형

1)top - 23:34:08 up 38 days, 1:31, 2)2 users, load average: 0.02, 0.01, 0.00

3)Tasks: 226 total, 1 running, 225 sleeping, 0 stopped, 0 zombie

4)%Cpu(s): 1.6 us, 1.6 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 15923.4 total, 633.3 free, 578.7 used, 14711.5 buff/cache

MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 14918.0 avail Mem

 

PID USER 5)PR 6)NI 7)VIRT 8)RES 9)SHR 10)S %CPU %MEM TIME+ COMMAND

1 root 20 0 226244 9888 6856 S 0.0 0.1 0:53.39 systemd

2 root 20 0 0 0 0 S 0.0 0.0 0:00.41 kthreadd

4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H

6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq

7 root 20 0 0 0 0 S 0.0 0.0 0:04.42 ksoftirqd/0


1)top - 23:34:08 up 38 days

현재 시스템의 시간과 서버가 얼마나 구동되었는지 구동시간이 나와있다

 

2)2 users, load average: 0.02, 0.01, 0.00

몇 명의 사용자가 로그인해 있는지, 시스템의 Load Average는 어느 정도인지 보여준다. Load Average는 현재 시스템이 얼마나 많은 일을 하고 있는지를 보여주는 데이터이다.

 

3)Tasks: 226 total, 1 running, 225 sleeping, 0 stopped, 0 zombie

현재 시스템에 구동중인 프로세스의 개수를 나타낸다. 또한 프로세스 상태에 대한 통계 정보 제공

 

4)%Cpu(s): 1.6 us, 1.6 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 15923.4 total, 633.3 free, 578.7 used, 14711.5 buff/cache

MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 14918.0 avail Mem

CPU, MEM, SWAP 메모리의 사용량이다.


 

5)PR은 프로세스의 실행 우선순위이며 6)NIPR을 얼만큼 조절할건지를 의미한다. 기본적으로 5)PR6)NI를 더해서 실제 우선순위를 계산한다.

 

7)VIRTTASK(프로세스)가 사용하고 있는 Virtual Memory의 전체 용량

8)RES는 현재 TASK가 사용하고 있는 물리 메모리의 양

9)SHR는 다른 프로세스와 공유하고 있는 공유메모리의 양

, VIRT는 프로세스의 할당된 가상메모리 전체크기 이며 RES는 기중 실제로 메모리에 올려서 사용하고 있는 물리 메모리의 크기이고 SHR은 다른 프로세스와 공유하고 있는 메모리의 크기이다

 

10)S는 프로세스의 상태이다.

반응형
반응형

전반부 처리와 후반부 처리

  • 빠른 실행 속도와 대량 작업 실행이라는 인터럽트의 2가지 목표는 서로 충돌하는 점이다.
  • 이 목표를 달성하기 위해 인터럽트 처리는 두 부분으로 나눠져 있다.
    (전반부 처리 top half 와 후반부 처리 bottom half)
  • 전반부 처리(top half)는 인터럽트를 받은 즉시 실행되며 인터럽트 수신확인이나 하드웨어 재설정 처리시한이 중요한 작업만 처리
  • 나중에 할 수 있는 일들은 후반부 처리(bottom half)로 지연 시킨다.

인터럽트 핸들러 등록

  • 인터럽트 핸들러는 하드웨어를 관리하는 드라이버가 담당한다
  • 드라이버는 <linux/interrupt.h> 파일에 정의된 request_irq() 함수를 이용하여 인터럽트를 활성화시키고 인터럽트 핸들러를 등록
  • 첫번째 irq 인자를 통해 할당할 인터럽트를 저장하다. 기본장치의 경우 번호가 할당되어 있지만 다른 장비들은 탐색 작업이나 프로그램에 따라 동적으로 할당된다.
  • 두번째 handler 인자는 인터럽트를 처리할 실제 인터럽트 핸드러를 가르키는 함수 포인트이다
  • typedef irqreturn_t (*irq_handler_t)(int, void *); 

  • 세번째 flag 인자는 0또는 <linux/interrupt.h>에 정의된 플래그를 조합한 비트마스크 값을 사용한다.
  1. IRQF_DISABLED
  2. IRQF_SAMPLE_RANDOM
  3. IRQF_TIMER
  4. IRQF_SHARED
  • 네번째 name 인자는 인터럽트를 사용하는 장비의 ASCII 형식 이름이다
  • 다섯번째 dev 인자는 인터럽트를 공유할 때 사용한다. 인터럽트 핸들러를 해제할 때 dev에 고유한 쿠키값을 지정함으로써 해당 인터럽트 라인에서 원하는 인터럽트 핸들러만을 제거 할 수 있다.
  • 성공하면 request_irq()는 0을 리턴하고 오류가 발생할 때는 0이 아닌값을 사용한다.
  • request_irq()는 휴면상태를 허용하기 때문에 인터럽트 컨텍스트에 있을 때나 코드 실행이 중단되는 상황에서는 호출 불가하다

 

반응형
반응형

커널은 각 장치와 통신을 해야 H/W를 관리할 수 있다. 일반적으로 H/W와 통신속도는 프로세서 속도보다 훨씬 느려서 느린 H/W가 응답할 때까지 커널이 요청을 보내고 기다리는 방식은 이상적이지 않다. H/W의 응답 속도는 매우 느리므로 커널은 다른 작업을 수행하다가 H/W가 실제로 작업을 마친 다음에 이를 처리 할 수 있다.

 

프로세스가 하드웨어를 관리하는 방법 중 하나는 Polling(폴링)이 있다. 커널이 주기적으로 시스템 하드웨어의 상태를 확인하고 그 상태에 따라 처리하는 것이다 . 더 좋은 방법은 커널 처리가 필요한 수간에 하드웨어가 커널 신호를 보낼 수 있는 체계를 두는 것이다. 이런 체계를 Interrupt(인터럽트)라고 한다.

 

인터럽트

  • 하드웨어는 인터럽트를 이용해 프로세서에 신호를 보낼 수 있다.
  • 하드웨어는 프로세스 클럭(Clock)과 상관없이 비동기적으로 인터럽트를 발생시키므로 인터럽트는 아무때나 발생할 수 있다.
  • 따라서 인터럽트 처리로 인해 커널은 언제라도 방해 받을 수 있다.
  • 각 인터럽트 별로 고유한 값을 할당할 수 있으며 장비에 따라 다른 인터럽트를 할당 할 수 있다.
  • 때문에 키보드에서 키보드와 하드디스크에서 발생한 인터럽트는 다르다.
  • 인터럽트 값을 인터럽트 요청(IRQ, interrupt request)라인이라고 하고 각 IRQ 라인에는 번호가 붙어 있다.
  • 요점은 장치별로 특정 인터럽트가 지정되어 있으며, 커널이 이 정보를 가지고 있다는 것이다.

예외(exception)

  • 인터럽트와 달리 예외는 프로세서 클럭과 동기되어 발생
  • 예외는 프로세서 클럭과 동기화 되어 발생한다. 또한 예외는 동기화된 인터럽트라고 부르는 경우가 많다.

인터럽트 핸들러

  • 인터럽트 핸들러(Interrupt handler) , 인터럽트 서비스 루틴 (ISR, Interrupt Service Routine) : 인터럽트를 처리하기 위해 커널이 실행하는 함수
  • 인터럽트를 발생 시키거나 각 장치별로 인터럽트 핸들러가 있다.
  • 리눅스의 인터럽트 핸들러는 일반적인 C함수이며 표준적인 방식으로 커널이 핸들러에 정보를 전달할 수 있게 정해진 함수 원형을 사용해야 한다는 점만 제외하면 보통함수와 다르지 않다.
  • 인터럽트 함수의 특징은 인터럽트가 발생했을 때 커널이 호출한다는 점과 인터럽트 컨텍스트 (interrupt context)라는 특별한 컨텍스트에서 실행된다는 점
  • 인터럽트는 언제라도 발생할 수 있으므로 인터럽트 핸들러도 언제든지 실행될 수 있다. 중단된 코드를 최대한 빨리 다시 실행하려면 핸들러의 실행 속도가 빨라야 한다.
  • 따라서 하드웨어 입장에서는 운영체제가 지체없이 처리하는 것이 중요하지만, 시스템의 다른 부분 입장에서는 인터럽트 핸들러의 실행시간이 가능한 짧은 것이 중요하다.

 

 

반응형
반응형

리눅스 커널의 구현 방식

→ 리눅스 커널은 구조체를 연결 리스트로 바꾸는 대신 구조체에 연결 리스트의 노드를 넣는 방식을 사용

 

 

연결 리스트 구조체

→ 연결 리스트 코드는 <linux.list.h>헤더 파일에 정의되며 자료 구조는 위에와 같다.

  • next 포인터는 리스트의 다음 노드를 가르킴

  • prev 포인터는이전 노드를 가르킴

 

이렇게 하면 fox 구조체의 list_head.next는 다음 항목을 가리키고, list_head.prev는 이전 항목을 가리키게 할 수 있다.

커널은 이런 연결리스트를 조작하는 함수를 제공한다.

반응형
반응형

리눅스 커널 코드에서 사용 내장 자료 구조에 대해 소개 하도록 하겠습니다.

 

커널 개발자들은 해결책을 스스로 고안하기 보다는 이런 자료구조를 최대한 활용해야 합니다.

 

앞으로 다룰 자료구조는

  • 연결 리스트
  • 이진트리

연결리스트는

  • 리눅스 커널에서 가장 많이 사용하는 간단한 자료구조
  • 노드라고 부르는 가변적인 개수의 데이터를 저장하고 관리하는 기능을 제공
  • 동적으로 데이터를 생성해 리스트에 추가
  • 그러므로 컴파일 시접에 미리 개수를 알 수 없는 데이터 관리 가능
  • 데이터가 인접한 메모리 공간에 모여 있지 않으며
  • 따라서 , 데이터를 서로 연결시킬 방법이 있어야 하므로 next라는 포인터 사용

단일 연결 리스트와 이중 연결 리스트

 

 

연결 리스트 내에서 이동

  • 연결 리스트내의 이동은 선형으로 일어난다.

  • 한 항목을 참조하고 다른 포인터를 따라가 다음 항목을 참조한다.

  • 이 과정을 반복하며 해당 데이터에 접근한다.

  • 임의순서로 데이터에 접근하는 동작이 중요한 상황에는 연결리스트는 부적절

  • 전체 리스트를 차례대로 훑는 작업이나 항목으을 동적으로 삽입하고 제거하는 작업에 적합

  • 연결리스트 구현에서 리스트의 '시작' 부분에 접근하기 쉽게 리스트의 첫번째 항목을 헤드(head)라고 부르는 특별한 포인터로 표시하는 경우가 많다

  • 환형이 아닌

     

    리스트라면 다음항목을 가라크니는  포인터가 Null인 경우 마지막 항목이 된다.

  • 환형 리스트는 첫번째 항목이 마지막 항목이 된다.

리눅스 커널의 구현 방식

리눅스 커널은 구조체를 연결리스트로 바꾸는 대신 구조체에 연결리스트의 노드를 넣는 방식을 사용

 

연결 리스트 구조체

 

 

반응형
반응형

리눅스 커널을 분석하기 위해서는 반드시 소스코드 레벨에서 분석이 필요할 때가 있습니다. 물론 모든 경우에 소스코드 레벨 분석이 필요한 것은 아니지만 ... 많은 경우에 필요로 하죠...

 

그때 많이 사용하게 되는 소스코드 분석 준비에 대해 알아보겠습니다.

 

source insight나 eclipe와 같은 GUI기반의 훌륭한 소스 Tool들이 있지만 리눅스 커널 소스코드를 분석하기에는 약간 모자란 부족한 점이 있습니다. 자신의 PC의 사양이 좋다면 상관 없지만 리눅스 소스코드는 100MB가 넘는 엄청난 용량을 자랑하고 이것을 한 프로젝트 구동하게 될 경우에는 문제가 발생할 수 있죠

 

그래서 저는 언제나... vim과 ctag를 이용합니다.

 

vim은 테스트 에디터이고 ctag는 소스코드의 tag를 분석해주는 tool입니다. 그밖에 다른 플러그인들도 많이 있지만 저는 이렇게를 가장 많이 사용합니다.

 

우선 설치 방법은 우분투를 기준으로

 

apt-get install vim ctags -y

 

입력하면 설치가 됩니다.

 

그 다음에는 ctag를 이용해 태그파일을 생성해야 합니다.

이때 2가지 방법이 있습니다

 

1. 소스코드 상위 루트에서 #ctags -R을 사용해서 생성

2. 소스코드 상위 루트에서 #make tags를 사용해서 생성

 

1번과 2번의 차이점은 2번으로 생성할 경우 해당 커널 config 파일을 기반으로 태그 파일을 생성하게 됩니다. 이유는 커널은 대양한 아키텍처를 포함하기 때문에 1번 방법으로 할 경우 중복된 태그가 다수 만들어집니다. 물론 아키텍처 별로 분석을 해야 할 경우에는 1번을 사용해야 되지만 자신의 현재 시스템에 적합한 소스코드를 분석하기 위해서는 2번을 사양해야 됨을 알아두시길 바랍니다.

 

마지막으로 제가 사용하는 vim 설정파일을 제안하는 것으로 마무리 하겠습니다.

 

 set shiftwidth=2             ">>나 << 사용시 들여쓰기 간격을 지정합니다.
set visualbell            "사용자실수를 경고할때 비쥬얼 벨을 사용함                 
set nobackup                 "백업 파일을 생성하지 않음
set cindent                  "C스타일의 들여쓰기를
set ruler                    "커서의 위치를 표시함사용함
set autoindent               "자동들여쓰기를 사용
set smartindent              "지능적인 들여쓰기 사용
set incsearch                "키워드를 입력할때 마다 검색하는 점진 검색을 사용
set ruler                    "커서의 위치를 표시함
set showcmd                  "화면마지막 라인에 커맨드 표시
set backspace=2              "삽입모드에서 백스페이스를 계속 허용
set wrapscan                 "찾기에서 파일의 맨끝에 이르면 처음부터 다시 찾음
set title                    "타이틀 바에 현재 편집중인 파일을 표시
set number                   "줄번호표시
set ts=2                     "tab 키를 스패이스바 2개로 구분     
syntax on                    "구문강조기능 사용
filetype on                  "파일종류에 따라 구문을 강조
set background=dark          "배경색을 어두운 색으로
colorscheme evening          "색상테마를 evning으로
set history=1000             "편집기록을 1000개 등록
set hlsearch                 "검색어 기능 강조
set ignorecase               "검색시 대/소문자 구분 없음
set showmatch                "닫는 괄호를 입력할 때
set novisualbell             "화면깜박거리지 않기
set backspace=indent,eol,start  "줄의 끝, 시작, 들여쓰기에서 백스페이스를 사용하면 이전줄과 연결

"################### 단축키 설정 ####################"
"파일 버터간 이동 "
map ,1 :b!1<cr>
map ,2 :b!2<cr>
map ,3 :b!3<cr>
map ,4 :b!4<cr>
map ,5 :b!5<cr>
map ,6 :b!6<cr>
map ,7 :b!7<cr>
map ,8 :b!8<cr>
map ,9 :b!9<cr>
map ,0 :b!0<cr>
map ,w :bw <cr>

"F2 == 폴딩하기  "
map <F2>  z]}zf

"F3 == 저장 "
map <F3> : w! <CR>
map <F3> <ESC> <F3>

"F4 == 탭열기, Ctrl+h,l로 탭이동 "
map <F4> : tabnew<CR>
map <C-h> gT
map <C-l> gt

"F5 == 컴파일 후 결과보기 / 오류난 라인으로 이동
map <F5> : w<cr> :make<cr> :ccl<cr> :cw<cr>

"F6 == Taglist 열기
map <F6> : TlistToggle<CR>

"F7 == 태그리스트 넘어 다니기
map <F7> <c-w> <c-w>

"F8 == 디렉토리 목록 열기
map <F8> : NERDTree<CR>

"F12 == 저장후 종료
map <F12> : wq! <CR>
map <F12> <ESC> <F12>


"=============== ctags 설정 ================"
set tags=./tags,../tags,../../tags,/usr/src/linux/tags,/usr/src/mango100_kernel_2010_07_15/tags


"세부 코드 보여주기 "
if version >= 500
func! Sts()
 let st = expand("<cword>")
 exe "sts ".st
endfunc 
nmap ,st :call Sts() <CR>

func! Tj()
 let st = expand("<cword>")
 exe "tj ".st
nmap ,tj :call Tj() <CR>
endfunc
endif

"=============== cscope 설정 ================"
"set csprg=/usr/bin/cscope
"set csto=0
"set cst
"set nocsverb

if filereadable("./cscope.out")
 cs add cscope.out
else
 cs add /usr/src/linux/cscope.out
endif
set csverb

func! Css()
 let css = expand("<cword>")
 new
 exe "cs find s ".css
 if getline(1) = ""
   exe"q!"
 endif
endfunc
nmap ,css :call Css()<cr>

func! Csc()
 let css = expand("<cword>")
 new
 exe "cs find c ".csc
 if getline(1) = ""
   exe"q!"
 endif
endfunc
nmap ,csc :call Csc()<cr>

func! Csd()
 let csd = expand("<cword>")
 new
 exe "cs find d ".csd
 if getline(1) = ""
   exe"q!"
 endif
endfunc
nmap ,csd :call Csd()<cr>

func! Csg()
 let csg = expand("<cword>")
 new
 exe "cs find g ".csg
 if getline(1) = ""
   exe"q!"
 endif
endfunc
nmap ,csg :call Csg()<cr>

 

"============== Man page 설정 ==============="
func! Man()
 let sm = expand("<cword>")
 exe "!man -S 2:3:4:5:6:7:8:9:tcl:n:l:p:o ".sm
endfunc
nmap ,ma :call Man()<cr><cr>

 

"############### taglist ##########################"
let Tlist_Display_Tag_Scope = 1 "태그 범위를 표시합니다
let Tlist_Display_Prototype = 1 "함수의 원형을 표시합니다
let Tlist_Sort_Type="name"      "태그리스트를 이름 순서로 표시합니다.

 

반응형

+ Recent posts