当前位置: 首页 > news >正文

广告设计模板网站宣传片拍摄应急预案

广告设计模板网站,宣传片拍摄应急预案,如何建一个商业网站,友情链接互换简介 一个字符设备驱动通常会实现常规的open、release、read和write接口,但是如果需要扩展新的功能,通常以ioctl接口的方式实现。 #mermaid-svg-uY8EyPklf5e4ZMQo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill…

简介

一个字符设备驱动通常会实现常规的openreleasereadwrite接口,但是如果需要扩展新的功能,通常以ioctl接口的方式实现。

user space vfs driver ioctl() sys_ioctl() ulocked_ioctl()或compat_ioctl() user space vfs driver

用户空间的ioctl

#include <sys/ioctl.h> 
int ioctl(int fd, int cmd, ...) ;
参数描述
fd文件描述符
cmd交互协议,设备驱动将根据cmd执行对应操作
可变参数arg,依赖cmd指定的长度以及类型
返回值执行成功时返回0,失败则返回-1

驱动中的ioctl

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

在新版内核中,unlocked_ioctl()与compat_ioctl()取代了ioctl()。unlocked_ioctl(),顾名思义,应该在无大内核锁(BKL)的情况下调用;compat_ioctl(),compat全称compatible(兼容的),主要目的是为64位系统提供32位ioctl的兼容方法,也是在无大内核锁的情况下调用。

在字符设备驱动开发中,一般情况下只要实现unlocked_ioctl()即可,因为在vfs层的代码是直接调用unlocked_ioctl()。

ioctl命令,用户与驱动之间的协议

前文提到ioctl方法第二个参数cmd为用户与驱动的“协议”,理论上可以为任意int型数据,可以为0、1、2、3……,但是为了确保该“协议”的唯一性,ioctl命令应该使用更科学严谨的方法赋值,在linux中,提供了一种ioctl命令的统一格式,将32位int型数据划分为四个位段,如下图所示:

img

在内核中,提供了宏接口以生成上述格式的ioctl命令:

// include/uapi/asm-generic/ioctl.h#define _IOC(dir,type,nr,size) \(((dir)  << _IOC_DIRSHIFT) | \((type) << _IOC_TYPESHIFT) | \((nr)   << _IOC_NRSHIFT) | \((size) << _IOC_SIZESHIFT))
  • dir(direction),ioctl命令访问模式(数据传输方向),占据2bit,可以为_IOC_NONE、_IOC_READ、_IOC_WRITE、_IOC_READ | _IOC_WRITE,分别指示了四种访问模式:无数据、读数据、写数据、读写数据;
  • type(device type),设备类型,占据8bit,在一些文献中翻译为“幻数”或者“魔数”,可以为任意char型字符,例如‘a’、‘b’、‘c’等等,其主要作用是使ioctl命令有唯一的设备标识。**tips:**Documentions/ioctl-number.txt记录了在内核中已经使用的“魔数”字符,为避免冲突,在自定义ioctl命令之前应该先查阅该文档。
  • nr(number),命令编号/序数,占据8bit,可以为任意unsigned char型数据,取值范围0~255,如果定义了多个ioctl命令,通常从0开始编号递增;
  • size,涉及到ioctl第三个参数arg,占据13bit或者14bit(体系相关,arm架构一般为14位),指定了arg的数据类型及长度,如果在驱动的ioctl实现中不检查,通常可以忽略该参数。

通常而言,为了方便会使用宏_IOC()衍生的接口来直接定义ioctl命令:

// include/uapi/asm-generic/ioctl.h/* used to create numbers */
#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))

同时,内核还提供了反向解析ioctl命令的宏接口:

// include/uapi/asm-generic/ioctl.h/* used to decode ioctl numbers */
#define _IOC_DIR(cmd)        (((cmd) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(cmd)       (((cmd) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(cmd)     (((cmd) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(cmd)       (((cmd) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

示例

