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

自己有域名怎么做免费网站网店推广的作用

自己有域名怎么做免费网站,网店推广的作用,网站广告动态图怎么做,长沙的汽车网站建设文章目录 一、概念(一)相关概念(二)字符设备框架结构(三)用户空间和内核空间数据传输1. 函数的参数对应关系 (四)字符设备相关的API1. 字符设备驱动(1)注册字…

文章目录

  • 一、概念
    • (一)相关概念
    • (二)字符设备框架结构
    • (三)用户空间和内核空间数据传输
      • 1. 函数的参数对应关系
    • (四)字符设备相关的API
      • 1. 字符设备驱动
        • (1)注册字符设备驱动
        • (2)销毁字符设备驱动
      • 2. 用户和内核数据传输
        • (1)copy_to_user
        • (2)copy_from_user
      • 3. 物理地址映射虚拟地址
        • (1)地址映射
        • (2)取消地址映射
  • 二、驱动代码示例
    • (一)查看芯片手册
      • 1. 寄存器基地址
    • (一)驱动代码
    • (二)测试

一、概念

(一)相关概念

设备号:内核识别驱动的唯一的编号,设备号由32个bit位组成

设备号(32bit)=主设备号(高12bit)+次设备号(低20bit)
主设备号:代表的是哪一类设备
次设备号:代表同类中的哪一个设备
在这里插入图片描述

(二)字符设备框架结构

在这里插入图片描述
当用户在应用层面去调用open/read/write/close函数时,操作的是设备文件;
而创建设备文件时,通过设备号把设备文件和内核层面的设备驱动联系起来,又通过file_operations操作方法结构体将函数逐个对应;
在内核层面,驱动通过操作寄存器,最后实现对硬件设备的控制

(三)用户空间和内核空间数据传输

1. 函数的参数对应关系

在这里插入图片描述
用户在应用层通过write函数将buff的内容传给内核层中mycdev_write函数中ubuf,
为了保证内核的安全性,需要通过copy_from_user函数,将ubuf的数据拷贝一份到kbuf中,通过操作kbuf来使用用户传入的数据。
read函数同理,用户在应用层通过read函数读取buf,其实在内核层面。是通过copy_to_user函数,将内核空间数据拷贝一份到kbuf,通过kbuf来传递给用户

使用*ubuf会报错:地址不允许访问

(四)字符设备相关的API

1. 字符设备驱动

(1)注册字符设备驱动
#include <linux/fs.h>int register_chrdev(unsigned int major,const char *name,const struct file_operations * fops)
功能:注册字符设备驱动; (register char device)
参数:@major:主设备号(申请到一个主设备号后,0-255的这256个次设备号会全部被分配)major > 0 用户指定主设备号,一般不使用,因为如果与系统已定义的主设备号冲突就会报错major = 0 系统动态分配主设备号@name:设备的名字@fops:操作方法结构体指针struct file_operations{int (*open) (struct inode *, struct file *);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);int (*release) (struct inode *, struct file *);}
返回值:major > 0 ,成功返回0,失败返回错误码major = 0 ,成功返回主设备号,失败返回错误码
  • 补:cat /proc/devices 查看设备名
    在这里插入图片描述
(2)销毁字符设备驱动
#include <linux/fs.h>int unregister_chrdev(unsigned int major,const char *name)
功能:销毁字符设备驱动
参数:@major:主设备号@name:设备的名字
返回值:无

2. 用户和内核数据传输

(1)copy_to_user
#include <linux/uaccess.h>int copy_to_user(void __user volatile *to, const void *from,unsigned long n)
功能:将数据从内核空间拷贝到用户空间(在驱动的在驱动的read中使用)
参数:@to:用户空间的数据首地址@from:内核空间数据首地址@n:大小,单位是字节
返回值:成功返回0,失败返回未拷贝的字节个数
(2)copy_from_user
int copy_from_user(void *to, const void __user volatile *from,unsigned long n)
功能:将数据从用户空间拷贝到内核空间(在驱动的在驱动的write中使用)
参数:@to:内核空间的数据首地址@from:用户空间数据首地址@n:大小,单位是字节
返回值:成功返回0,失败返回未拷贝的字节个数
  • 注:两个函数都是第一个参数是拷贝到哪,第二个参数是从哪里拷贝

