Device Node는 Device File
로 HW 컨트롤을 한다. ./dev
에서 장치들을 관리한다.
ls-al ./dev
를 하게 되면, 다음 이미지와 같이 확인할 수 있다.
Major Number(주번호) : 디바이스 종류
Minor Number(부번호) : 구분하기 위한 용도
sudo mknod ./[파일명] c 100 200
: chardev로 주번호 100 보조번호 200인 device file 생성
커널 내부에서 디바이스 파일과 커널 모듈을 연결하여, app 단에서 디바이스 파일을 열어서 커널 모듈을 제어한다.
nobran.c
기본형태
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int nobrand_init(void) {
printk( KERN_INFO "OK HELLO NOBRAND!!\n");
return 0;
}
static void nobrand_exit(void) {
printk( KERN_INFO "BYE BYE\n\n");
}
module_init(nobrand_init);
module_exit(nobrand_exit);
Device File
./dev
는 장치 파일을 제어해주는 디렉토리, 디바이스 파일은 ./dev에 저장되어 있어야 한다.
sudo mknod /dev/nobrand c 100 0
sudo chmod 666 /dev/nobrand
app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
printf("OPEN FILE!!\n");
int fd = open("/dev/nobrand", O_RDONLY); // 디바이스 파일에 접근하기
if (fd == -1)
{
printf("FILE OPEN ERROR\n");
return 0;
}
printf("CLOSE FILE!!\n");
close(fd);
return 0;
}
nobrand.c
완성본
#include <linux/module.h>
#include <linux/fs.h>
#define NOD_NAME "nobrand"
#define NOD_MAJOR 100 // Device File의 Major Number
MODULE_LICENSE("GPL");
static int nobrand_open(struct inode *inode, struct file *filp) {
printk( KERN_INFO "OPEN!!!\n");
return 0;
}
static int nobrand_release(struct inode *inode, struct file *filp) {
printk( KERN_INFO "CLOSE!!!\n");
return 0;
}
static struct file_operations fops = {
.open = nobrand_open, // app.c에서 open 명령어 실행시 실행
.release = nobrand_release // app.c에서 close 명령어 실행시 실행
};
static int nobrand_init(void) { // insmod 명령어 입력시 실행
printk( KERN_INFO "OK HELLO NOBRAND!!\n"); // KERN_INFO : log에 print하기 위해
if (register_chrdev(NOD_MAJOR, NOD_NAME, &fops) < 0) { // device file에 접근 실패시 실행
printk( KERN_INFO "ERROR!!! register error\n");
}
return 0;
}
static void nobrand_exit(void) { // rmmod 명령어 입력시 실행
unregister_chrdev(NOD_MAJOR, NOD_NAME);
printk( KERN_INFO "BYE BYE\n\n");
}
module_init(nobrand_init);
module_exit(nobrand_exit);
makefile
KERNEL_SRC=/lib/modules/$(shell uname -r)/build
obj-m := nobrand.o
go:
make -C $(KERNEL_SRC) M=$(PWD) modules
clean:
make -C $(KERNEL_SRC) M=$(PWD) clean
KERNEL_SRC
경로에 Makefile
이 존재한다. 해당 Makefile에 선언해준 obj-m
이 있다.
PWD(현재 경로)의 모든 파일을 커널에 접근하여 make를 통해 나온 결과물을 다시 가져오게된다.
make
를 통해 커널 모듈 빌드
sudo insmod ./nobrand.ko
를 통해 커널에 집어넣기
gcc ./app.c -o ./app
을 통해 app 파일 빌드
./app
을 통해 app에서 커널 모듈에 접근
sudo rmmod nobrand
를 통해 커널에서 빼기
참고 : ko 파일은 test용으로 app단에 존재하는거지, 원래는 커널에 있어야한다.
재부팅시 필요한 파일들을 만들어주는데, 상단에서 만든 nobrand 파일은 필수가 아니므로 다시 만들어줘야한다.
$ make clean
$ rm app
$ sudo mknod /dev/nobrand c 100 0
$ sudo chmod 666 /dev/nobrand
$ make
$ gcc app.c -o app
터미널 새로 키고 $ dmesg -w
$ sudo insmod nobrand.ko
$ ./app
$ sudo rmmod nobrand
$ make clean
$ rm app
app gcc를 추가
KERNEL_SRC=/usr/src/linux
TARGET := app
obj-m := nobrand.o
all: driver app
driver:
make -C $(KERNEL_SRC) M=$(PWD) modules
app:
$(CC) -o $@ $@.c
clean:
make -C $(KERNEL_SRC) M=$(PWD) clean
rm -f *.o $(TARGET)
source ./alias.sh
로 실행가능
매크로 함수로, sd
로 커널 진입 , sc
로 커널 빠져나오기
alias sc='sudo insmod ./nobrand.ko'
alias sd='sudo rmmod nobrand'