문자 디바이스 드라이버 코드를 작성하는
구동 모듈 코딩
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/uaccess.h>
static int data;
static int chr_open (struct inode * inode, struct file * file){
printk("character device open\n");
return 0;
}
static int chr_release (struct inode * inode, struct file * file){
printk("character device close\n");
return 0;
}
ssize_t chr_read (struct file * file, char __user * buf, size_t size, loff_t * offset){
if(copy_to_user(buf, &data,sizeof(data))){
printk("copy failed\n");
return -EFAULT;
}
return sizeof(data);
}
ssize_t chr_write (struct file * file, const char __user * buf, size_t size, loff_t * offset){
if(copy_from_user(&data, buf, sizeof(data))){
printk("copy failed\n");
return -EFAULT;
}
return sizeof(data);
}
/* file_operations 用来存储驱动内核模块提供的对设备进行各种操作的函数的指针。
* 该结构体的每个域都对应着驱动内核模块用来处理某个被请求的事务的函数的地址。
*/
static struct file_operations chr_fop = {
.open = chr_open,
.release = chr_release,
.read = chr_read,
.write = chr_write,
};
static struct cdev *my_chr_cdev;
static struct class *chr_class;
static dev_t device;
/* 驱动模块的入口函数 */
static int chr_test_init(void){
if (device){
/* 静态申请设备号 */
register_chrdev_region(device,1,"chr_dev");
}else{
/* 动态申请设备号 */
alloc_chrdev_region(&device,0, 1,"chr_dev");
}
/* 申请空间 */
my_chr_cdev = cdev_alloc();
/* 注册字符设备驱动 */
cdev_init(my_chr_cdev,&chr_fop);
cdev_add(my_chr_cdev, device, 1);
/* 创建设备节点 */
chr_class = class_create(THIS_MODULE, "mydev");
class_device_create(chr_class, NULL, device, NULL,"mydev");
return 0;
}
/* 驱动模块的退出函数 */
static void chr_test_exit(void){
/* 删除设备节点 */
class_device_destroy(chr_class, device);
class_destroy(chr_class);
/* 注销字符设备驱动 */
cdev_del(my_chr_cdev);
/* 释放空间 */
cdev_put(my_chr_cdev);
/* 释放设备号和相应的设备名 */
unregister_chrdev_region(device, 1);
}
/* 这个宏将 chr_test_init 函数修饰为模块的入口函数 */
module_init(chr_test_init);
/* 这个宏将 chr_test_exit 函数修饰为模块的退出函数 */
module_exit(chr_test_exit);
/* 遵循GPL协议 */
MODULE_LICENSE("GPL");
둘째, 메이크 쓰기
#内核源码树路径
KERN_DIR = /work/system/kernel/source/linux-2.6.22.6
#目标文件
obj-m += first.o
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
셋째, 테스트 응용 프로그램
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int buf;
int main(int argc, char** argv){
int fd;
if((fd = open("/dev/mydev",O_RDWR))<0){
printf("open device failed\n");
return -1;
}
/* 将数据写到驱动程序,再读出来验证 */
for(int i=0; i<10; i++){
write(fd,&i,sizeof(i));
read(fd,&buf,sizeof(buf));
printf("read the data is:%d\n",buf);
sleep(1);
}
close(fd);
return 0;
}
테스트를 네 번째 컴파일
1, 커널 드라이버를 컴파일
소스 코드 및 메이크 다음, 리눅스 시스템을 테스트 실행
make
frist.ko 개발 보드에 복사 할 파일을, 내가 여기에 사용하고하는 것은 NFS (네트워크 파일 시스템)입니다
cp first.ko /work/system/nfs/
2. 테스트 프로그램을 컴파일
컴파일
arm-linux-gcc -o main main.c
주요 개발 보드에 복사 할 파일을
cp main /work/system/nfs/
(3) 시험
커널 모듈을 삽입
insmod frist.ko
모듈 정보를 볼 수 있습니다
lsmod
응용 프로그램을 실행하기를
./main·
V. 요약
(보통 디바이스 드라이버 명령에 사용되는)
로드 모듈을
insmod xxx.ko
커널 모듈 삽입 참조
lsmod
모듈 하적
rmmod xxx
뷰잉 모듈 기술 정보를
modinfo xxx.ko