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

php做网站优点ui设计职业培训机构

php做网站优点,ui设计职业培训机构,温州企业网站建设要多少钱,建设银行官方网站首页个人登录目录一、如何编写一个驱动程序1、流程简介2、具体函数二、编写LED驱动程序2、整体代码三、混杂设备驱动1、简介2、程序编写一、如何编写一个驱动程序 1、流程简介 定义文件操作file_operations结构体(static struct file_operations fops)实现对应的op…

目录

  • 一、如何编写一个驱动程序
    • 1、流程简介
    • 2、具体函数
  • 二、编写LED驱动程序
    • 2、整体代码
  • 三、混杂设备驱动
    • 1、简介
    • 2、程序编写

一、如何编写一个驱动程序

1、流程简介

  1. 定义文件操作file_operations结构体(static struct file_operations fops)
  2. 实现对应的open、read、write、close相关函数,填入file_operations结构体
  3. 编写入口函数:注册驱动程序
    (1) 申请设备号(alloc_chrdev_region
    (2) 初始化字符设备结构体cdev变量(cdev_init
    (3)将驱动程序注册到内核中(cdev_add)
    (4)初始化硬件,完成虚拟内存和物理内存转换(ioremap
    (5)创建class和device,用来实现设备节点的自动添加(class_createdevice_create
  4. 编写出口函数:卸载驱动程序

2、具体函数

  1. 定义file_operations结构体
	static struct file_operations fops = {.owner = THIS_MODULE,.open = my_open,.read = my_read,.write = my_write,.release = my_release,};
  1. 实现对应的open、read、write、close相关函数,填入file_operations结构体
static int my_open(struct inode *inode, struct file *file) {}
static ssize_t my_read(struct file *file, char __user *buf, size_t len, loff_t *offset) {}
static ssize_t my_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) {}
static int my_release(struct inode *inode, struct file *file) {}
  1. 编写入口函数:注册驱动程序
    (1) 申请设备号
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);
示例:
dev_t dev_num;
alloc_chrdev_region(&dev_num, 0, 1, "mychardev");参数解释:
dev:用于返回分配的设备号(主设备号 + 次设备号)。
baseminor:起始次设备号。
count:申请的设备数量。
name:设备名称,用于 /proc/devices。

(2) 初始化cdev变量
(3)将驱动程序注册到内核中

void cdev_init(struct cdev *cdev, const struct file_operations *fops);
int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);
示例:
struct cdev my_cdev;
cdev_init(&my_cdev, &fops);
cdev_add(&my_cdev, dev_num, 1);参数解释:
cdev:字符设备结构体指针。
fops:文件操作结构体指针。
dev:设备号。
count:设备数量。

(4)初始化硬件
5. 编写出口函数:卸载驱动程序
6. 其他完善:实现设备节点的自动添加
(1)创建class
(2)创建device

struct class *class_create(struct module *owner, const char *name);
struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
示例:
struct class *my_class;
struct device *my_device;
my_class = class_create(THIS_MODULE, "mycharclass");
my_device = device_create(my_class, NULL, dev_num, NULL, "mychardev");参数解释:
owner:通常为 THIS_MODULE。
name:类名。
parent:父设备,通常为 NULL。
devt:设备号。
drvdata:驱动数据,通常为 NULL。
fmt:设备名称格式。

总结调用流程

static int __init mychardev_init(void) {// 申请设备号alloc_chrdev_region(&dev_num, 0, 1, "mychardev");// 初始化字符设备结构体cdev_init(&my_cdev, &fops);// 注册字符设备到内核cdev_add(&my_cdev, dev_num, 1);// 创建类,用于自动创建设备节点my_class = class_create(THIS_MODULE, "mycharclass");// 创建设备节点 /dev/mychardevmy_device = device_create(my_class, NULL, dev_num, NULL, "mychardev");return 0;
}

二、编写LED驱动程序

1、创建文件操作结构体file_operations

struct file_operations fops =
{	.owner = THIS_MODULE,.release = led_driver_close,.open = led_driver_open,.read = led_driver_read,.write = led_driver_write,
};

2、编写打开、读写、关闭等函数,填入file_operations中

int led_driver_open(struct inode *p_node, struct file *fp)
{printk("open\n");return 0;
}
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{printk("read\n");return 0;
}
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{char s[10];copy_from_user(s, user_buffer, n);ledOn(s[0]);printk("write\n");return n;
}
int led_driver_close(struct inode *p_node, struct file *fp)
{printk("close\n");return 0;
}
void ledOn(unsigned int n)
{*regGPBDAT |= (0x0F << 5);if(n < 1 || n > 4){return;}*regGPBDAT &= ~(1 << (n + 4));
}

3、编写入口函数:初始化驱动程序
(1)申请主设备号alloc_chrdev_region()

	ret = alloc_chrdev_region(&dev_num, 0, 1, "first device");if(ret){printk("alloc_chrdev_region is error\n");goto alloc_chrdev_region_err;}printk("major = %u, minior = %u\n", MAJOR(dev_num), MINOR(dev_num));

(2)初始化cdev

cdev_init(&led_dev, &fops);

(3)将cdev注册到内核中

ret = cdev_add(&led_dev, dev_num, 1);if(ret){printk("cdev_add is error\n");goto cdev_add_err;}

(4)初始化硬件,完成物理地址和虚拟地址的映射

	regGPBCON = ioremap(GPBCON, 4);regGPBDAT = ioremap(GPBDAT, 4);*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);*regGPBDAT |= (0x0F << 5);

