커널의 역할 및 구조

커널의 역할

모든 운영 체제에서 커널은 소프트웨어의 입ㆍ출력 요청을 관리하고 CPU 및 기타 장치에 대한 데이터 처리 명령으로 변환하는 프로그램입니다.
커널은 프로세스 관리, 메모리 관리, 파일 시스템, 장치 제어, 네트워킹 등을 담당합니다.

 

1. 프로세스 관리
프로세스의 생성 및 소멸을 담당합니다. 
커널은 프로세스 스케쥴러를 이용하여 여러 프로세스가 동작 할 수 있도록 각 프로세스를 생성하고 제거합니다.

2. CPU 스케쥴링 동기화
여러 프로세서를 병렬로 연결하는 경우 다중 프로세서의 효율적인 관리 기법을 제공합니다.

3. 메모리 관리
시스템의 메모리 하드웨어를 효율적으로 관리합니다.
각각의 프로세스가 독립적인 공간에서 실행될 수 있도록 가상 주소 공간 및 이 가상 메모리 관리를 바탕으로

보조 기억 장치와 연동하여 물리적인 한계를 극복 할 수 있는 기능을 제공합니다.

4. 파일 시스템 관리
리눅스 커널은 시스템에 동작하는 모든 자원을 파일처럼 다룰 수 있도록 인터페이스를 제공합니다. 
가상 파일 시스템을 이용하여 여러 파일 시스템 타입을 지원합니다.

5. 디바이스 관리
커널은 하드웨어를 제공하기 위해서 입ㆍ출력 요청 검증, 입ㆍ출력 요청 작업의 스케쥴링, 주변장치와 메모리 간의 자료 전송,

입출력 제어기 관리, 인터럽트 요청 및 처리와 같은 기능을 수행합니다.

6. 네트워크 관리
리눅스 커널은 주로 네트워크를 필요로 하는 시스템에서 개발되었기 때문에 우수한 네트워크 관리 시스템을 갖추고 있습니다. 
네트워크 스택을 이용하여 응용 프로그램과 네트워크 디바이스 드라이버를 연결하며 효울적인 네트워크 처리를 구현하고 있습니다.

커널의 구조

 

리눅스 디바이스 드라이버

디바이스 드라이버의 필요성

디바이스 드라이버는 커널 모드에서 실행되는 프로그램으로 각 장치의 하드웨어와 직접 상호 작용 할 수 있습니다.
디바이스 드라이버의 주요 목적은 하드웨어 장치를 사용하는 응용 프로그램 또는 운영 체제 사이에서 중간 역할을 하여 

추상화를 제공하는 것입니다.

 

사용자 응용 프로그램을 하드웨어에 직접 액세스하는 것은 많은 위험성이 존재합니다. 
여기서 장치 드라이버의 역할은 이러한 호출을 실제 하드웨어에서 작동 할 수 있도록 장치별로 매핑하는 것입니다.
최종 사용자가 사용하는 특정 하드웨어에 관계없이 더 높은 수준의 응용 프로그램 코드를 작성 할 수 있도록 도와줍니다.

Linux의 장치 드라이버 프로그래밍 인터페이스는 드라이버를 나머지 커널과 별도로 빌드 할 수 있으며 필요할 때 런타임에 사용할 수 있습니다. 
이 모듈 방식으로 Linux 드라이버를 보다 쉽게 ​​작성하고 유지 관리가 가능합니다.

 

런타임에 커널에 추가할 수 있는 코드를 모듈이라고 합니다.
지원되는 모듈 중 하나는 장치 드라이버이며, insmod 프로그램에 의해 작동 중인 커널에 동적으로 링크되고 rmmod 프로그램에 의해

   링크가 해제 될 수 있습니다.

 

디바이스 드라이버의 종류

리눅스에서는 세 가지 기본 장치 유형을 구분합니다.

 

문자 장치

문자 장치는 파일처럼 바이트 스트림으로 액세스 할 수 있는 장치입니다.

char 드라이버는 일반적으로 open, close, read 및 write 시스템 호출을 구현합니다. 

블록 장치

블록 장치는 파일 시스템을 호스팅 할 수 있는 하드 디스크와 같습니다. 
리눅스에서 문자 장치처럼 취급되고, 문자 장치와 마찬가지로 바이트 수의 전송을 허용합니다. 

 

네트워크 장치

네트워크 인터페이스 / 장치는 일반적으로 하드웨어이며 다른 호스트와 데이터를 교환 할 수 있습니다. 
네트워크 드라이버는 개별 연결에 대해 알 수 없고 커널의 네트워크 하위 시스템에 의해 구동되는 패킷 (전송, 수신 등) 만 처리합니다. 
문자 및 블록 장치와 달리 eth0 같은 네트워크 인터페이스는 파일 시스템의 노드에 직접 매핑되지 않고, 커널과 드라이버 간

통신 방법도 다릅니다. 읽기와 쓰기 대신 커널은 패킷 전송과 관련된 기능을 호출합니다.

 

유닉스 디자인의 파일 시스템 개념

파일 시스템은 파일을 관리하는 장치를 말합니다.

파일 시스템 간의 호환성은 windows와 unix 및 mac 등은 기본적으로 그 상태의 파일을 사용 할 수 없지만,

