嵌入式系统实验1-简单字符设备驱动实验

写一个简单的字符设备驱动程序,要求:

定义一个全局结构指针,初始值为NULL,该数据结构中包含一个大小为1024的buffer和一个count整形变量
在open中对该全局结构进行NULL判断,为NULL则为其分配内存,并将buffer初始化为0,将count自加
在release中如果count为0,则释放,否则进行count自减
在read里面对该buffer进行读取
在write里面对该buffer进行赋值(任意赋值即可)
写测试程序进行测试

设备驱动基础知识

https://www.cnblogs.com/microxiami/p/11254081.html

字符设备驱动reference

https://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html
https://www.cnblogs.com/chen-farsight/p/6155518.html#unit3.1.5

这两篇比较详细

自己根据题目修改和简化后的实现

demo1.c文件
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/cdev.h>
#include<linux/fs.h>
#include<linux/kdev_t.h>
#include<linux/types.h>
#include<linux/uaccess.h>
#include<linux/string.h>
#include <linux/slab.h>
unsigned int major=0;  //主设备号
unsigned int minor=0;  //次设备号
dev_t dev_no;  //设备号
int ret;   //返回结果
struct cdev chrdev;   //struct cdev在<linux/cdev.h>中定义,描述一个字符设备

typedef struct mydata
{
    char buffer[1024];
    int count;
} d, *D;  //d=struct mydata    D=struct mydata*

D my = NULL;  //NULL

 
int my_open(struct inode *i,struct file *f){  //open操作
    if (my==NULL)  //结构体指针为空时
    {
         my=kmalloc( sizeof(struct mydata),GFP_KERNEL);  //分配内存
      
        my->count++;  //count自增
    }
    printk("cdev open\n");
    return 0;
}
 
int my_release(struct inode *i,struct file *f){//release操作
    if(my->count==0)
    printk("cdev release\n");
    else{
        my->count--;  
    }
    return 0;
}
 
static ssize_t my_write(struct file *f,const char __user *u,size_t l,loff_t *o){  //write操作
    
    copy_from_user(my->buffer,u,l);   //对buffer赋值
    printk(KERN_EMERG"write string:%s",my->buffer);  
    return l;
}
 
static ssize_t my_read(struct file *f,char __user *u,size_t l,loff_t *o){  //read操作
    
    copy_to_user(u,my->buffer,strlen(my->buffer));    //复制到用户态
    printk(KERN_EMERG"read string:%s",my->buffer);  //读取buffer
    return l;
}
 
struct file_operations fops={  //定义文件操作集
    .owner=THIS_MODULE,
    .open=my_open,
    .release=my_release,
    .write=my_write,
    .read=my_read
};
 
static int my_init(void){//驱动的初始化
    dev_no=MKDEV(major,minor);
    if(dev_no>0){
        ret=register_chrdev_region(dev_no,1,"demo1");//静态注册设备号
    }else{
        ret=alloc_chrdev_region(&dev_no,0,1,"demo1");//动态申请设备号
    }
    if(ret<0){
        return ret;
    }
    cdev_init(&chrdev,&fops);
    chrdev.owner=THIS_MODULE;
    cdev_add(&chrdev,dev_no,1);
    return 0;
}
 
static void my_exit(void){ //驱动的退出
    unregister_chrdev_region(dev_no,1);
    cdev_del(&chrdev);
}
 
module_init(my_init);//调用系统函数来设置驱动初始化函数
module_exit(my_exit);//设置驱动结束的函数
 
MODULE_AUTHOR("xxxxx-zhangsan");   /*作者名*/
MODULE_DESCRIPTION("this ostest demo1");
MODULE_LICENSE("GPL");    /*宏声明许可证*/
 
Makefile文件
ifneq ($(KERNELRELEASE),)
obj-m := demo1.o
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
	rm -fr .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.*
endif

编译

在这里插入图片描述

加载驱动模块查看设备驱动号

在这里插入图片描述
250为设备驱动号

lsmod查看是否加载

在这里插入图片描述

添加设备文件
root@ubuntu:/home/linux/Lecture/lab# mknod /dev/demo1 c 250 0
root@ubuntu:/home/linux/Lecture/lab# ll /dev/demo1
crw-r--r-- 1 root root 250, 0  424 22:45 /dev/demo1
删除设备文件

rm -f /dev/demo1

测试程序 test.c
#include<stdio.h>
#include <unistd.h>
#include<fcntl.h>
int main(void)
{
int fd;
char *buf="Grace under pressure!";
char buf2[20];
fd=open("/dev/demo1",O_RDWR);
if(fd<0){
	printf("fd<0\n");
}else{
	printf("fd:%d\n",fd);
}
write(fd,buf,22);
read(fd,buf2,22);
printf("res:%s",buf2);
close(fd);
}

在这里插入图片描述

dmesg查看驱动打印信息
刚insmod后

在这里插入图片描述

运行test后

在这里插入图片描述

卸载模块后

在这里插入图片描述

附:linux内核模块的依赖性、查看、加载与删除
查看模块信息 modinfo

在这里插入图片描述

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值