(5)自动创建设备节点:包括class_create和device_create创建

	p_class = class_create(THIS_MODULE, "Led class");if(IS_ERR(p_class)){printk("class_create is error!");goto class_create_err;}p_device = device_create(p_class, NULL, dev_num, NULL, "led");if(p_device == NULL){printk("device_create is error\n");goto device_create_err;}

4、编写出口函数:卸载驱动程序

static void __exit led_driver_exit(void)
{iounmap(regGPBDAT);iounmap(regGPBCON);device_destroy(p_class, dev_num);class_destroy(p_class);cdev_del(&led_dev);unregister_chrdev_region(dev_num, 1);printk("exot\n");
}

2、整体代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define GPBCON  (0x56000010)
#define GPBDAT  (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;int led_driver_open(struct inode *p_node, struct file *fp)
{printk("open\n");return 0;
}ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{printk("read\n");return 0;
}void ledOn(unsigned int n)
{*regGPBDAT |= (0x0F << 5);if(n < 1 || n > 4){return;}*regGPBDAT &= ~(1 << (n + 4));
}ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{char s[10];copy_from_user(s, user_buffer, n);ledOn(s[0]);printk("write\n");return n;
}int led_driver_close(struct inode *p_node, struct file *fp)
{printk("close\n");return 0;
}struct file_operations fops =
{	.owner = THIS_MODULE,.release = led_driver_close,.open = led_driver_open,.read = led_driver_read,.write = led_driver_write,
};static dev_t dev_num;
struct cdev led_dev;
static struct class *p_class;
static struct device *p_device;static int __init led_driver_init(void)
{	int ret;ret = alloc_chrdev_region(&dev_num, 0, 1, "first device");if(ret){printk("alloc_chrdev_region is error\n");goto alloc_chrdev_region_err;}printk("major = %u, minior = %u\n", MAJOR(dev_num), MINOR(dev_num));cdev_init(&led_dev, &fops);ret = cdev_add(&led_dev, dev_num, 1);if(ret){printk("cdev_add is error\n");goto cdev_add_err;}p_class = class_create(THIS_MODULE, "Led class");if(IS_ERR(p_class)){printk("class_create is error!");goto class_create_err;}p_device = device_create(p_class, NULL, dev_num, NULL, "led");if(p_device == NULL){printk("device_create is error\n");goto device_create_err;}regGPBCON = ioremap(GPBCON, 4);regGPBDAT = ioremap(GPBDAT, 4);*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);*regGPBDAT |= (0x0F << 5);return 0;device_create_err:class_destroy(p_class);
class_create_err:cdev_del(&led_dev);
cdev_add_err:unregister_chrdev_region(dev_num, 1);
alloc_chrdev_region_err:return ret;
}static void __exit led_driver_exit(void)
{iounmap(regGPBDAT);iounmap(regGPBCON);device_destroy(p_class, dev_num);class_destroy(p_class);cdev_del(&led_dev);unregister_chrdev_region(dev_num, 1);printk("exot\n");
}module_init(led_driver_init);
module_exit(led_driver_exit);MODULE_LICENSE("GPL");

三、混杂设备驱动