파일을 주고받으려면 전용 애플리케이션을 사용하거나 호환성 있는 파일 포맷을 사용해야 합니다.

Linux는 파일 시스템 모듈의 개념을 지원하며, S/W 인터페이스는 파일 시스템 inode, 디렉토리, 파일 및 수퍼 블록에서 수행 가능한

다양한 작업을 선언합니다.

 

커널에 디바이스 드라이버 로드하기

 Linux 시스템은 커널 모드와 사용자 모드로 나뉩니다. 
하드웨어 장치는 커널 모드에서만 액세스 할 수 있고 드라이버는 사용자 모드의 코드가 하드웨어 장치에 액세스가 가능한 커널 모드에서 제공되는 API로 간주됩니다.

test_module.c 파일 - 커널에 로드할 디바이스 드라이버 파일

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");

int test_init(void)
{
    printk(KERN_INFO "TEST_MODULE_INIT\n");
    return 0;
}

void test_exit(void)
{
    printk(KERN_INFO "TEST_MODULE EXIT\n");
}

module_init(test_init);
module_exit(test_exit);


Linux 드라이버는 C언어를 사용하여 개발되었으며 이는 일반적인 사용 방식과 다릅니다. 
우리가 자주 사용하는 것은 커널에 존재하지 않는 Libc 라이브러리입니다. 
드라이버는 커널에서 실행되는 프로그램이지만 커널의 라이브러리 함수를 사용합니다.

드라이버 코드에는 하나의 진입 점과 하나의 종료 점이 있습니다. 
드라이버를 커널에 로드하면 위 코드에서 test_init 함수 인 module_init 함수로 정의 된 함수가 실행됩니다. 
드라이버가 커널에서 언로드 되면 module_exit 함수에 의해 정의 된 함수가 호출되는데, 위 코드에서 test_exit 함수입니다.
위의 코드는 드라이버가 로드 될 때 TEST_MODULE_INIT를 출력하고 드라이버가 언로드 될 때 TEST_MODULE EXIT를 출력합니다.

 

디바이스 드라이버 컴파일

드라이버는 make 명령으로 컴파일을 해야 하며 Makefile은 다음과 같습니다.

obj-m := test.o 명령을 통해 test.o를 test.ko로 컴파일하는 것을 의미하며 .ko 파일은 커널 모듈 파일입니다.

 

Makefile 파일

obj-m := test_module.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.ko
rm -rf *.mod.*
rm -rf .*.cmd
rm -rf *.o

 

커널에 모듈 적재 및 제거하기

insmod : 모듈을 커널에 적재합니다.

rmmod : 커널에서 모듈을 제거합니다.

lsmod : 커널에 적재된 모듈 목록을 출력합니다.

depmod : 모듈 간 의존성 정보를 생성합니다.

modprobe : 모듈을 커널에 적재하거나 제거합니다.

 

ex. # insmod test_module.ko // test_module.ko 모듈을 커널에 로드

       # rmmod test_module // test_module 모듈을 커널에서 제거

 

아래의 콘솔창에서 lsmod 명령어를 통해 test_module이 커널에 적재된 것을 확인 할 수 있습니다.

 

mknod를 이용한 장치 파일 생성하기

mknod라는 명령어는 장치파일 (FIFO, Block, Character)을 만들 때 사용하는 명령어입니다.
일반적으로 블록 디바이스, 문자 디바이스라고 하는 파일을 생성할 때 사용하며 리눅스 시스템에 새로 장착되는 하드웨어의 장치 파일 생성 시에 주로 사용합니다. 장치 파일에는 주번호 (Major Number)와 부번호 (Minor Number)가 필요하며, 장치 파일 생성 시 지정해주어야 합니다. 

형식 : mknod ([옵션]) [장치명] [타입] ([주번호 부번호])

[타입]에는 "b", "c" 또는 "u"가 설정되며, 블록장치파일 또는 문자장치파일을 생성할 때 반드시 주번호와 부번호를 지정해야 합니다.
하지만 [타입]에 "p"를 지정하여 FIFO파일을 생성할 때에는 주번호와 부번호를 생략 할 수 있습니다.

 

파일생성시 초기 퍼미션 = 0644
p = FIFO파일
b = Block특수파일
c,u = Character특수파일

 

mknod 명령어를 사용하면 장치 파일 생성이 가능하고, 아래의 터미널에서 test_module 장치가 올라간 것을 확인할 수 있습니다.

/dev : 이 디렉토리에는 모든 장치에 대한 특수 장치 파일이 들어 있습니다.

/proc/devices : 현재 실행중인 커널 (블록 및 문자)로 구성된 장치 드라이버 목록

 

커널에 모듈 적재 및 장치 파일 생성 쉘

ins_driver.sh 파일

#! /bin/sh
module="test_module"
device="test_module"
group="root"
mode="666"

/sbin/insmod -f $module.ko $* || exit 1

rm -f /dev/${device}

mknod /dev/${device} c 60 0

chgrp $group /dev/${device}
chmod $mode  /dev/${device}

 

커널에 적재된 모듈 제거 및 장치 파일 삭제

rm_driver.sh 파일

#! /bin/sh
module="test_module"
device="test_module"

/sbin/rmmod --force -v $module || exit 1

rm -f /dev/${device}