리눅스/디바이스 드라이버

[디바이스 드라이버] 4. 장치파일과 디바이스 드라이버 연결하기

다락공방 2024. 9. 2. 01:38

목표

이번엔 장치파일과 디바이스 드라이버를 만들어서 연결해볼 것이다.

그렇게해서 애플리케이션(User Level)에서는 디바이스 드라이버로(Kernel Level)에 장치파일을 이용해 접근해본다.

 


디바이스 드라이버 모듈

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("IH02");
MODULE_DESCRIPTION("user_to_driver");

static int driver_open(struct inode *device_file, struct file *instance){ 
	printk("open was called!\n");
	return 0;
}

static int driver_close(struct inode *device_file, struct file *instance){ 
	printk("close was called!\n");
	return 0;
}

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


#define MAJOR_NUM 100


static int __init driver_init(void) {
	int retval;

	printk("Driver init!\n");
	
	retval = register_chrdev(MAJOR_NUM, "IH_driver2", &fops);
	if(retval == 0) {
		printk("Device Major Number :%d, Minor : %d\n", MAJOR_NUM,0);
	}
	else if(retval > 0) {
		printk("Registered Device number Major :%d, Minor : %d\n", retval>>20,retval&0xfffff);

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

	return 0;
}





static void __exit driver_exit(void) {
	unregister_chrdev(MAJOR_NUM, "IH_driver2");
	printk("Driver exit!\n");
}

module_init(driver_init);  
module_exit(driver_exit);

 

이전 모듈 프로그래밍이랑 좀 달라진 점이 있어 확인해보자.

fops 구조체 

  • 문자 디바이스의 파일 조작을 처리하는 함수 포인터들의 집합을 의미
  • open 필드는 디바이스 파일이 열릴 때 호출되는 함수의 포인터이다.
  • release 필드는 디바이스 파일이 닫힐 때 호출되는 함수의 포인터이다.

이번에는 장치 파일을 열고 닫아서, 장치파일과 연결된 디바이스 드라이버에서 함수가 잘 호출되는지 확인할예정이다.

 

 

register_chrdev 함수의 역할

  • register_chrdev(MAJOR_NUM, "IH_driver2", &fops);
  • 이 함수는 커널에 문자 디바이스를 등록한다. 주번호(major number)를 통해 디바이스를 식별하고, 해당 디바이스에 대해 수행할 작업을 정의하는 file_operations 구조체를 연결한다.
  • 반환값은 0이면 등록성공, 0보다 작으면 등록실패를 의미한다.

 

 

등록 확인

 

 

 

 

 

 

 


디바이스 파일 만들기 

mknod로 만들 수 있다.

 

dev 폴더 안에 day2라는 문자 장치파일을 만들고, 100번의 주번호로 디바이스 드라이버와 연결해준다.

chmod로 권한을 부여해준다. 666은 장치파일을 읽고 쓸 수 있도록 해주는 것이다.

 

 

 

 


유저 어플리케이션 생성

 

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

int main() {

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

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

        return 0;
}

 

유저 실행파일은 위와 같이 만들었으며, 단순히 open, close 함수를 이용하여 /dev/day2 파일을 열고 닫는다.

이 장치 파일을 열고 닫으면 디바이스 드라이버에서의 fops 구조체에서의, 파일 open/release 포인터가 연결된 함수들이 호출될 것이다.

 

위 c 파일을 실행파일로 컴파일하고 실행한다.

 

 

 

 

 

 


결과 확인

 

 

dmesg를 통해 장치파일과 디바이스 드라이버에 정상적으로 접근했는지 확인할 수 있다.

open_moduile을 선언했을때 3번째 줄, 4번째 줄이 순차적으로 디바이스 드라이버를 통해 호출 되었음을 확인할 수 있다.

 

이로서 유저 프로그램으로 디바이스 드라이버 접근까지 성공하였다.