1、简介

  linux内核api接口提供了一种混杂设备驱动程序框架,可以大幅度降低编写字符设备驱动程序复杂性。misc 的意思是混合、杂项的,因此misc 驱动也叫做杂项驱动,misc 驱动其实就是最简单的字符设备驱动。所有的misc 设备驱动的主设备号都为10,不同的设备使用不同的从设备号。随着Linux字符设备驱动的不断增加,设备号变得越来越紧张,尤其是主设备号,misc 设备驱动就用于解决此问题。misc 设备会自动创建cdev,不需要像我们以前那样手动创建,因此采用misc 设备驱动可以简化字符设备驱动的编写。
  使用混杂设备驱动程序和之前的方法类似,需要注册一个混杂设备。该函数需要一个struct miscdevice结构体变量的地址:

int misc_register(struct miscdevice * misc);struct miscdevice结构体中我们主要关注3个成员:
1. minor:子设备号,由于主设备号都是10,子设备号必须指定而且不能冲突, linux/miscdevice.h中定义了几个子设备号,如果需要动态获取,就用MISC_DYNAMIC_MINOR
3. name:将来在/dev下的设备名
4. fops:指向文件操作结构体变量的指针

在这里插入图片描述

2、程序编写

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
//2、编写打开、读写、关闭函数,写入到结构体中
int beep_open(struct inode *p_node, struct file *fp)
{return 0;
}int beep_release(struct inode *p_node, struct file *fp)
{return 0;
}ssize_t beep_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t * offset)
{int ret;copy_from_user(&ret, user_buffer, 4);printk("kernel : %d",ret);if(ret){*regGPBDAT |= (1 << 0);}else{*regGPBDAT &= ~(1 << 0);}return 4;
}
// 1、定义文件操作结构体
static struct file_operations fops =
{.owner = THIS_MODULE,.open = beep_open,.release = beep_release,.write = beep_write
};static struct miscdevice beep_device =
{.minor = MISC_DYNAMIC_MINOR,.name = "beep",.fops = &fops,
};// 3、编写注册函数:misc_register
static int __init beep_init(void)
{int ret;ret = misc_register(&beep_device);if(ret){printk("misc_register is error");return ret;}regGPBCON = ioremap(GPBCON, 4);regGPBDAT = ioremap(GPBDAT, 4);*regGPBCON &= ~(3 << 0);*regGPBCON |= (1 << 0);return 0;
}
// 4、编写卸载函数
static void __exit beep_exit(void)
{iounmap(regGPBCON);iounmap(regGPBDAT);misc_deregister(&beep_device);
}module_init(beep_init);
module_exit(beep_exit);MODULE_LICENSE("GPL");
http://www.dtcms.com/a/486380.html

相关文章:

  • 【ADS-1】【python基础-2】基本语法与数据结构(列表、字典、集合)
  • 简单的网站源码娱乐网站后缀是什么
  • C# 基于halcon的视觉工作流-章46-不匀面划痕
  • 一个手机的奇幻之旅(手机在基站间的切换)
  • Android thermal (4)_cooling device(上)
  • JavaEE初阶——TCP/IP协议栈:从原理到实战
  • 建设网站要买服务器徐闻网站建设公司
  • 我想网上做网站怎么做卖东西的网站
  • 用于汽车雷达应用的步进频率PMCW波形——论文阅读
  • 使用 python-docx 和 difflib 对比 Word 文档
  • 食品电子商务网站建设规划书开发网站的好处
  • 找人做的网站怎么运行精神堡垒设计
  • 开源 Linux 服务器与中间件(一)基本介绍
  • 开源 Linux 服务器与中间件(二)嵌入式Linux服务器和中间件
  • 公司建设一个网站有什么好处国外网站建设现状图分析
  • 绿色 网站 源码个人建网站怎么赚钱
  • 定时器的学习(二)
  • SpringBoot模特兼职网站zu3n3(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • windows开发中使用flutter开发鸿蒙
  • calibre LVS 跑不起来 就将setup 的LVS Option connect下的 connect all nets by name 打开。
  • 向RAGFlow中上传文档到对应的知识库
  • 网站后台发邮件建设网站都需要哪些内容
  • 惠州网站建设 英语外贸论坛有哪些?
  • 【学习笔记10】C++模板编程深度学习(下):可变参数模板与完美转发核心技术
  • 华为盘古 Ultra-MoE-718B-V1.1 正式开放下载!
  • 【OpenHarmony】AI引擎模块架构
  • 为什么选php语言做网站江苏网站建设网络推广
  • 数据结构算法学习:LeetCode热题100-链表篇(上)(相交链表、反转链表、回文链表、环形链表、环形链表 II)
  • STC亮相欧洲区块链大会,碳资产RWA全球化战略迈出关键一步
  • 使用Electron创建helloworld程序