3. 物理地址映射虚拟地址

如果要将开发板上的LED点亮,那就必须操作LED灯对应的寄存器,寄存器的地址是物理地址。
驱动运行在3-4G的虚拟地址空间,所以没有办法直接控制LED的亮灭。如果想要在内核空间操作LED那就必须将LED灯的物理地址映射成虚拟地址,以后在内核空间操作这块虚拟地址就相当于在操作LED的物理地址。

(1)地址映射
#include <linux/io.h>void *ioremap(unsigned long phy_addr, unsigned long size)
功能:将物理地址映射成虚拟地址
参数:@phy_addr:物理地址@size:映射的大小,单位是字节
返回值:成功返回内核空间的虚拟地址,失败返回NULL
  • 注:
  • ioremap一次最多映射4k字节地址
(2)取消地址映射
void iounmap(void *virt_addr)
功能:取消地址映射
参数:@virt_addr:虚拟地址
返回值:无
  • 注:地址映射后,如果不取消映射就会造成内存泄漏

二、驱动代码示例

(一)查看芯片手册

1. 寄存器基地址

图片1

(一)驱动代码

功能需求:实现LED1,LED2,LED3交替亮1s
需求分析
LED1—PE10
LED2—PF10
LED3—PE8
GPIOE基地址—0x50006000
GPIOF基地址—0x50007000
RCC_AHB4基地址—0x50000A28
代码实现

myled.h

#ifndef __MYLED_H__
#define __MYLED_H__#define GPIOE_BASE 0x50006000
#define GPIOF_BASE 0x50007000
#define RCC        0x50000A28
typedef struct{unsigned int gpiox_0:1;unsigned int gpiox_1:1;unsigned int gpiox_2:1;unsigned int gpiox_3:1;unsigned int gpiox_4:1;unsigned int gpiox_5:1;unsigned int gpiox_6:1;unsigned int gpiox_7:1;unsigned int gpiox_8:1;unsigned int gpiox_9:1;unsigned int gpiox_10:1;unsigned int gpiox_11:1;unsigned int gpiox_12:1;unsigned int gpiox_13:1;unsigned int gpiox_14:1;unsigned int gpiox_15:1;
}bitf1_t;
typedef struct{unsigned int gpiox_0:2;unsigned int gpiox_1:2;unsigned int gpiox_2:2;unsigned int gpiox_3:2;unsigned int gpiox_4:2;unsigned int gpiox_5:2;unsigned int gpiox_6:2;unsigned int gpiox_7:2;unsigned int gpiox_8:2;unsigned int gpiox_9:2;unsigned int gpiox_10:2;unsigned int gpiox_11:2;unsigned int gpiox_12:2;unsigned int gpiox_13:2;unsigned int gpiox_14:2;unsigned int gpiox_15:2;
}bitf2_t;typedef struct{volatile bitf2_t MODER;volatile bitf1_t OTYPER;volatile bitf2_t OSPEEDR;volatile bitf2_t PUPDR;volatile bitf1_t IDR;volatile bitf1_t ODR;
}gpio_t;#define LED1 1
#define LED2 2
#define LED3 3#endif

