ARM驱动学习之21_字符驱动

ops/2024/9/22 9:50:11/

                              ARM驱动学习之21_字符驱动

操作步骤:

file_operations中的函数比较多,
选取用的比较多的函数简单介绍,
后
面的驱动教程中调用了对应的函数• int (*open) (struct inode *, struct file *)
– 打开函数
• int (*release) (struct inode *, struct file *)
– 释放close函数
• long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long)
– io控制函数
• ssize_t (*read) (struct file *, char __user *, size_t, loff_t *)
– 读函数
• ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)
– 写函数
• loff_t (*llseek) (struct file *, loff_t, int)
– 定位函数1.修改文件名为char_driver并修改Makefile里面的文件。定义函数如下:
/*打开操作*/
static int chardevnode_open(struct inode * inode,struct file * file){printk(KERN_EMERG "chardevnode_open is opened! \n");return 0;
}/*关闭操作*/
static int chardevnode_release(struct inode *inode,struct file *file){printk(KERN_EMERG "chardevnode_release is release! \n");return 0;     
}/*IO操作*/
static long chardevnode_ioctl (struct file *file, unsigned int cmd, unsigned long arg){printk(KERN_EMERG "chardevnode_ioctl is success! cmd is %d,arg is %d \n",cmd,arg);return 0;  
}static ssize_t chardevnode_read (struct file *file , char __user *buf, size_t count, loff_t *f_ops){return 0; 
}static ssize_t chardevnode_write (struct file *file , const char __user *buf, size_t count, loff_t *f_ops){return 0; 
}static loff_t chardevnode_llseek (struct file *file , loff_t offset, int ence){return 0; 
}2.在struct file_operations my_fops = {.owner = THIS_MODULE,.open = chardevnode_open,.release = chardevnode_release,.unlocked_ioctl = chardevnode_ioctl,.read = chardevnode_read,.write = chardevnode_write,.llseek = chardevnode_llseek,
};

2.修改invoke_hello.c文件:

1.将“invoke_hello.c”改为“invoke_char_driver.c”
在文件中添加如下内容:
char *hello_node0 = "/dev/chardevnode0";
char *hello_node1 = "/dev/chardevnode1";
2.修改函数名为hello_node0 和 hello_node1;
if((fd = open(hello_node0,O_RDWR|O_NDELAY)) < 0)
{printf();
}close(fd);编译应用命令如下
– arm-none-linux-gnueabi-gcc -o invoke_char_driver invoke_char_driver.c -static

代码,设备节点:

