ioctl函数的使用以及设备文件的自动创建

news/2025/2/22 15:37:23/

ioctl函数存在的意义

在linux的系统驱动中,内核有意将设备功能的控制选择的读写交给不同的函数完成,既让read和write函数专注于硬件的数据的读写,而设备的功能和实现交给iocti函数来完成,既让read和write函数专注一硬件数据的读写,而设备的功能控制和实现交给ioctl函数来完成,比如,对串口完成控制和完成驱动控制,让iocti完成串口通信的数据,让write通过串口发送数据

#include<sys/ioct1.h>
int ioct(int fd,unsigned long request,....)
功能:进行设备的io和功能控制
参数:
fd :设备文件的文件描述符
request:要实现的功能的功能码
.... 可以写可以不写,是传递给驱动中ioct1方法的一个参数
返回值:成功返回0,失败返回-1
long mycdev_ioct1(struct file *file,unsigned int cmd ,unsigned long arg)
{file:保存当前设备调用ioct1函数时,驱动中的ioct1方法会被自动回调
参数:
file:保存当前设备文件信息的文件指针
cmd:ioct1的功能码,应用程序ioct1第二个参数传递过来
arg:用于接收用户程序中的ioct1函数的函数的第三个参数的数值
return 0;}

一个ioctl的功能码是32位大小,我们需要对ioctl的函数的功能进行编码,编码的规则可以在linux内核编码中查看位置:内核源码顶层目录 /Documentation/userspace-api/ioctl/ioctl-decoding.rst记录了ioctl函数的32位功能码的编码规则



