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

Golang基于反射的ioctl实现

记录下首次使用反射特性。
还有两个比较坑的事情。一个是使用 unix.Syscall,交叉编译到ARM平台时,指定 GOARCH=arm ,如果使用的是arm64平台,unix.Syscall 调用会失败,报错:inappropriate ioctl for device 。32位平台和64位平台在内核中使用ioctl不一样,如果内核中只实现了 unlocked_ioctl ,就会报上面的错误。因此需要指定 GOARCH=arm64 。第二个,也是指定了64位平台,那么golang下的int和uint将变成64bit,即8字节,因此如果要使用4字节的长度,最好直接用int32和uint32。
下面是使用反射的代码:

package mainimport ("flag""fmt""os""reflect""golang.org/x/sys/unix"
)type Args struct {calRead  boolcalWrite boolcalFile  stringdev      string
}var gArgs Argstype hudCal struct {args *Argsdevf *os.File
}type IOC_C uint32
type IOC_T int32const (IOC_W  = 1IOC_R  = 2IOC_RW = 3
)/*** Notice!!! In arm64, int is int64!*/func parseArgs() {flag.BoolVar(&gArgs.calRead, "r", false, "Read calibration data")flag.BoolVar(&gArgs.calWrite, "w", false, "Write calibration data")flag.StringVar(&gArgs.calFile, "f", "", "Calibration file")flag.StringVar(&gArgs.dev, "d", "/dev/panel-03", "Panel device control node")flag.Parse()
}func IOC_CMD(rw IOC_T, magic byte, cmd byte, size any) IOC_C {tp := reflect.TypeOf(size)iocCmd := ((uint32(rw) & 0x3) << 30) | (uint32(magic) << 8) | uint32(cmd) | uint32((tp.Size()&0x3FFF)<<16)fmt.Printf("ioctl cmd: %x(%b)\n", iocCmd, iocCmd)return IOC_C(iocCmd)
}func ioctl(f *os.File, cmd IOC_C, value any) error {v := reflect.ValueOf(value)if v.Kind() != reflect.Ptr || !v.Elem().CanSet() {return fmt.Errorf("ioctl error: value isn't a pointer type or can't set")}_, _, errno := unix.Syscall(unix.SYS_IOCTL, f.Fd(), uintptr(cmd), uintptr(v.Pointer()))if errno != 0 {return fmt.Errorf("ioctl error: %v", errno)}return nil
}func ioctlText(h *hudCal) {var link int32cmd := IOC_CMD(IOC_R, 'f', 50, link)err := ioctl(h.devf, cmd, &link)if err != nil {fmt.Println("ioctl error:", err)os.Exit(-1)}fmt.Println("link status: ", link)
}func (h *hudCal) Open() error {var err errorh.devf, err = os.OpenFile(gArgs.dev, os.O_RDWR, 0666)return err
}func (h *hudCal) Close() {h.devf.Close()
}func main() {fmt.Println("hello world")var hud hudCalvar err errorparseArgs()hud.args = &gArgserr = hud.Open()if err != nil {fmt.Println("hud open error: ", err)}defer hud.Close()ioctlText(&hud)
}
http://www.xdnf.cn/news/483589.html

相关文章:

  • 鸿蒙5.0项目开发——鸿蒙天气项目的实现(主页2)
  • HarmonyOS 开发之 —— 合理使用动画与转场
  • userfaultfd内核线程D状态问题排查
  • 数学实验(Matlab编程基础)
  • Flutter - 集成三方库:日志(logger)
  • 【深度学习】#11 优化算法
  • 麒麟服务器操作系统安装 MySQL 8 实战指南
  • EC800X_DP-DTU-Q600R 系列开发板介绍
  • QML 动画控制、顺序动画与并行动画
  • 25考研经验贴(11408)
  • 智能呼叫系统中的NLP意图理解:核心技术解析与实战
  • 游戏引擎学习第286天:开始解耦实体行为
  • R1 快开门式压力容器操作证备考练习题及答案
  • 2025程序设计天梯赛补题报告
  • 《数字藏品APP开发:解锁高效用户身份认证与KYC流程》
  • xss-labs靶场第11-14关基础详解
  • 2025认证杯数学建模第二阶段A题完整论文(代码齐全):小行星轨迹预测思路
  • MySQL的 JOIN 优化终极指南
  • RAG-MCP:突破大模型工具调用瓶颈,告别Prompt膨胀
  • Android Studio AI插件与Bolt工具实战指南:从零到一打造智能应用
  • PostgreSQL中的全页写
  • 【python编程从入门到到实践】第十章 文件和异常
  • Spring框架(三)
  • 7.重建大师点云处理教程
  • 每周靶点:PCSK9、Siglec15及文献分享
  • python基础语法(三-中)
  • [Java][Leetcode middle] 238. 除自身以外数组的乘积
  • 学习alpha
  • 【基础】Windows开发设置入门4:Windows、Python、Linux和Node.js包管理器的作用和区别(AI整理)
  • go.mod关于go版本异常的处理