#include <linux/init.h>
/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/
#include <linux/module.h>
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
/*定义module_param module_param_array的头文件*/
#include <linux/moduleparam.h>
/*定义module_param module_param_array中perm的头文件*/
#include <linux/stat.h>
/*字符设备函数*/
#include <linux/fs.h>
/*MDKDEV转换设备号数据类型宏定义*/
#include <linux/kdev_t.h>
/*定义字符设备的结构体*/
#include <linux/cdev.h>
/*分配内存空间函数头文件*/
#include <linux/slab.h>#include <linux/device.h>#define DEVICE_NAME "chardevnode"
#define DEVICE_MINOR_NUM 2
#define DEV_MAJOR 0
#define DEV_MINOR 0#define REGDEV_SIZE 3000MODULE_LICENSE("Dual BSD/GPL");
/*声明是开源的,没有内核版本限制*/
MODULE_AUTHOR("iTOPEET_dz");
/*声明作者*/static int numdev_major = DEV_MAJOR ;//主设备号
static int numdev_minor = DEV_MINOR ;//次设备号module_param(numdev_major,int,S_IRUSR);
module_param(numdev_minor,int,S_IRUSR);struct reg_dev
{char *data;unsigned long size;struct cdev cdev;
};
struct reg_dev *my_devices;
static struct class * myclass;/*打开操作*/
static int chardevnode_open(struct inode * inode,struct file * file){printk(KERN_EMERG "chardevnode_open is success! \n");return 0;
}/*关闭操作*/
static int chardevnode_release(struct inode *inode,struct file *file){printk(KERN_EMERG "chardevnode_release is success! \n");return 0;     
}/*IO操作*/
static long chardevnode_ioctl (struct file *file, unsigned int cmd, unsigned long arg){printk(KERN_EMERG "chardevnode_ioctl is success! cmd is %d,arg is %d \n",cmd,arg);return 0;  
}ssize_t chardevnode_read (struct file *file , char __user *buf, size_t count, loff_t *f_ops){return 0; 
}ssize_t chardevnode_write (struct file *file , const char __user *buf, size_t count, loff_t *f_ops){return 0; 
}loff_t chardevnode_llseek (struct file *file , loff_t offset, int ence){return 0; 
}struct file_operations my_fops = {.owner = THIS_MODULE,.open = chardevnode_open,.release = chardevnode_release,.unlocked_ioctl = chardevnode_ioctl,.read = chardevnode_read,.write = chardevnode_write,.llseek = chardevnode_llseek,
};/*设备注册到系统*/
static void reg_init_cdev(struct reg_dev *dev,int index){int err;int devno = MKDEV(numdev_major,numdev_minor + index);/*数据初始化*/cdev_init(&dev -> cdev,&my_fops);dev -> cdev.owner = THIS_MODULE;dev -> cdev.ops = &my_fops;err = cdev_add(&dev -> cdev,devno,1);if(err){printk(KERN_EMERG "failed,cdev_add is %d ,index is %d\n",err,index);}else{printk(KERN_EMERG "cdev_add %d success\n",index);printk(KERN_EMERG "numdev_minor  is %d",numdev_minor);}}static int Ascdev_init(void)
{int ret = 0;int i = 0;printk(KERN_EMERG "numdev_major is %d!\n",numdev_major);printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor);dev_t num_dev;if(numdev_major){num_dev = MKDEV(numdev_major,numdev_minor);//宏命令,用于处理各种设备号相关的数据//设备注册ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);if(ret < 0){printk(KERN_EMERG "register_chrdev_region req is %d is failed \n",num_dev );}printk(KERN_EMERG "register_chrdev_region %d is success \n",numdev_major);	}else{ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);if(ret < 0){printk(KERN_EMERG "alloc_chrdev_region req is %d is failed \n",num_dev );return -1;}numdev_major = MAJOR(num_dev);//huoqu printk(KERN_EMERG "numdev_major is %d \n",numdev_major);}myclass = class_create(THIS_MODULE,DEVICE_NAME);my_devices = kmalloc(DEVICE_MINOR_NUM * sizeof(struct reg_dev),GFP_KERNEL);	if(!my_devices){ret = -ENOMEM;goto fail;}	memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev));//初始化缓存为0;for(i = 0;i < DEVICE_MINOR_NUM;i ++){my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL);memset(my_devices[i].data,0,REGDEV_SIZE);reg_init_cdev(&my_devices[i],i);device_create(myclass,NULL,MKDEV(numdev_major,numdev_minor + i),NULL,DEVICE_NAME"%d",i);//这个 i 可以创建chardevnode0,chardevnode1		}printk(KERN_EMERG "Ascdev enter!\n");/*打印信息,KERN_EMERG表示紧急信息*/return 0;fail:unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);printk(KERN_EMERG "kmalloc is fail\n");return ret;	}static void Ascdev_exit(void)
{	int i;for(i = 0;i < DEVICE_MINOR_NUM;i++){cdev_del(&(my_devices[i].cdev));	device_destroy(myclass,MKDEV(numdev_major,numdev_minor + i));}class_destroy(myclass);
//	kfree(myclass);	unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);printk(KERN_EMERG "Ascdev exit!\n");
}module_init(Ascdev_init);
/*初始化函数*/
module_exit(Ascdev_exit);
/*卸载函数*/

应用:

/*************************************************************************
> File Name: Invoke.c
> Author: 
> Mail: 
> Created Time: Fri 27 Sep 2019 10:51:55 PM CST
************************************************************************/#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>int main(void)
{char * hello_node0 = "/dev/chardevnode0";char * hello_node1 = "/dev/chardevnode1";int fd; if(fd = open(hello_node0,O_RDWR|O_NDELAY) < 0){printf("hello_node0 open %s is failed\r\n",hello_node0);}else{printf("hello_node0 open  %s is success\r\n",hello_node0);}close(fd);if(fd = open(hello_node1,O_RDWR|O_NDELAY) < 0){printf("hello_node1 open %s is failed\r\n",hello_node1);}else{printf("hello_node1 open  %s is success\r\n",hello_node1);}	close(fd);return 0;
}

运行结果:

[root@iTOP-4412]# ls
chardevicenode.ko   invoke_char_driver
[root@iTOP-4412]# insmod chardevicenode.ko                                                                     
[ 1951.543724] numdev_major is 0!
[ 1951.545312] numdev_minor is 0!
[ 1951.548335] numdev_major is 248 
[ 1951.553133] cdev_add 0 success
[ 1951.554733] numdev_minor  is 0
[ 1951.559293] cdev_add 1 success
[ 1951.561050] numdev_minor  is 0
[ 1951.565035] Ascdev enter!
[root@iTOP-4412]# ls /sys/class                                                                                
android_usb   gpsdrv        kovaplus      net           scsi_device   ump
arvo          graphics      lcd           power_supply  scsi_disk     usb_device
backlight     i2c-adapter   lirc          ppp           scsi_generic  video4linux
bdi           i2c-dev       mali          pyra          scsi_host
block         ieee80211     mdio_bus      rc            sound
bluetooth     input         mem           rc522         spi_master
chardevnode   kone          misc          regulator     switch
firmware      koneplus      mmc_host      rtc           tty
[root@iTOP-4412]# ls /dev/chardevnode*                                                                         
/dev/chardevnode0  /dev/chardevnode1
[root@iTOP-4412]# ./invoke_char_driver                                                                         
[ 2065.729172] chardevnode_open is success! 
[ 2065.732435] chardevnode_open is success! 
[ 2065.735821] chardevnode_release is success! 
[ 2065.740939] chardevnode_release is success! 
hello_node0 open  /dev/chardevnode0 is successhello_node1 open  /dev/chardevnode1 is success[root@iTOP-4412]# 
[root@iTOP-4412]# rmmod chardevicenode                                                                         
[ 2072.553457] Ascdev exit!


http://www.ppmy.cn/ops/113554.html

相关文章

YOLOv8改进 - 注意力篇 - 引入ECA注意力机制

一、本文介绍 作为入门性第一篇&#xff0c;这里介绍了ECA注意力在YOLOv8中的使用。包含ECA原理分析&#xff0c;ECA的代码、ECA的使用方法、以及添加以后的yaml文件及运行记录。 二、ECA原理分析 ECA官方论文地址&#xff1a;ECA文章 ECA的pytorch版代码&#xff1a;ECA的…

el-table 的单元格 + 图表 + 排序

<el-table border :data"tableDataThree" height"370px" style"width: 100%"><el-table-column :key"activeName 8" width"50" type"index" label"序号" align"center"></el…

8586 括号匹配检验

### 思路 1. **初始化栈**&#xff1a;创建一个空栈用于存储左括号。 2. **遍历字符串**&#xff1a;逐个字符检查&#xff1a; - 如果是左括号&#xff08;( 或 [&#xff09;&#xff0c;则入栈。 - 如果是右括号&#xff08;) 或 ]&#xff09;&#xff0c;则检查栈是…

自动化测试常用函数

目录 一、元素的定位 1、cssSelector 2、xpath &#xff08;1&#xff09;xpath 语法 1、获取HTML页面所有的节点 2、获取HTML页面指定的节点 3、获取一个节点中的直接子节点 4、获取一个节点的父节点 5、实现节点属性的匹配 6、使用指定索引的方式获取对应的节点内容…

如何搭建虚拟机Ubuntu?

1.创建新虚拟机 2.进入新建虚拟机向导&#xff0c;选择稍后安装 3. 选择Linux中的Ubuntu 4.为虚拟机命名设置路径 5. 设置磁盘容量大小 6.选择自定义硬件 7.设置设备状态 8.完成Ubuntu虚拟机创建

Maven入门学习笔记

一、maven介绍 Maven是一款自动化构建工具&#xff0c;专注服务于JAVA平台的项目构建和依赖管理。在javaEE开发的历史上构建工具的发展也经历了一系列的演化和变迁。 管理jar包 当我们使用SSM之后我们就需要使用非常多的jar包 没有maven找jar包非常的麻烦。 使用maven下载…

硬件基础知识

驱动开发分为&#xff1a;裸机驱动、linux驱动 嵌入式&#xff1a;以计算机技术为基础&#xff0c;软硬结合的、可移植、可剪裁的专用计算机 单片机最小单元&#xff1a;vcc gnd reset 晶振 cpu --- soc :system on chip 片上外设 所有的程序都是在soc&#xff08;cpu&…

检测场景变化并将视频按场景分开

1. PySceneDetect PySceneDetect 是一个功能强大的 Python 库&#xff0c;专门用于检测视频中的场景变化。它可以自动检测视频中不同场景的切换&#xff0c;并返回场景的时间段。你可以使用这些信息来进一步将视频分割为不同的片段 通过 pip 安装 PySceneDetect&#xff1a; …