Application과 Device Driver 개발
1. Device File 제작
# mknod : 특수 파일 만드는 유틸리티
# device file을 만들 address, type과 major, minor number 설정
$ sudo mknod /dev/nobrand c 100 0
# 파일의 권한 설정
$ sudo chmod 666 /dev/nobrand
2. Device Driver 제작
nobrand.c
1 #include <linux/module.h>
2 #include <linux/fs.h>
3
4 #define NOD_MAJOR 100
5 #define NOD_NAME "nobrand"
6
7 MODULE_LICENSE("GPL");
8
9 // inode : Device File의 inode 정보를 가짐
10 // insmod 시, inode에는 주번호 / 부번호 정보도 적힌다.
11 // filp : Device File이 App에서 어떤 형태로 읽혔는 지의 정보가 들어있음 (app에서 O_RDWR로 읽음)
12 static int nobrand_open(struct inode *inode, struct file *filp){
13 printk( KERN_INFO "welcome\n");
14 return 0;
15 }
16
17
18 // printk : Linux kernel에서 메세지를 출력하는 함수
19 // KERN_INFO : 메세지의 log level을 지정하는 함수 - 디버깅 및 정보 출력에 쓰임
20 // 이외에 KERN_ERR, KERN_WARNING 등이 있음
21 static int nobrand_release(struct inode *inode, struct file *filp){
22 printk( KERN_INFO "release\n");
23 return 0;
24 }
25
26 // 구조체 지정 초기화를 이용한 방법
27 // app level에서 "open" system call --> nobrand_open 함수가 호출
28 // app level에서 "close" system call --> nobrand_release 함수가 호출
29 static struct file_operations fops = {
30 .open = nobrand_open,
31 .release = nobrand_release,
32 };
33
34 static int nobrand_init(void)
35 {
36 // Device driver가 insmod 될 때, chrdev를 등록
37 // chrdev : 문자 기반 디바이스 파일을 지원하는 device driver를 개발하기 위한 interface
38 // 실패 시, INIT FAIL 출력
39 if( register_chrdev(NOD_MAJOR, NOD_NAME, &fops) < 0){
40 printk("INIT FAIL\n");
41 }
42 printk( KERN_INFO "hi\n");
43 return 0;
44 }
45
46 static void nobrand_exit(void)
47 {
48 // Device driver가 rmmod 될 때, chrdev 해제
49 unregister_chrdev(NOD_MAJOR, NOD_NAME);
50 printk( KERN_INFO "bye\n");
51 }
52
53 module_init(nobrand_init);
54 module_exit(nobrand_exit);
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
- major : 디바이스 드라이버의 주 번호 / 커널 내부에서 디바이스 파일을 식별하는데 사용
- name : 디바이스 파일의 이름을 지정
- fops : 디바이스 파일에서 지원하는 입출력 연산을 정의하는 struct file_operations 구조체를 가리킴
함수의 기능
1. 커널은 major 번호를 사용하여 디바이스 파일을 연결
2. 해당 파일에 대한 입출력 요청을 처리할 수 있도록 fops 구조체를 연결
3. 추후 poll() 함수를 사용하여 디바이스 파일에 대한 이벤트 감지 가능
Makefile
1 # 커널 헤더 파일 위치 정의
2 KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build
3
4 # 컴파일러를 gcc로 설정
5 CC = gcc
6
7 # 빌드 대상 응용 프로그램 이름 정의
8 TARGET := app
9
10 # 커널 모듈 오브젝트 파일 이름 정의 / obj-m은 Kbuild에서 사용되는 변수 중 하나
11 obj-m := nobrand.o
12
13 all : driver app
14
15 driver:
16 make -C $(KERNEL_HEADERS) M=$(PWD) modules
17
18 app:
19 $(CC) -o $@ $@.c
20
21 clean:
22 make -C $(KERNEL_HEADERS) M=$(PWD) clean
23 rm -f *.o $(TARGET)
- make all : 전체를 build
- make driver : driver 빌드
- make app : application 빌드
- make clean : driver와 application 제거
3. Application 제작
app.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7
8 int main(){
9 int fd = open("/dev/nobrand", O_RDWR);
10 if (fd < 0){
11 printf("ERROR\n");
12 close(fd);
13 exit(1);
14 }
15
16 printf("GO\n");
17 close(fd);
18 return 0;
19 }
man page를 활용한 헤더 파일 추가
Device file을 open/close하는 system call 사용
4. 동작 테스트
다른 Terminal을 오픈해서 커널 로그 모니터링을 통해 확인할 것
$ make
$ sudo insmod ./nobrand.ko
$ ./app
app Level 의 system call인 open() / close() 이 호출되면,
- Device File 을 통해서 system call 이 Device Driver 를 빌드한 결과물 ( .ko 파일) 에
- nobrand_open / nobrand_release 가 호출됨
$ sudo rmmod nobrand
결과
1) 디바이스 파일 생성
sudo mknod /dev/nobrand c 100 0
sudo chmod 666 /dev/nobrand
2) Device Driver 를 커널에 등록 시
insmod → nobrand_init() → register_chrdev() → hi
3) ./app 실행 시
open() syscall → nobrand_open() → welcome
close() syscall → nobrand_release() → release
4) Device Driver 를 커널에서 제거 시
rmmod → nobrand_exit() → unregister_chrdev() → bye
'IT_Study > Personal Project' 카테고리의 다른 글
Raspberry Pi와 SenseHat을 활용한 자이로스코프 게임 만들기 (0) | 2023.04.19 |
---|---|
API 활용 Web 프로젝트 (2) : Naver Datalab API를 활용한 Data Visualization 하기 (0) | 2023.03.17 |
API 활용 Web 프로젝트 (1) : 요구사항에 따른 DB 설계 및 EC2 상에서의 API 서버 배포 방법 (0) | 2023.03.07 |