2 분 소요

block device driver source code

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/uaccess.h>

#include <linux/slab.h>

#define DRV_NAME "thermal_buffer"

#define  BUFF_SIZE      1024

#define  MAJOR_NUMBER   255

static char *buffer  = NULL;

static int my_open( struct inode *inode, struct file *filp  )

{

printk( "[sulac] opened\n"  );

return 0;

}

static int my_release( struct inode *inode, struct file *filp  )

{

printk( "[sulac] released\n"  );

return 0;

}

static ssize_t my_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos  )

{

int i =0;

int sz_data = count;

printk( "[sulac] write to buffer \n");

printk( "[sulac] write to buffer - before count [%ld]\n", count );

printk("%d \n", copy_from_user(buffer, buf, sz_data ));

printk( "[sulac] write to buffer - after\n" );

return count;

}

static ssize_t my_read( struct file *filp, char *buf, size_t count, loff_t *f_pos  )

{

int sz_data = 0;

printk( "[sulac] read from buffer [%ld]\n", count  );

printk("%s \n ",buffer);

copy_to_user( buf, buffer, 1024 );

return sz_data;

}

static struct file_operations vd_fops = {

.read = my_read,

.write = my_write,

.open = my_open,

.release = my_release

};

int __init my_init( void  )

{

register_chrdev( MAJOR_NUMBER, DRV_NAME, &vd_fops  );

buffer = (char*) kmalloc( BUFF_SIZE, GFP_KERNEL  );

memset( buffer, 0, BUFF_SIZE );

if(buffer == NULL)

printk("Could not alloc \n");

printk( "[sulac] initialized\n" );

return 0;

}

void __exit my_exit( void  )

{

unregister_chrdev( MAJOR_NUMBER, DRV_NAME );

kfree( buffer  );

printk( "[sulac] exited\n" );

}

module_init( my_init  );

module_exit( my_exit  );

MODULE_LICENSE( "GPL"  );

application source code.


  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include
  4. #include
  5. #include
  6. #include

  7. int main(void)
  8. {
  9. int fd,ret;
  10. ret = 0;
  11. unsigned char buf[]=”eofeofeof”;
  12. unsigned char readbuf[10]={0,};
  13. printf(“app start\n”);
  14. fd = open(“/dev/thermal_buffer”,O_RDWR);
  15. if(fd < 0)
  16. {
  17. printf(“fd file open fail\n”);
  18. return -1;
  19. }
  20. printf(“write data [%s] write result[%ld] \n”, buf, write(fd, buf, 10));
  21. //write(fd,&buf,1);
  22. printf(“read result[%ld]  ”, read(fd, readbuf, 10));
  23. printf(“read data [%s]\n”, readbuf);
  24. //read(fd,&buf,1);
  25. //printf(“ioctl %d \n”, ioctl(fd,1,2));
  26. //ioctl(fd,1,2);
  27. //printf(“close fd [%d] \n”, close(fd));
  28. close(fd);
  29. return ret;
  30. }

Makefile


  1. obj-m :=thermal_driver.o
  2. KDIR :=/lib/modules/$(shell uname -r)/build
  3. PWD := $(shell pwd)
  4. default:
  5. $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
  6. gcc -o test_app application.c
  7. clean:
  8. rm -rf *.order *.symvers *.ko *.mod.* *.o test_app

build

  • make

test 절차

  1. device driver node 만들기

sudo touch /dev/thermal_buffer

mknod /dev/thermal_buffer b 250 0( /dev폴더에 (주 250/부 0 )번호 thermal_buffer 라는 장치파일을 생성)\

sudo mknod -m 666 /dev/thermal_buffer c 250 0  (/dev 폴더에  주250, 부 0 번호  thermal_buffer 라는 케릭터 디바이스 드라이버 생성)

–»  250 을 할당하기 전에 cat /proc/devices 를 열어서 사용하고 있는지 확인을 미리 해야 합니다.

  1. block device drivere 올리기

  2. char device drivere 올리기

sudo insmod thermal_driver.ko

(올라간지 확인 : lsmod grep thermal_driver , cat /proc/devices )
  1. application 설행

sudo ./test_app

  1. check
dmesg grep sulac
  1. younlea@sulac:~/temp/thermal/RamDiskDriver/test$ dmesg grep sulac
  2. [2852979.919437] [sulac] exited
  3. [2856399.540554] [sulac] initialized
  4. [2856489.844273] [sulac] exited
  5. [2856517.427697] [sulac] initialized
  6. [2856789.656291] [sulac] exited
  7. [2856974.656498] [sulac] initialized
  8. [2857918.200307] [sulac] exited
  9. [2857924.684514] [sulac] initialized
  10. [2876690.184567] [sulac] exited
  11. [2876695.304778] [sulac] initialized
  12. [2876709.260492] [sulac] opened
  13. [2876709.260499] [sulac] read from buffer
  14. [2876709.260505] [sulac] released
  15. [2876723.004447] [sulac] opened
  16. [2876723.004450] [sulac] write to buffer
  17. [2876723.004461] [sulac] read from buffer
  18. [2876723.004470] [sulac] released

5.driver내리기

sudo rmmod thermal_driver

driver 지우기

sudo rm -rf /dev/thermal_buffer

버퍼에 올리고 쓸꺼라 block device driver를 쓸 필요가 없어서 char device driver 로 선회 ^^;

error case : “No such device or address” 라고 나오고 open이 안된다.

해당 이슈는 device driver 가 insmode가 안되어서 나오는 이슈로 insmod 후에 확인해 보면 됩니다.

driver가 잘 올라갔는지 확인할때 cat /proc/drivers에서도 확인이 가능합니다.

Test app없이도 cat으로 file을 open 하면 dmesg로 쓴것을 확인할수 있습니다.

참고

dmesg 실시간으로 보기가 하고 싶을듯 하여 방법을 추가합니다.

아래 두가지중 한가지를  사용하시면 됩니다.

$ tail -f /var/log/kern.log

$ watch “dmesg tail -f”

훔.. 동작하다 보면 커널이 죽어 버리는.. 쿨럭… 테스트 해봐야 할껀 copy_to_user, copy_from_user 인데…

참고

sample code 에 있는 <asm/uaccess.h>는 빌드를 하면 에러가 난다.

https://lkml.org/lkml/2017/9/30/189 를 참고해 보면 linux/uaccess.h 로 바꾸면 빌드가 잘 된다고 해서 바꿔서 하니 잘된다.

copy_to_user, copy_from_user 를 쓸수 있게 된다.

리눅스 헤더파일을 못찾아서 빌드가 안될때 참고