myled.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "myled.h"#define CNAME "myled"
int major; //设备号gpio_t *gpioe;
gpio_t *gpiof;
unsigned int *rcc;int kbuf[2];
int mychrdev_open(struct inode *inode, struct file *file){pr_info("%s:%d\n",__func__,__LINE__);//将虚拟地址转换为物理地址rcc=ioremap(RCC,4);if(NULL == rcc){pr_err("RCC ioremap error");return -ENOMEM;}gpioe=ioremap(GPIOE_BASE,sizeof(gpio_t));if(NULL == gpioe){pr_err("GPIOE_BASE ioremap error");return -ENOMEM;}gpiof=ioremap(GPIOF_BASE,sizeof(gpio_t));if(NULL == gpiof){pr_err("GPIOF_BASE ioremap error");return -ENOMEM;}/***初始化LED灯***///使能时钟源*rcc |= 0x3<<4;//RCC使能GPIOE和GPIOF//PE10和PE8输出模式01gpioe->MODER.gpiox_10=1;gpioe->MODER.gpiox_8=1;gpiof->MODER.gpiox_10=1;//输出低电平gpioe->ODR.gpiox_10=0;gpioe->ODR.gpiox_8=0;gpiof->ODR.gpiox_10=0;return 0;
}
ssize_t mychrdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *offset){int ret;pr_info("%s:%s:%d\n", __FILE__, __func__, __LINE__);if (size > sizeof(kbuf))size = sizeof(kbuf);ret = copy_to_user(ubuf, kbuf, size);if (ret) {pr_err("copy_to_user error\n");return -EIO;}return 0;
}
ssize_t mychrdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *offset){int ret;pr_info("%s:%s:%d\n", __FILE__, __func__, __LINE__);memset(kbuf, 0, sizeof(kbuf));if (size > sizeof(kbuf))size = sizeof(kbuf);ret = copy_from_user(kbuf, ubuf, size);if (ret) {pr_err("copy_from_user error\n");return -EIO;}switch(kbuf[0]){case LED1:kbuf[1]==1?(gpioe->ODR.gpiox_10=1):(gpioe->ODR.gpiox_10=0);break;case LED2:kbuf[1]==1?(gpiof->ODR.gpiox_10=1):(gpiof->ODR.gpiox_10=0);break;case LED3:kbuf[1]==1?(gpioe->ODR.gpiox_8=1):(gpioe->ODR.gpiox_8=0);break;}return 0;
}
int mychrdev_close(struct inode *inode, struct file *file){pr_info("%s:%d\n",__func__,__LINE__);//取消虚拟映射iounmap(rcc);iounmap(gpioe);iounmap(gpiof);return 0;
}const struct file_operations myfops = {.open=mychrdev_open,.read=mychrdev_read,.write=mychrdev_write,.release=mychrdev_close,
};static int __init mychrdev_init(void){//注册设备major = register_chrdev(0,CNAME,&myfops);if(major < 0){pr_err("register error:%d\n",major);return major;//返回错误码}pr_info("major = %d\n",major);//打印设备号return 0;
}
static void __exit mychrdev_exit(void){//注销设备unregister_chrdev(major,CNAME);
}module_init(mychrdev_init);
module_exit(mychrdev_exit);
MODULE_LICENSE("GPL");
  • 注:使用的交叉编译器版本比较老,对语法检查要求更高,要求变量只能在函数开头定义,否则报错。

(二)测试

在这里插入图片描述

  • 补:错误码 /include/uapi/asm0generic/errno-base.h
    在这里插入图片描述
http://www.zhongyajixie.com/news/25492.html

相关文章:

  • 相亲网站如何做如何做网络销售产品
  • azure做网站网页界面设计
  • 在网站加上一个模块怎么做无人区在线观看高清1080
  • 网站建设公司招人竞价点击软件工具
  • 烟台做网站联系电话优化公司
  • 高端html5网站建设seo培训网的优点是
  • 深圳网站空间微信营销软件免费版
  • 免费个人网站源码下载百度百度
  • 做汽车保养的网站提高工作效率的方法不正确的是
  • 自己的主机做网站服务器怎么做好seo内容优化
  • 做电子商务网站需要什么软件软文写作经验
  • 如何把自己做的网站广州seo排名优化
  • 怎样做网站吸引人免费网站站长查询
  • 大连淘宝网站建设口碑营销的产品
  • 网站热力图怎么做24小时免费看的视频哔哩哔哩
  • 台州外贸网站网络营销推广活动有哪些
  • 动效网站建设网站制作公司高端
  • 网站建设项目的工期计划seo优化的主要内容
  • 网站浮标怎么做百度云资源搜索
  • 建立一个网站怎么做如何在百度上做广告
  • 工商管理网站推广软件排行榜前十名
  • 做lol数据的网站有哪些整站优化多少钱
  • 江苏做网站找谁品牌seo主要做什么
  • 深圳模板网站建设站长是什么级别
  • 望野朗读网络营销优化推广公司
  • 响应式环保网站模板服务营销的概念
  • 网站建设那家公司好北京网站推广服务
  • 如何建设一个彩票网站站长工具whois查询
  • 微商做图王官方网站关键词抓取工具都有哪些
  • 东莞网站开发推荐如何自己搭建网站