- 개요 이 문서에서는 실습용으로 실행 가능한 간단한 드라이버 예제를 제공하고, Linux에서 드라이버 템플릿의 요소들을 설명합니다. 또한 Linux에서 애플리케이션에서 드라이버로의 실행 과정을 설명합니다. 이 간단한 드라이버 예제는 개발 보드의 Linux 시스템에서 직접 실행됩니다.
개발 환경: TQ2440 개발 보드 + Linux 2.6.30.4
- 드라이버 프로그램 예제
- 드라이버 파일 EmbedSky_hello.c 작성
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#define MY_DEVICE_MAJOR 231
#define DEVICE_NAME "MyDevice"
static int my_device_open(struct inode *inode, struct file *file)
{
printk("<1>MyDevice open.\n");
return 0;
}
static int my_device_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos)
{
printk("<1>MyDevice write.\n");
return 0;
}
static struct file_operations my_flops = {
.owner = THIS_MODULE,
.open = my_device_open,
.write = my_device_write,
};
static int __init my_device_init(void)
{
int ret;
ret = register_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME, &my_flops);
if (ret < 0)
{
printk("<1>%s can't register major number.\n", DEVICE_NAME);
return ret;
}
printk("<1>%s initialized.\n", DEVICE_NAME);
return 0;
}
static void __exit my_device_exit(void)
{
unregister_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME);
printk("<1>%s removed.\n", DEVICE_NAME);
}
module_init(my_device_init);
module_exit(my_device_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.embedsky.net");
MODULE_DESCRIPTION("SKY2440/TQ2440 Board First module test");
- 드라이버 Makefile 작성
KERN_DIR = /opt/EmbedSky/linux-2.6.30.4
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += my_device.o
- 드라이버 예제 테스트
- 드라이버 컴파일 전 주의사항
- 드라이버 파일이 Linux 커널 소스 트리의 하위 디렉터리가 아닙니다.
- 드라이버 파일이 "opt/EmbedSky/work/EmbedSky_hello" 디렉터리에 있습니다.
- Linux 커널 소스가 "opt/EmbedSky/linux-2.6.30.4"에 있습니다.
- Ubuntu에서 드라이버 컴파일
# cd /opt/EmbedSky/work/EmbedSky_hello
# make
- Ubuntu에서 드라이버를 개발 보드로 복사
# cd /opt/EmbedSky/root_nfs/lib
# cp /opt/EmbedSky/work/EmbedSky_hello/my_device.ko ./
- 개발 보드에서 드라이버 설치
# insmode my_device.ko
- 드라이버 등록 정보 확인
# cat /proc/devices
- 애플리케이션 테스트
- 테스트 코드 작성
- hellotest.c 내용
#include <fcntl.h>
#include <stdio.h>
int main(void)
{
int fd;
int val = 1;
fd = open("/dev/my_device", O_RDWR);
if(fd < 0){
printf("can't open!\n");
}
write(fd, &val, 4);
return 0;
}
- Ubuntu에서 애플리케이션 컴파일
# arm-linux-gcc hellotest.c -o hellotest
- Ubuntu에서 애플리케이션을 개발 보드로 복사
# cd /opt/EmbedSky/root_nfs/usr/bin
# cp /opt/EmbedSky/work/EmbedSky_hello/hellotest ./
- 개발 보드에서 장치 파일 생성
# mknod /dev/my_device c 231 0
- 테스트 코드 실행
# cd /usr/bin
# ./hellotest
- 드라이버 템플릿
- 헤더 파일
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
- 초기화 함수
static int __init my_device_init(void)
{
int ret;
ret = register_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME, &my_flops);
if (ret < 0) {
printk(KERN_EMERG DEVICE_NAME " can't register major number.\n");
return ret;
}
printk(KERN_EMERG DEVICE_NAME " initialized.\n");
return 0;
}
module_init(my_device_init);
- 종료 함수
static void __exit my_device_exit(void)
{
unregister_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME);
printk(KERN_EMERG DEVICE_NAME " removed.\n");
}
module_exit(my_device_exit);
- 라이선스 정보
MODULE_LICENSE("GPL");
- 기능 함수
static int my_device_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG "my_device open.\n");
return 0;
}
static int my_device_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos)
{
printk(KERN_EMERG "my_device write.\n");
return 0;
}
static struct file_operations my_flops = {
.owner = THIS_MODULE,
.open = my_device_open,
.write = my_device_write,
};
- 애플리케이션에서 드라이버로의 실행 과정
- Linux 시스템의 계층 구조
- 애플리케이션 계층 ---> 라이브러리 ---> 커널 ---> 드라이버 ---> 하드웨어
- 애플리케이션에서 드라이버로의 실행 과정
- "open("/dev/my_device", O_RDWR)" 함수의 실행 과정을 예로 설명
- 드라이버 프로그램의 실행 특징
- 애플리케이션과 달리 드라이버는 주动生成되지 않습니다.
- 애플리케이션의 요청에 따라 초기화되고, 읽기/쓰기 작업을 수행합니다.
- 드라이버는 커널 공간에서 실행되고, 시스템의 신뢰할 수 있는 일부분입니다.