open(), close()
Linux/Device Driver

open(), close()

https://rorsi.tistory.com/61

 

디바이스 드라이버

디바이스 드라이버(Device Driver) 일반적으로 디바이스란 컴퓨터에 물려있는 여러 주변장치들을 뜻한다. 네트워크 어댑터, 오디오, 키보드, 마우스 등이 디바이스에 해당하고, 이러한 디바이스들

rorsi.tistory.com

 

위 포스트에 이어서 디바이스 드라이버를 만들었다면 이제 그 드라이버를 이용해 open(), close()를 구현해 보고자 한다.

driver.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/cdev.h>

#define DEVICE_NAME "driver"

static dev_t device_dev;
static struct class *device_class;
static struct cdev device_cdev;

int device_open(struct inode *inode, struct file *filp);
int device_release(struct inode *inode, struct file *filp);

static struct file_operations fops = {
	.open = device_open,
	.release = device_release
};

int device_open(struct inode *inode, struct file *filp)
{
	printk(KERN_INFO "device open\n");
	return 0;
}

int device_release(struct inode *inode, struct file *filp)
{
	printk(KERN_INFO "device close\n");
	return 0;
}

int __init device_init(void) 
{
	if(alloc_chrdev_region(&device_dev, 0, 1, DEVICE_NAME))
	{
		printk(KERN_ALERT "[&s] alloc_chrdev_region failed\n", __func__);	
		return -1;
	}
	
	cdev_init(&device_cdev, &fops);

	if(cdev_add(&device_cdev, device_dev, 1))
	{
		printk(KERN_ALERT "[%s] cdev_add failed\n", __func__);
		unregister_chrdev_region(device_dev, 1);
	}

	if((device_class = class_create(THIS_MODULE, DEVICE_NAME)) == NULL) 
	{
		printk(KERN_ALERT "[%s] class_add failed\n", __func__);
		unregister_chrdev_region(device_dev, 1);
	}

	if(device_create(device_class, NULL, device_dev, NULL, DEVICE_NAME) == NULL)
	{
		printk(KERN_ALERT "[%s] device_create failed\n", __func__);
		class_destroy(device_class);
	}

	printk(KERN_INFO "[%s] successfully created device: Major = %d, Minor = %d\n",
			__func__, MAJOR(device_dev), MINOR(device_dev));
	return 0;
	
}

void __exit device_exit(void)
{
	device_destroy(device_class, device_dev);	
	class_destroy(device_class);
	cdev_del(&device_cdev);
	unregister_chrdev_region(device_dev, 1);
	printk("KERN_INFO [%s] successfully unregistered.\n", __func__);
}

module_init(device_init);
module_exit(device_exit);

MODULE_AUTHOR("Test");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("character device driver");

이전 포스팅의 코드와 다른 점은 open 함수와 release 함수와 연결할 수 있게 file operation에 해당 코드를 적어준다.

static struct file_operations fops = {
.open = device_open,
.release = device_release
};

 

Kernel은 등록된 디바이스 드라이버의 파일 연산 구조체를 참고하여 응용 프로그램의 요청에 대응하는 함수를 호출한다.

즉, 파일 연산 구조체 변수를 Kernel에 등록하는 것은 디바이스 드라이버를 등록하는 것이다.

 

close와 release의 차이

우리는 파일을 닫을 때 close를 사용하는데, file_operations에는 release 함수를 구현하라고 되어있다. 그건 파일은 동시에 여러 번 open 될 수 있기 때문이다. 즉, close는 파일을 닫을 때마다 호출되지만, release는 close가 호출된 후, 더 이상 이 파일을 열고 있는 프로세스가 존재하지 않을 때 호출된다.

 

open_close.c

#include <stdio.h>  // printf()
#include <unistd.h> // close()
#include <sys/fcntl.h>  // open()

int   main(void) {
  int fd;

  fd = open("/dev/driver", O_RDWR);
  if (fd < 0)
  {
    printf("failed opening device\n");
    return 0;
  }
  else
  {
    printf("succeess opening device\n");
  }

  close(fd);
}

 

디바이스 드라이버를 등록 한 후 해당 코드를 작성한 뒤 실행시켜준다.

정상적으로 open()이 작동한 것을 확인할 수 있다.

 

이제 dmesg 명령어를 통해 커널 메시지를 확인해보면 정상적으로 open 뒤 close 된 것을 확인 할 수 있다.

'Linux > Device Driver' 카테고리의 다른 글

read(), write()  (0) 2022.11.25
ioctl()  (0) 2022.11.25
디바이스 드라이버  (0) 2022.11.20