반응형
call_dev.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#define CALL_DEV_NAME "calldev"
#define CALL_DEV_MAJOR 230
static int call_open(struct inode *inode, struct file *filp)
{
int num = MINOR(inode->i_rdev);
printk("call open -> minor : %d\n", num);
num = MAJOR(inode->i_rdev);
printk("call open -> major : %d\n", num);
return 0;
}
static loff_t call_llseek(struct file *filp, loff_t off, int whence)
{
printk("call llseek -> off : %08X, whence : %08X\n", (unsigned int)off, whence);
return 0x23;
}
static ssize_t call_read(struct file *filp, char *buf,size_t count, loff_t *f_pos)
{
printk("call read -> buf : %08X, count : %08X\n", (unsigned int)buf, count);
return 0x33;
}
static ssize_t call_write(struct file *filp, const char *buf,size_t count, loff_t *f_pos)
{
printk("call write -> buf : %08X, count : %08X\n", (unsigned int)buf, count);
return 0x43;
}
static long call_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
printk("call ioctl -> cmd : %08X, arg : %08X\n", cmd, (unsigned int)arg);
return 0x53;
}
static int call_release(struct inode *inode, struct file *filp)
{
printk("call release\n");
return 0;
}
//선언과 동시에 초기화하기 위해서 .owner = THIS_MODULE 이런식으로 해주는거임.
//여기서 들어가는 값들은 함수포인터들임.
//왼쪽에 있는 .read가 file_operations 구조체에 정의되어 있는 사용가능한 함수원형이고 call_read는 우리가 그 원형에 맞게 구현해둔 함수임.
struct file_operations call_fops =
{
.owner = THIS_MODULE,
.llseek = call_llseek,
.read = call_read,
.write = call_write,
.unlocked_ioctl = call_ioctl,
.open = call_open,
.release = call_release,
};
static int call_init(void)
{
int result;
printk("call call_init \n");
result =register_chrdev(CALL_DEV_MAJOR,CALL_DEV_NAME, &call_fops);//커널에 device driver를 적재해주는 코드
//230번에 calldev라는 이름으로 file_operations 구조체를 등록시켜주는거임.
if(result < 0) return result;
return 0;
}
static void call_exit(void)
{
printk("call call_exit \n");
unregister_chrdev(CALL_DEV_MAJOR,CALL_DEV_NAME);
}
module_init(call_init);
module_exit(call_exit);
MODULE_LICENSE("Dual BSD/GPL");
call_app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_FILENAME "/dev/calldev"
int main(void)
{
int dev;
char buff[128];
int ret;
printf("1) device file open\n");
dev = open(DEVICE_FILENAME, O_RDWR | O_NDELAY);
if(dev >=0)
{
printf("2) seek function call dev:%d\n",dev);
ret=lseek(dev,0x20, SEEK_SET);
printf("ret = %08X\n",ret);
printf("3) read function call \n");
ret = read(dev,(char*)0x30,0x31);
printf("ret = %08X\n",ret);
printf("4) write function call \n");
ret = write(dev,(char*)0x40,0x41);
printf("ret = %08X\n",ret);
printf("5) ioctl function call \n");
ret = ioctl(dev,(char*)0x51,0x52);
printf("ret = %08X\n",ret);
printf("6) device file close \n");
ret = close(dev);
printf("ret = %08X\n",ret);
}
else
perror("open");
return 0;
}
Makefile
APP := call_app
MOD := call_dev
SRC := $(APP).c
obj-m := $(MOD).o
CROSS = ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
CC := arm-linux-gnueabihf-gcc
KDIR := /home/ubuntu/pi_bsp/kernel/linux
PWD := $(shell pwd)
default:$(APP)
$(MAKE) -C $(KDIR) M=$(PWD) modules $(CROSS)
cp $(MOD).ko /srv/nfs
$(APP):
$(CC) $(APP).c -o $(APP)
cp $(APP) /srv/nfs
clean:
rm -rf *.ko
rm -rf *.mod.*
rm -rf .*.cmd
rm -rf *.o
rm -rf modules.order
rm -rf Module.symvers
rm -rf $(MOD).mod
rm -rf .tmp_versions
rm -rf $(APP)
make를 하고 call_app과 call_dev가 컴파일되면 ko파일이 자동으로 라즈베리파이의 nfs로 복사가 되고
라즈베리의 nfs로 가서 실행시켜보자
call_dev.ko와 call_app 실행파일 2가지가 있음.
pi@pi08:/mnt/ubuntu_nfs $ cat /proc/devices
사용중인 device들의 번호를 확인해주고 안쓰는걸로 하나 잡아
그래서 call_dev.ko 등록시켜주고
pi@pi08:/mnt/ubuntu_nfs $ sudo mknod /dev/calldev c 230 32
pi@pi08:/mnt/ubuntu_nfs $ sudo insmod call_dev.ko
dmesg하면 커널 메시지 출력되어 있고
pi@pi08:/mnt/ubuntu_nfs $ sudo ./call_app
앱 실행시켜보면 정상적으로 device driver를 통해 file 입출력이 가능함.
dmesg하면 커널 메시지 출력되어 있음.
앱과 device driver의 관계를 보는게 이번 실습의 목표이고 어떤 값들을 return하는지 보기 위한 예제일뿐임.
반응형
'Linux BSP' 카테고리의 다른 글
[Linux Device Driver] Device Driver와 application으로 led, 버튼 제어 (0) | 2024.02.23 |
---|---|
[Linux Device Driver] 디바이스 드라이버 (0) | 2024.02.23 |
[Device Driver] 변수의 데이터형과 바이트 순서와 volatile 변수 (0) | 2024.02.22 |
[RaspberryPi DeviceDriver] 디바이스 드라이버 매개변수 명령어로 입력 받는 함수 만들기 (0) | 2024.02.22 |
Makefile은 왜 사용하며, 어떻게 사용하는가 (2) | 2024.02.22 |