행복한 하루

Raspberry Pi – Linux Device Driver 만들어 보기-2 (장치 번호와 접근해보기) 본문

RaspberryPi/DeviceDriver

Raspberry Pi – Linux Device Driver 만들어 보기-2 (장치 번호와 접근해보기)

변화의 물결 2022. 7. 18. 19:12

 

 

안녕하세요.

 

  이전 내용에서 디바이스 드라이버 소스의 간단한 형태를 잡아 보았다면 이번에는 디바이스에 장치 번호를 할당해서 접근하는 방법을 알아보도록 하겠습니다. 커널 레벨, 유저 레벨 등의 이론적인 내용은 아주 간략하게 설명했고, 실습 위주로 정리해보았습니다.


1.  사전 준비

  이전 파일을 좀 더 디바이스 같은 느낌(?)으로 파일 이름을 변경합니다. (작업하는 디렉터리 이름은 day2로 변경했습니다. 

pi@raspberrypi:~/DriverStudy/day2 $ mv day1_module.c dev_nr.c

 

  그러면 Makefile도 같이 내용을 수정해줍니다.

obj-m += dev_nr.o

 

2. 디바이스 드라이버 소스 수정

pi@raspberrypi:~/DriverStudy/day2 $ vim dev_nr.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>

/* Meta Information */
MODULE_LICENSE("GPL");
// MODULE_AUTHOR("Johannes 4 GNU/Linux"); refer source site
MODULE_AUTHOR("Student GNU/Linux");
MODULE_DESCRIPTION("Registers a device nr. and implement some callback functions");

/*
 * @brief This fuction is called, whe the device file is opened
 */
static int driver_open(struct inode *device_file, struct file *instance){ 
	printk("dev_nr - open was called!\n");
	return 0;
}

/*
 * @brief This fuction is called, whe the device file is closed
 */
static int driver_close(struct inode *device_file, struct file *instance){ 
	printk("dev_nr - close was called!\n");
	return 0;
}

static struct file_operations fops = {
	.owner = THIS_MODULE,
	.open = driver_open,
	.release = driver_close
};


#define DD_MAJOR 90

/*
 @ brief This function is called, when the module is loaded into the kernel
 */
static int __init driver_init(void) {
	int retval;

	printk("Hello, Driver dev_nr!\n");
	/* register device nr */
	retval = register_chrdev(DD_MAJOR, "dev_nr", &fops);

	if(retval == 0) {
		printk("dev_nr - registered Device number Major :%d, Minor : %d\n", DD_MAJOR,0);
	}
	else if(retval > 0) {
		printk("dev_nr - registered Device number Major :%d, Minor : %d\n", retval>>20,retval&0xfffff);

	} else {
		printk("Could not register device number!\n");
		return -1;
	}

	return 0;
}


/**
 * @brief This function is called, when the module is removed from the kernel
 */
static void __exit driver_exit(void) {
	unregister_chrdev(DD_MAJOR, "dev_nr");
	printk("Bye Driver Day2\n");
}

module_init(driver_init);  
module_exit(driver_exit);

 

  - 빌드해서 드라이버 파일을 생성합니다.

pi@raspberrypi:~/DriverStudy/day2 $ make

3. 디바이스 드라이버 동작확인

  - 장치 드라이버로 등록되어 번호를 할당받았는지 확인합니다. 만약 Major 90번이 이미 할당되어 있을 경우 다른 번호로 입력하여 생성하면 됩니다. 

pi@raspberrypi:~/DriverStudy/day2 $ sudo insmod dev_nr.ko
pi@raspberrypi:~/DriverStudy/day2 $ cat /proc/devices | grep dev_nr
pi@raspberrypi:~/DriverStudy/day2 $ sudo rmmod dev_nr
pi@raspberrypi:~/DriverStudy/day2 $ cat /proc/devices | grep dev_nr

 

  

 - 장치들과 연결할 수 있는 캐릭터 디바이스 노드를 생성합니다. 좀 더 상세한 내용은 참조사이트를 도움받으시면 됩니다. 여기서는 간단하게 설명드리면 리눅스에서는 관리해야 할 자원들을 파일 단위로 관리하고 있기 때문에, 디바이스 파일을 만들어 접근해야 하고, 애플리케이션(User Level)에서는 디바이스 드라이버로(Kernel Level)에 직접 접근할 수 없기 때문에 이 두 가지의 역할을 해주는 디바이스 노드 파일을 만듭니다. 

pi@raspberrypi:~/DriverStudy/day2 $ sudo mknod /dev/dev_nr c 90 0
pi@raspberrypi:~/DriverStudy/day2 $ ls /dev/dev_nr -al

 

  - 출력한 로그들을 확인할 수 있습니다.

pi@raspberrypi:~/DriverStudy/day2 $ dmesg | tail -n 3

 

 

  - 실제적으로 응용프로그램에서 디바이스 드라이버를 접근해보도록 합니다. write 권한이 필요한 디바이스 드라이버라면 노드에 쓰기 권한도 추가해줍니다.

pi@raspberrypi:~/DriverStudy/day2 $ sudo chmod 666 /dev/dev_nr

  -  드라이버를 커널에 추가 시킵니다.

pi@raspberrypi:~/DriverStudy/day2 $ sudo insmod dev_nr.ko

 4. 응용프로그램 소스 수정

  - 간단하게 디바이스 드라이버에 접근하는 테스트 응용프로그램 코드를 작성합니다.

pi@raspberrypi:~/DriverStudy/day2 $ vim open_dev_nr.c

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main() {

        int dev = open("/dev/dev_nr", O_RDONLY);

        if(dev == -1) {
                printf("Opening was not possible!\n");
                return -1;
        }
 
        printf("Opening was successfull!\n");
        close(dev);

        return 0;
}

 

   - 응용프로그램을 컴파일 하고 실행합니다.

pi@raspberrypi:~/DriverStudy/day2 $ gcc open_dev_nr.c -o open_dev_nr
pi@raspberrypi:~/DriverStudy/day2 $./open_dev_nr

  - 디바이스 드라이버의 Open, Close 함수가 호출된 것을 알 수 있습니다. 즉, 응용프로그램에서 device driver에 노드를 통해서 Open, Close를 할 때 Device Driver에 등록된 Open, Close 함수가 호출되는 것을 확인할 수 있습니다. 

pi@raspberrypi:~/DriverStudy/day2 $ dmesg | tail -n 5

 

감사합니다.

 

 

<참고 사이트>

1. Let's code a Linux Driver - 2: Device Numbers and Files

https://youtu.be/h7 ybJMYyqDQ? list=PLCGpd0 Do5-I3 b 5 TtyqeF1 UdyD4 C-S-dMa

2. 디바이스 드라이버(device driver).

https://velog.io/@jinh2352/%EB%94%94% EB% B0%94% EC% 9D% B4% EC% 8A% A4-%EB%93% 9C% EB% 9D% BC% EC% 9D% B4% EB% B2%84

3. [Linux] Device node

https://talkingaboutme.tistory.com/entry/Linux-Device-node

4. 리눅스 디바이스 드라이버 프로그래밍

https://jeongchul.tistory.com/111

day2.zip
0.00MB

 

Comments