#ifndef __HAPTCIS_IOCTL_H__
#define __HAPTCIS_IOCTL_H__/** @Date: 2024-10-12 15:53:37* @LastEditors: zdk* @LastEditTime: 2024-10-14 11:47:49* @FilePath: \kernel\drivers\haptics\haptics_ioctl.h*/#include <linux/ioctl.h>
// #include <sys/ioctl.h>   // 用户空间/*这里使用ioctl定义两个协议,读寄存器和写寄存器
*用户空间和内核空间共用的头文件,包含ioctl命令及相关宏定义,可以理解为一份“协议”文件
*/
//cmd中的type
#define DEVICE_TYPE           'H'
#define HAPTICS_READ_REG_NR   (0)
#define HAPTICS_WRITE_REG_NR  (1)
#define HAPTICS_READ_REG      _IOR(DEVICE_TYPE,HAPTICS_READ_REG_NR,ioctl_protocol_t *)  
#define HAPTCIS_WRITE_REG     _IOW(DEVICE_TYPE,HAPTICS_WRITE_REG_NR,ioctl_protocol_t *)typedef struct
{uint8_t reg_addr;uint8_t reg_value;
}ioctl_protocol_t;#endif

这个头文件是共用的,因为他定义了协议的具体内容。

/**  Silicon Integrated Co., Ltd haptic sih688x haptic driver file**  Copyright (c) 2021 heater <daokuan.zhu@si-in.com>** This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public License version 2 as published by* the Free Software Foundation*/#include <linux/init.h>  //包含宏定义的头文件
#include <linux/module.h>   //包含初始化加载模块的头文件
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include "haptics_ioctl.h"#define HAPTICS_MISC_DEV_NAME  "haptics"//打开设备
static int haptics_open(struct inode* inode,struct file * filp)
{printk("%s\n",__FUNCTION__);return 0;
}//关闭设备
static int haptics_release(struct inode* inode ,struct file* filp)
{printk("%s\n",__FUNCTION__);return 0;
}//ioctl
static long haptics_ioctl(struct file * filp, unsigned int cmd, unsigned long arg)
{int ret = 0;ioctl_protocol_t msg;//反解cmd中的字段int type = _IOC_TYPE(cmd);int dir = _IOC_DIR(cmd);int nr = _IOC_NR(cmd);int size = _IOC_SIZE(cmd);printk("dir=%d size=%d\n",dir,size);//检验cmd是否正确//1.校验cmd_typeif(DEVICE_TYPE != type){printk(KERN_ERR "cmd type error\n");ret =-1;return ret;}if(HAPTICS_READ_REG == cmd)//读寄存器{//校验nrif(HAPTICS_READ_REG_NR == nr){ret = copy_from_user(&msg, (ioctl_protocol_t __user *)arg, sizeof(ioctl_protocol_t));printk("read_reg:%#02x\n",msg.reg_addr);msg.reg_value=0xff;//这里模拟读寄存器的值//将读取到的值传给用户空间ret = copy_to_user((ioctl_protocol_t __user *)arg, &msg, sizeof(ioctl_protocol_t));}}else if(HAPTCIS_WRITE_REG == cmd)//写寄存器{//校验nrif(HAPTICS_WRITE_REG_NR == nr){ret = copy_from_user(&msg, (ioctl_protocol_t __user *)arg, sizeof(ioctl_protocol_t));printk("write_reg:%#02x=%#02x\n",msg.reg_addr,msg.reg_value);//模拟写寄存器的值}}else//{printk(KERN_ERR "unknown cmd\n");}return ret;
}static struct file_operations haptics_fops=
{.owner = THIS_MODULE,.open = haptics_open,.release = haptics_release,.unlocked_ioctl = haptics_ioctl,
};struct miscdevice mdev =
{.minor = MISC_DYNAMIC_MINOR,.name = HAPTICS_MISC_DEV_NAME,.fops = &haptics_fops,
};//定义一个杂项设备结构体static int __init haptics_init(void)
{int ret = 0;//内核层只能使用printk,不能使用printfprintk(KERN_EMERG "%s\n",__FUNCTION__); //输出等级为0ret = misc_register(&mdev);if(0 == ret){printk(KERN_EMERG "misc_register ok minor=%d\n",mdev.minor);}return 0;
}static void __exit haptics_exit(void)
{misc_deregister(&mdev);printk(KERN_EMERG "%s\n",__FUNCTION__); //输出等级为0
}module_init(haptics_init);//驱动入口
module_exit(haptics_exit);//驱动出口MODULE_AUTHOR("<daokuan.zhug@si-in.com>");//声明作者信息
MODULE_DESCRIPTION("Haptics Driver V1.0.0"); //对这个模块作一个简单的描述
MODULE_LICENSE("GPL v2");//声明开源许可证// "GPL" 是指明 这是GNU General Public License的任意版本// “GPL v2” 是指明 这仅声明为GPL的第二版本