4 IOCTL 函数使用示例,--不传递第三个参数

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "led.h"int major;
char kbuf[128]={0};
gpio_t *vir_led1;
gpio_t *vir_led1;
unsigned int *vir_rcc
int  myled_open(struct inode ,struct file *file)
{printk("%s:%s:%d\n",_FILE_,func_,_LINE_);return 0;
}
ssize_t myled_read(struct file* file ,char *ubuf,size_t  size ,loff_t *lof)
{
unsigned long ret;
printk("%s ,%s ,%d\n",_FILE_,_func_,_LINE_);
if(size>sizeof(buf));
size=sizeof(kbuf);
ret=copy_to_user(ubf,kbuf,size);
if(ret)
{
printk("copy)to_user filed\n");}}
long mycdev_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{switch (cmd)
{case LED_ON://开灯
vir_led1->ODR|=(0X1<<10);
vir_led2->odr |=(0X1<<10);
vir_led3->ODR|=(0X1<<8);
break;
case LED_OFF://关灯
vir_led1->ODR&=(~(0X1<<10));
vir_led2->ODR&=(~(0x1<<10));
vir_led3->ODR&=(~(0X1<<8));
break;}int all_led_init(void )
{
vir_led1=ioremp(PHY_LED1_ADDR,sizeof(gpio_t));if (vir_led1==NULL)
{
printk("iormap filed :%d\n",_LINE_);return    ENOMEM;}
vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
if(vir_rcc==NULL)
{
printk("ioremap filed :%d\n",_LINE__);
return ENOMEM;}
printk("物理地址映射成功\n");
(*vir_rcc)|=(3<<4);
vir_led1->MODER &=(~(3<<20));
vir_led1->MODER |=(1<<20);
vir_led1->ODR &=(~(1<<10));
vir_led2->MODER&=(~(3<<20));
vir_led2->MODER|=(1<<20);
vir_led2>ODR &=(~(1<<10));
led3
vir_led3->MODER &=(~(3<<16));
vir_led1->MODER |=(1<<16);
vir_led1->ODR &=(~(1<<8));
printk("寄存器初始化成功");
return 0;
}
}
static int __init myled_init(void )
{major=register_chrdev(0,"mychrdev",&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功:major=%d\n",major);all_led_init();
return 0;
}
static void_exit myled_exit(void)
{
iounmap(vir_led1);
iounmap(vir_led2);
iounmap(vir_rcc);
//注销字符设备设备驱动
unregister_chrdev(major,"mychrdev");
}
module_init(myled_init);
module_init(muled_exit);
MODULE_LICENSE("GPL");
int main(int argc, char const *argv[])
{
char buf[128]={0};
int fd=open("/dev/mychrdev",O_RDWR);
if(fd<0)
{
printf("打开设备文件失败\n");
exit(-1);}
int a;
while(1)
{
printf("请输入要进行的控制\n");
printf(":0(关灯) 1(关灯)");
printf("请输入>");
scanf("%d",&a);
switch(a)
{
case 0:
ioctl(fd,LED_OFF);
break;
case 1:
iocal(fd,LED_ON);
break;}}close(fd);
return 0;}
int  major;
char  kbuf[128]={0};
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;
int myled_open(struct inode*inode,struct file *file){printk("%s:%s :%d\n",__FILE__,__func__,__line__);return 0;
}
ssize_t myled_read(struct file *file ,char *ubuug)
if(size>sizeof(kbuf))
size=sizeof(kbuf);
ret=copy_from_user(kbuf,ubuf,size);
if(ret){
printk("copy_to_user filed\n")
return ret;}

file结构体和inode结构体的讲解分析                                                                                                                       

        只要一个文件存在操作系统中,在操作系统的内核空间就会存在struct inode结构的全部信息

内核空间为了方便管理相同类型的结构,一般会把相同类型的结构构成一个顺序表或者内黑链表

所以在内核中的一定会存在一张内核链表或者顺序表 表中的每一个成员都是struct inode类型,保存了系统中多少文件,这个表中就会有多少成员,而inode编号就是当前文件在表中的索引号,而我们可以根据inode的结构体的对象进而获取文件的信息

struct inode {umode_t i_mode //保存文件的各种属性,权限,硬链接的数量
kuid_t    i_uid //文件的用户ID
kgid_t     i_gid//文件的用户组id
struct inode_operations *i_op//文件的操作方法结构
unsigned long
dev_t  i_rdev//保存当前文件的设备号/*
MKDEV(主设备号,次设备号):根据主设备号和次设备号获取设备号
MAJOR(设备号):根据设备号获取当时设备号的·主设备号
MINOR(设备号):根据设备号获取当前设备号的次设备号}

struct file 结构体

这个结构体息息相关,只要在进程中打开一个文件,内核就会申请一个struct file类型的结构体空间,这个空间中保存了当前被打开的文件的各种信息,包含打开文件的一些属性,当前进程的开开的文件的file 构成一个内核的顺序表,文件对应描述符fd 就是顺序表的数组下标

struct file
{struct path  f_path;//打开文件得路径
struct inode  *f_inode ;//打开前文件得innode编号
const struct file_operations *f_op //文件对应得驱动的操作方法
unsigned int f_flags//打开文件得时候需要添加的一些打开属性
unsigned int f_flags;
void  *private_data;}

ssize_t myled_lead(struct file*file,char *ubuf,size_t size,loff_t  *lof)

{

unsigned long ret;

printk(“%s:%s:%d\n",_FILE_)

}

 


http://www.ppmy.cn/news/1574192.html

相关文章

DPVS-2:单臂负载均衡测试

上一篇编译安装了DPVS&#xff0c;这一篇开启DPVS的负载均衡测试 &#xff1a; 单臂 FULL NAT模式 拓扑-单臂 单臂模式 DPVS 单独物理机 CLINET&#xff0c;和两个RS都是另一个物理机的虚拟机&#xff0c;它们网卡都绑定在一个桥上br0 &#xff0c; 二层互通。 启动DPVS …

【网络安全】从零开始的CTF生活

1、CTF是什么&#xff1f; CTF&#xff08;Capture The Flag&#xff0c;夺旗赛&#xff09;起源于 1996 年 DEFCON 全球大会&#xff0c;是网络安全爱好者之间的竞技游戏。 2、比赛怎么打&#xff1f; 1、解题模式&#xff1a; 与ACM编程竞赛、信息学奥赛类似&#xff0c;…

深入理解Zookeeper:分布式系统的协调者

引言 在现代分布式系统中&#xff0c;协调和管理多个节点之间的状态和行为是一个复杂且关键的任务。Zookeeper作为一个分布式协调服务&#xff0c;为开发者提供了一种高效、可靠的方式来处理分布式系统中的一致性问题。本文将介绍Zookeeper的基本概念、使用场景以及如何通过示…

爱普生 SG-8101CE 可编程晶振在笔记本电脑的应用

在笔记本电脑的精密架构中&#xff0c;每一个微小的元件都如同精密仪器中的齿轮&#xff0c;虽小却对整体性能起着关键作用。如今的笔记本电脑早已不再局限于简单的办公用途&#xff0c;其功能愈发丰富多样。从日常轻松的文字处理、网页浏览&#xff0c;到专业领域中对图形处理…

毕业项目推荐:基于yolov8/yolo11的水稻叶片病害检测识别系统(python+卷积神经网络)

文章目录 概要一、整体资源介绍技术要点功能展示&#xff1a;功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出&#xff08;xls格式&#xff09;功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…

Baklib智能平台:数据驱动下的企业知识安全与协作

内容概要 在数字化转型加速渗透的今天&#xff0c;企业知识资产的智能化管理与安全防护已成为核心竞争力构建的关键环节。Baklib作为新一代知识中台&#xff08;Knowledge Hub&#xff09;的典型代表&#xff0c;以数据驱动技术为核心引擎&#xff0c;重构了企业知识管理的底层…

Spring监听器Listener

目录 1、Spring监听器简介 2、事件&#xff08;Event&#xff09; 3、监听器&#xff08;Listener&#xff09; 3、事件发布器 4、监听器使用 4.1、自定义事件 4.2、自定义监听器 4.3、发布事件 4.4、测试 4.5、使用注解方式监听 4.6、异步事件处理 5、总结 1、Spri…

Web数据管理复习考点整理

Web数据管理复习考点整理 &#xff08;临近毕业&#xff0c;把之前整理的一些要发没发的东西发一下&#xff0c;希望能对后来的朋友们有所帮助。这个考点整理是我在听了ll老师的复习课之后对照着PPT一点一点写的&#xff0c;考试纯背这个&#xff0c;最终98分&#xff09; &am…