5. 驱动开发
文章目录
- 一、驱动开发
- 1.1 前言
- 1.2 何谓驱动框架
- 1.3 内核驱动框架中LED的基本情况
- 1.3.1 相关文件
- 1.3.2 九鼎移植的内核中led驱动
- 1.3.3 案例分析驱动框架的使用
- 1.3.4 典型的驱动开发行业现状
- 1.4 初步分析led驱动框架源码
- 1.4.1 涉及到的文件
- 1.4.2 subsys_initcall
- 1.4.3 led_class_attrs
- 1.4.4 led_classdev_register
- 1.5 在内核中添加或去除某个驱动
- 1.5.1 去除九鼎移植的LED驱动
- 1.5.2 添加led驱动框架支持
- 二、实践---基于驱动框架写led驱动
- 2.1 分析
- 2.2 在驱动中将LED设备分开
- 三、gpiolib引入
一、驱动开发
1.1 前言
驱动一般是驱动开发工程师或内核维护者。驱动编程协作是有一定的要求,接口标准化,从而尽量降低驱动开发者难度。
1.2 何谓驱动框架
(1) 内核中驱动部分维护者针对每个种类的驱动设计一套成熟的、标准的、典型的驱动实现,然后把不同厂家的同类硬件驱动中相同的部分抽出来自己实现好,再把不同部分留出接口给具体的驱动开发工程师来实现,这就叫驱动框架。
(2) 内核维护者在内核中设计了统一管控系统资源的体系,这些体系让内核能够对资源在各个驱动之间的使用统一协调和分配,保证整个内核的稳定运行。譬如系统中所有的GPIO就属于系统资源,每个驱动模块如果要使用某个GPIO就要先调用特殊的接口先申请,申请到后使用,使用完后要释放。又譬如中断号也是一种资源,驱动在使用前也必须去申请。这也是驱动框架的组成部分。
(3) 一些特定的接口函数、一些特定的数据结构,这些是驱动框架的直接表现。
1.3 内核驱动框架中LED的基本情况
1.3.1 相关文件
(1) drivers/leds目录,这个目录就是驱动框架规定的LED这类硬件驱动存放的位置。
(2) led-class.c和led-core.c,这两个文件加起来属于LED驱动框架的第一部分,这两个文件是内核开发者提供的,描述的是内核中所有厂家的不同LED硬件的相同部分的逻辑。
(3) leds-xxxx.c,这个文件是LED驱动框架的第2部分,是由不同厂商的驱动工程师编写添加的,厂商驱动工程师结合自己公司的硬件的不同情况来对LED进行操作,使用第一部分提供的接口来和驱动框架进行交互,最终实现驱动的功能。
1.3.2 九鼎移植的内核中led驱动
(1) 九鼎实际未使用内核推荐的led驱动框架
(2) drivers/char/led/x210-led.c
1.3.3 案例分析驱动框架的使用
(1) 以leds-s3c24xx.c为例。leds-s3c24xx.c中通过调用led_classdev_register来完成LED驱动的注册,而led_classdev_register是在drivers/leds/led-class.c中定义的。所以其实SoC厂商的驱动工程师是调用内核开发者在驱动框架中提供的接口来实现自己的驱动的。
(2) 驱动框架的关键点就是:分清楚内核开发者提供了什么,驱动开发者自己要提供什么
1.3.4 典型的驱动开发行业现状
(1) 内核开发者对驱动框架进行开发和维护、升级,对应led-class.c和led-core.c
(2) SoC厂商的驱动工程师对设备驱动源码进行编写、调试,提供参考版本,对应leds-s3c24xx.c
(3) 做产品的厂商驱动工程师以SoC厂商提供的驱动源码为基础,来做移植和调试
1.4 初步分析led驱动框架源码
1.4.1 涉及到的文件
(1) led-core.c(只简单包含一些头文件)
(2) led-class.c(包含led驱动框架的主要部分)
1.4.2 subsys_initcall
(1) 经过基本分析,发现LED驱动框架中内核开发者实现的部分主要是led-class.c
(2) 对led-class.c分析应该从下往上,遵从对模块的基本分析方法。
(3) 为什么LED驱动框架中内核开发者实现的部分要实现成一个模块?
因为内核开发者希望这个驱动框架是可以被装载/卸载的。这样当内核使用者不需要这个驱动框架时可以完全去掉,需要时可以随时加上。
(4) subsys_initcall是一个宏,定义在linux/init.h中。经过对这个宏进行展开,发现这个宏的功能是:将其声明的函数放到一个特定的段:.initcall4.init。
subsys_initcall
__define_initcall(“4”,fn,4)
(5) 分析module_init宏,可以看出它将函数放到了.initcall6.init段中。
module_init
__initcall
device_initcall
__define_initcall(“6”,fn,6)
(6) 内核在启动过程中需要顺序的做很多事,内核如何实现按照先后顺序去做很多初始化操作。内核的解决方案就是给内核启动时要调用的所有函数归类,然后每个类按照一定的次序去调用执行。这些分类名就叫.initcalln.init。n的值从1到7。内核开发者在编写内核代码时只要将函数设置合适的级别,这些函数就会被链接的时候放入特定的段,内核启动时再按照段顺序去依次执行各个段即可。
比如负责内核链接的文件 vmlinux.lds( 此文件编译内核时会自动生成)。
(7) 经过分析,可以看出,subsys_initcall和module_init的作用是一样的,只不过前者所声明的函数要比后者在内核启动时的执行顺序更早。
1.4.3 led_class_attrs
(1) 什么是attribute,对应将来/sys/class/leds/目录里的内容,一般是文件和文件夹。这些文件其实就是sysfs开放给应用层的一些操作接口(非常类似于/dev/目录下的那些设备文件)
(2) attribute有什么用,作用就是让应用程序可以通过/sys/class/leds/目录下面的属性文件来操作驱动进而操作硬件设备。
(3) attribute其实是另一条驱动实现的路线。有区别于之前讲的file_operations那条线。
1.4.4 led_classdev_register
(1) 分析可知,led_classdev_register这个函数其实就是去创建一个属于leds这个类的一个设备。其实就是去注册一个设备。所以这个函数其实就是led驱动框架中内核开发者提供给SoC厂家驱动开发者的一个注册驱动的接口。
(2) 当使用led驱动框架去编写驱动的时候,这个led_classdev_register函数的作用类似于我们之前使用file_operations方式去注册字符设备驱动时的register_chrdev函数。
1.5 在内核中添加或去除某个驱动
1.5.1 去除九鼎移植的LED驱动
(1) 九鼎移植的驱动在应用层的接口在/sys/devices/platform/x210-led/目录下,有led1、led2、led3、led4四个设备文件,各自管理一个led。
(2) 要去掉九鼎自己移植的led驱动,要在make menucofig中去掉选择项,然后重新make得到zImage,然后重启时启动这个新的zImage即可。
make menuconfig Devices Driverscharcter devicesx210 led driver //按N去掉,保存退出重新make 编译得到新的zImage
(3) 新的内核启动后,如果/sys/devices/platform/目录下已经没有了x210-led这个目录,就说明去掉这个驱动成功了。
1.5.2 添加led驱动框架支持
(1) 当前内核中是没有LED驱动框架的,要去添加它。
make menuconfigDevice Drivers[*]LED support[*]LED class support
然后make编译之后,重新得到zImage,通过tftp启动,进入/sys/class,看见添加的leds就是成功。
二、实践—基于驱动框架写led驱动
2.1 分析
(1) 参考 drivers/leds/leds-s3c24xx.c
(2) 关键点:led_classdev_register
1) 驱动被加载了,/sys/class/leds/目录下确实多出来了一个表示设备的文件夹。文件夹里面有相应的操控led硬件的2个属性brightness和max_brightness
2) led-class.c中brightness方法有一个show方法和store方法,这两个方法对应用户在/sys/class/leds/myled/brightness目录下直接去读写这个文件时, 实际执行的代码。
当show brightness时,实际就会执行led_brightness_show函数
当echo 1 > brightness时,实际就会执行led_brightness_store函数
(3) show方法实际要做的就是读取LED硬件信息,然后把硬件信息返回即可。所以show方法和store方法必要要会去操控硬件。但是led-class.c文件又属于驱动框架中的文件,它本身无法直接读取具体硬件,因此在show和store方法中使用函数指针的方式调用了struct led_classdev结构体中的相应的读取/写入硬件信息的方法。
(4) struct led_classdev结构体中的实际用来读写硬件信息的函数,就是要写的驱动文件leds-s5pv210.c中要提供的。
2.2 在驱动中将LED设备分开
(1) 好处 :驱动层实现对各个LED设备的独立访问,并向应用层展示出4个操作接口led1、led2、led3、led4,这样应用层可以完全按照自己的需要对LED进行控制。
驱动的设计理念:不要对最终需求功能进行假定,而应该只是直接的对硬件的操作。有一个概念就是:机制和策略的问题。在硬件操作上驱动只应该提供机制而不是策略。策略由应用程序来做。
#include <linux/module.h> // module_init module_exit
#include <linux/init.h> // __init __exit
#include <linux/fs.h>
#include <linux/leds.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>#define GPJ0CON S5PV210_GPJ0CON
#define GPJ0DAT S5PV210_GPJ0DATstatic struct led_classdev mydev1; // 定义结构体变量
static struct led_classdev mydev2; // 定义结构体变量
static struct led_classdev mydev3; // 定义结构体变量// 这个函数就是要去完成具体的硬件读写任务的
static void s5pv210_led1_set(struct led_classdev *led_cdev,enum led_brightness value)
{printk(KERN_INFO "s5pv210_led1_set\n");writel(0x11111111, GPJ0CON);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭//writel(0x11111111, GPJ0CON);// 读改写三部曲writel((readl(GPJ0DAT) | (1<<3)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮//writel(0x11111111, GPJ0CON);writel((readl(GPJ0DAT) & ~(1<<3)), GPJ0DAT);}
}static void s5pv210_led2_set(struct led_classdev *led_cdev,enum led_brightness value)
{printk(KERN_INFO "s5pv2102_led_set\n");writel(0x11111111, GPJ0CON);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭//writel(0x11111111, GPJ0CON);// 读改写三部曲writel((readl(GPJ0DAT) | (1<<4)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮//writel(0x11111111, GPJ0CON);writel((readl(GPJ0DAT) & ~(1<<4)), GPJ0DAT);}
}static void s5pv210_led3_set(struct led_classdev *led_cdev,enum led_brightness value)
{printk(KERN_INFO "s5pv210_led3_set\n");writel(0x11111111, GPJ0CON);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭//writel(0x11111111, GPJ0CON);// 读改写三部曲writel((readl(GPJ0DAT) | (1<<5)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮//writel(0x11111111, GPJ0CON);writel((readl(GPJ0DAT) & ~(1<<5)), GPJ0DAT);}
}static int __init s5pv210_led_init(void)
{// 用户insmod安装驱动模块时会调用该函数// 该函数的主要任务就是去使用led驱动框架提供的设备注册函数来注册一个设备int ret = -1;// led1mydev1.name = "led1";mydev1.brightness = 255; mydev1.brightness_set = s5pv210_led1_set;ret = led_classdev_register(NULL, &mydev1);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}// led2mydev2.name = "led2";mydev2.brightness = 255; mydev2.brightness_set = s5pv210_led2_set;ret = led_classdev_register(NULL, &mydev2);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}// led3mydev3.name = "led3";mydev3.brightness = 255; mydev3.brightness_set = s5pv210_led3_set;ret = led_classdev_register(NULL, &mydev3);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}return 0;
}static void __exit s5pv210_led_exit(void)
{led_classdev_unregister(&mydev1);led_classdev_unregister(&mydev2);led_classdev_unregister(&mydev3);
}module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_AUTHOR("aston <1264671872@qq.com>"); // 描述模块的作者
MODULE_DESCRIPTION("s5pv210 led driver"); // 描述模块的介绍信息
MODULE_ALIAS("s5pv210_led"); // 描述模块的别名信息
测试结果:
三、gpiolib引入
(1) 一个事实:很多硬件都要用到GPIO、GPIO会复用
(2) 如果同一个GPIO被2个驱动同时控制了,就会出现bug
(3) 内核提供gpiolib来统一管理系统中所有GPIO
(4) gpiolib本身属于驱动框架的一部分
后续整理总结[6.Linux内核的gpiolib]。
相关文章:
5. 驱动开发
文章目录一、驱动开发1.1 前言1.2 何谓驱动框架1.3 内核驱动框架中LED的基本情况1.3.1 相关文件1.3.2 九鼎移植的内核中led驱动1.3.3 案例分析驱动框架的使用1.3.4 典型的驱动开发行业现状1.4 初步分析led驱动框架源码1.4.1 涉及到的文件1.4.2 subsys_initcall1.4.3 led_class_…...
模板方法模式详解
模板方法模式(行为模式) 1. 模板方法模式介绍 父类定义算法骨架,细节的具体实现延迟到子类子类只是定义某些自己的个性化处理,但不改变执行顺序 2. 好处 减少代码冗余,共性抽取后算法流程更加清晰与规范降低流程性…...
关于 Lightweight process container,ChatGPT的答案
晓楚 Can you give me a list of process container? As an AI language model, I can provide you with a list of popular process containers, which are as follows: Docker Kubernetes Apache Mesos LXC OpenVZ systemd-nspawn rkt (Rocket) Linux Containers (LXC) Ga…...
机器学习和深度学习的综述
机器学习和深度学习的综述 1.1.1人工智能、机器学习、深度学习的关系 人工智能(Artificial Intelligence,AI)是最宽泛的概念,是研发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。由于这个定义…...
Synopsys Sentaurus TCAD系列教程之--Sprocess(SmallMOS_2D3D) 解析
SmallMOS_2D3D解析 #header## STI depth set sti_depth 0.15 ## Half STI width set sti_width sti_width ## Half gate length set gate_len <lg/2> ## SD length (from center) set sd_len [expr $gate_len0.05]#endheader## X lines line x location 0.0 spacing 0.…...
好使!NAS中傻瓜式配置反向代理及SSL证书,提升网络安全性!
对于有NAS或者有个人主机的朋友来说,将机器映射到外网是基本操作。 但是一般来说,能直接从外网访问的往往仅有80和443端口。事实上,运营商一般把家庭宽带的这两个端口都封了,所以如果我们想要从外网访问自己家中机器部署的服务&a…...
数据结构队列-先进先出
一,概述 队列这个概念非常好理解。你可以把它想象成排队买票,先来的先买,后来的人只能站末尾,不允许插队。先进者先出,这就是典型的“队列”。 二,顺序队列和链式队列 队列和栈一样,也是一种…...
CentOS 7使用TiUP部署TiDB
本文主要是根据官方文档指导,结合实际主机情况,在Cent OS7上使用TiUP在线部署TiDB。 环境说明 类型操作系统版本配置中控机Deepin 20.34核CPU6G内存40G硬盘TiDB部署机Cent OS 7.38核CPU48G内存100硬盘网络情况中控机与外网相连,中控机与部署…...
java单元测试批处理数据模板【亿点点日志配合分页以及多线程处理】
文章目录引入相关资料环境准备分页查询处理,减少单次批量处理的数据量级补充亿点点日志,更易观察多线程优化查询_切数据版多线程_每个线程都分页处理引入 都说后端开发能顶半个运维,我们经常需要对大量输出进行需求调整,很多时候…...
【数据结构】模拟实现 堆
堆数据结构是一种数组对象,它可以被看作一颗完全二叉树的结构(数组是完全二叉树),堆是一种静态结构。堆分为最大堆和最小堆。最大堆:每个父结点都大于孩子结点。最小堆:每个父结点都小于孩子结点。堆的优势…...
Go语言学习的第三天--上部分(基础用法)
前两天经过不断度娘,与对up主的跟踪学习了解了go的历史,今天开始了go的基础!!本章主要是go 的注释、变量及常量的梳理一、注释不管什么语言都有自己的注释,go也不例外 !!单行注释 // 多行注释 …...
linux面试基础篇
题目目录1.简述DNS分离解析的工作原理,关键配置2.apache有几种工作模式,分别简述两种工作模式及其优缺点?3.写出172.0.0.38/27 的网络id与广播地址4.写出下列服务使用的传输层协议(TCP/UDP)及默认端口5.在局域网想获得…...
黑马程序员提高变成
这里写目录标题函数模板1.2.2 函数模板注意事项1.2.3 函数模板案例调用规则类模板与函数模板区别类模板与继承类模板成员函数类外实现#pragma once类模板与友元案例重新定义【】stl2.2 STL基本概念STL六大组件容器算法迭代器初识vectorvector容器嵌套容器string容器string赋值操…...
MySQL5种索引类型
MySQL的类型主要有五种:主键索引、唯一索引、普通索引、空间索引、全文索引 有表: CREATE TABLE t1 ( id bigint unsigned NOT NULL AUTO_INCREMENT, u1 int unsigned NOT NULL DEFAULT 0, u2 int unsigned NOT NULL DEFAULT 0, u3 varchar(20) NOT NU…...
uniapp封装缓存方法,支持类似cookie具有过期时间
1、定义CacheManage类,有set和get方法 class CacheManage {set() {},get() {} }set用来设置缓存,get用来获取缓存 2、完善set业务逻辑 大概逻辑如下: 1、将接收params参数,包含key、data、unit、time key 缓存字段,…...
Jfrog 搭建本地maven仓库以及上传Android库
Jfrog 下载 安装包下载地址:Download Artifactory OSS | JFrog 如果是想下载之前的版本,可以点击上面的Get code source ,如果是最新版本,直接点下面的下载就好。下面以Linux安装为例。 Jfrog安装 对于Linux而言,其实…...
日报周报月报工作总结生成器【智能文案生成器】
日报周报月报工作总结生成器【智能文案生成器】 天天写日报,我真的快奔溃了! 摸了一天鱼,下班还要写日报; 划了一周的水,周末还要写周报; 啊啊啊啊… 在职场上,尤其是互联网公司里,…...
linux日志管理工具logrotate配置
linux日志管理工具logrotate配置logrotate介绍logrotate配置讲解主配置文件解释(/etc/logrotate.conf)logrotete 命令参数添加配置以添加一个nginx配置为例强制启动配置logrotate介绍 logrotate是centos自带工具,其他操作系统可能需要自行安装。logrotate用来进行日…...
[ C++ ] 设计模式——单例模式
目录 1.设计模式: 2.单例模式 饿汉模式 懒汉模式 饿汉模式和懒汉模式的优缺点 1.设计模式: 设计模式(Design Pattern)是一套被反复使用,多数人只晓得,经过分类的,代码设计经验的总结。为什么会产生设计模式这样的…...
HACKTHEBOX——Help
nmap可以看到对外开放了22,80,3000端口可以看到80端口和3000端口都运行着http服务,先从web着手切入TCP/80访问web提示无法连接help.htb,在/etc/hosts中写入IP与域名的映射打开只是一个apache default页面,没什么好看的使用gobuster扫描网站目…...
Qt广告机客户端(下位机)
目录功能结构adClient.promain.cppadclient.h 客户端adclient.cpp 客户端addate.h 时间处理addate.cpp 时间处理adsocket.h 客户端Socket处理adsocket.cpp 客户端Socket处理weather.h 天气信息处理weather.cpp 天气信息处理rollmassege.h 滚动信息处理rollmassege.cpp 滚动信息…...
JavaScript新手学习手册-基础代码(二)
与上篇博客相接 一:函数: 案例:通过函数实现绝对值的输出 方法一: function absoluate(x){if(x>0){return x;}else{ return -x;}} 在控制台调用函数 方法二: var demo1 function(x){if(x>0){return x;}els…...
wireshark 抓包使用记录
文章目录前言wireshark 抓包使用记录一、wireshark的基础使用二、wireshark的常用功能1、开始混杂模式2、过滤器操作2.1、抓包过滤器2.2、显示过滤器3、时间格式显示4、统计流量图5、标记显示6、导出数据包7、增加、隐藏、删除显示列前言 如果您觉得有用的话,记得给…...
pd dataframe 读取处理 有合并单元格的excel方式
from pathlib import Path import openpyxl 拆分所有的合并单元格,并赋予合并之前的值。 由于openpyxl并没有提供拆分并填充的方法,所以使用该方法进行完成 def unmerge_and_fill_cells(worksheet): all_merged_cell_ranges list( worksheet.merged_…...
七,iperf3源代码分析:状态机及状态转换过程--->运行正向TCP单向测试时的服务端代码
本文目录一、测试用命令二、iperf3状态机中各个状态解析三、iperf3状态机迁移分析K-初始化测试对象(NA--->初始化状态):A-服务器端测试对象开始运行(初始化状态--->IPERF_START状态):B-建立控制连接(初始化状态-…...
【网络篇】----- 传输层协议 之 UDP(协议格式,协议特性和编程影响三方面详细分析)
文章目录 前言1、UDP协议2、协议格式 2.1、协议格式模型2.2、字段分析3.协议特性4.编程影响总结前言 1、UDP协议 UDP协议,又名数据报传输协议,是传输层协议之一!!! 在TCP/IP五层模型中,在传输层中ÿ…...
【基于STM32的多功能台灯控制】
基于STM32的多功能台灯控制 在之前一篇博文中已出过智能台灯相关的介绍,在这里对之前的模块以及功能上进行了优化和功能上的改进,需源码或实物可私【创作不易-拒绝白嫖】 功能说明 1、按键模式多功能台灯在设计上使用了4个按键分别做为 按键1模式的切换…...
Mac 编译x264源码No working C compiler found 错误
在mac上编译x264源码时,报错No working C compiler found 。网上找了一圈方案也无法解决 只能硬着头皮看configure这个脚本,通过一步一步抽丝拨茧终于是在mac上可以编译了。 这里只当记录一下,为后续同学遇到同样问题提供一个辅助解决方案。…...
如何有效地降低软件开发风险?
1、科学分析风险 高风险自动预警 一般对风险进行科学分析,主要从3个维度进行划分:影响的严重性、发生的可能性、产生的影响性。 根据风险对项目的影响程度,从3个维度将其划分5个等级:很低、比较低、中等、比较高、很高。这样我们能…...
【python】剑指offer代码大集合2
本文是【python】剑指offer代码大集合的姊妹篇,用于完善标识todo的代码! 刷题网站:https://leetcode.cn/problem-list/xb9nqhhg/ 剑指 Offer 14- I. 剪绳子 https://leetcode.cn/problems/jian-sheng-zi-lcof/ todo 剑指 Offer 14- II. 剪绳子 II https://leetcode.cn/pr…...
怎么在服务器做网站/班级优化大师头像
作者简介: 李中凯老师,8年前端开发,前端负责人,擅长JavaScript/Vue。 公众号:1024译站 掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts 主要分享:Vue.js, Jav…...
万网wordpress安装教程/百度秒收录技术
观察以下代码结果,为什么? 原因是因为:运算数类型整形除整形结果还是整形,计算机中float和double都是IEEE754标准 1记录浮点数的,以上代码中得到的值是3,转化为IEEE754标准值就是0.0000000 解决办法1&…...
pc开奖网站开发/网址缩短在线生成器
来源是:Text at LEFT如何更改CSS以使两个DIV看起来像?----------------------|Text at LEFT | ####|| | ####|| | ####|| | || | |----------------------即。文本在左侧DIV左上角,图像在右侧DIV右上方对齐。更新:我使用的是&…...
做网站建设需要/信息流优化
这次的 JDK 10 只是一个小版本更新,不过还是引入了一些非常重要的改变,我就挑几个对一般开发者影响重大的特性说说吧。Java 10 引入了局部变量类型推断,现在我们可以使用 var 替换局部变量声明时的类型部分,从而避免耗费精力去写出…...
网站如何做企业电子宣传册/产品营销网站建设
1、 数据库建表如何加密:采用哈希函数散列的方式将密码进行加密,此过程不可逆. 插入数据: --创建表; ----用户表; CREATE TABLE tb_User (No CHAR(10) NOT NULL PRIMARY KEY ,Password VARBINARY(128) NOT …...
如何不用域名也可以做网站/品牌推广工作内容
file ./liveMedia/rtcp_from_spec.o ./liveMedia/rtcp_from_spec.o: ELF 32-bit LSB relocatable, MIPS, MIPS32 rel2 version 1 (SYSV), not stripped...