上面是驱动代码,负责解析ioctl命令。

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "haptics_ioctl.h"
/*
argc:应用程序参数个数,包括应用程序本身
argv[]:具体的参数内容,字符串形式
./main <filename> <r:w> r表示读 w表示写
*/int main(int argc,char * argv[])
{ioctl_protocol_t msg;char* filename;int fd=0;if(argc!=3){printf("error usage\n");return -1;}filename=argv[1];fd = open(filename,O_RDWR);if(fd<0){printf("can not open file %s\n",filename);return -2;}if(0 == strcmp(argv[2],"r")){msg.reg_addr = 0x01;ioctl(fd,HAPTICS_READ_REG,&msg);printf("read %#02x=%#02x\n", msg.reg_addr,msg.reg_value);}else if(0 == strcmp(argv[2],"w")){msg.reg_addr = 0x01;msg.reg_value = 0xff;ioctl(fd,HAPTCIS_WRITE_REG,&msg);}else{printf("error usage\n");}close(fd);
}

上面是应用层代码,负责发送ioctl消息。

在这里插入图片描述

注意:

  • _IOR中第三个参数size是参数的大小,用于驱动中解析使用,但是如果是固定长度,这个参数也没有用到。理论上使用_IOR_IOW_IO是没有严格区别的,所以我们上述代码中可以改为\#define HAPTICS_READ_REG _IO(DEVICE_TYPE,HAPTICS_READ_REG_NR)
  • ioctl函数中第三个参数,表示传入驱动的实际参数,可以是一个整型值,也可以是一个结构体指针。我们示例中是传入的结构体指针。
http://www.bjxfkj.com.cn/article/107851.html

相关文章:

  • 怎么修改网站信息西维科技做网站怎么样
  • 做网站行情巩义网站建设费用
  • 网站行业认证怎么做佛冈网站建设
  • 网站开发验收资料北京价格网
  • 站外推广昆山门户网站
  • 网站背景视频是怎么做的中国企业网官方网站下载
  • 模板演示网站正能量网址能直接用的
  • 好网站推理wordpress sql文件
  • 做网站得多钱美团网站开发费用
  • 网站都需要续费免费公司取名器
  • 西安网站优化招聘网湖南长沙网站建设公司
  • 重庆网站建设的培训机构算命网站搭建
  • 招聘网站做沙龙龙岩招聘求职网站有哪些
  • 佛山网站制作网页制作重庆万州网站建设费用
  • dw怎样去除网站做的页面模板下载一个app软件
  • 个人网站工商备案上海优化网站排名
  • 佛山网站制作系统wordpress连载插件
  • 旅游网站开发工具电商建设网站
  • 做网站撘框架惠州seo网站排名
  • 网站设计昆明请举例说明什么是网络营销
  • 怎样用别人的网站做修改病句新手做网站选材
  • 网站更换域名 seo淘宝运营培训
  • 网站建设dream服务好的赣州网站建设
  • 凯盛建设公司网站国内比较牛的网站建设
  • 网站建设和信息工作会议大企业网站样式
  • 广州印刷网站建设做的网站怎么放在网上
  • 网站制作费多少企业策划
  • 巴中市平昌县建设局网站开发网站需要什么开发工具
  • 网站管理与建设总结百度小说搜索风云榜排名
  • 浙江省建设厅官方网站信用平台安徽工程建设信息网站6