UEFI 事件
UEFI 不再支持中断(准确地说,UEFI 不再为开发者提供中断支持,但在UEFI内部还是使用了时钟中断),所有的异步操作都要通过事件(Event)来完成。
启动服务为开发者提供了用于操作事件、定时器及TPL(任务优先级)的函数。这些函数可以分为三类:事件相关函数、定时器相关函数及 TPL相关函数。
事件函数
启动服务中事件相关函数有 6 个,函数名大部分以 Event
结尾。提供给事件生产者的函数有 CreateEvent/CreateEventEx
、SignalEvent
及CloseEvent
。提供给事件使用者的有WaitForEvent
和CheckEvent
。
等待事件的服务 WaitForEvent
WaitForEvent
用于等待事件的发生,类似于 Windows 提供的 WaitForMultipleObjects(...)
。
WaitForEvent
是阻塞操作,直到 Event
数组内任一事件被触发,或任一事件导致错误出现,WaitForEvent
才返回。WaitForEvent
从前到后依次检查 Event
数组内的事件,发现有被触发的事件或遇到错误则返回,如果所有事件都没有被触发,则从头开始重新检查。
当检查到某个事件处于触发态时,*Index
赋值为该事件在Event
数组中的下标,返回前该事件将重置为非触发态。
当检查到某个事件是EVT_NOTIFY_SIGNAL
类型时,*Index
赋值为该事件在Event
数组中的下标,并返回EFI_INVALID_PARAMETER
。
WaitForEvent
必须运行在 TPL_APPLICAION
级别,否则将返回 EFI_UNSUPPORTED
。
WaitForEvent
没有超时属性,如果想让 WaitForEvent
只等待一定的时间,则需要在事件等待数组加入定时器事件。
生成事件的服务 CreateEvent
CreateEvent
用于生成一个事件。
1.事件的类型
事件的类型可以是以下一种或几种基本类型的组合:
- EVT_TIMER:定时器事件。普通
Timer
事件,没有Notification
函数。生成事件后需调用SetTimer
服务设置时钟属性; - EVT_NOTIFY_WAIT:普通事件。这个事件有一个
Notification
函数,当这个事件通过CheckEvent()
检查状态或通过WaitForEvent()
等待时,这个Notification
函数会被放到待执行队列gEventQueue[Event->NotifyTpl]
中; - EVT_NOTIFY_SIGNAL:普通事件。这个事件有一个
Notification
函数,当这个事件通过SignalEvent()
被触发时,这个Notifcation
函数会被放到待执行队列gEventQueue[Event->NotifyTpl]
中等待执行; - 0x00000000:普通事件。此类事件没有Notification 函数。
还有两种特殊的事件,它们用在操作系统系统加载器从启动期向运行时期转换的过程中:
- EVT_SIGNAL_EXIT_BOOT_SERVICES:此类事件是一种特殊的
EVT_NOTIFY_SIGNAL
,实际上它是EVT_NOTIFY_SIGNAL
和0x00000001
的组合。当ExitBootServices()
执行时,事件被触发。EVT_SIGNAL_EXIT_BOOT_SERVICES
不能和其他类型混合使用。它的Notification
函数和子函数不能使用启动服务中的内存分配服务;在Notification
函数执行前所有的定时器服务都已失效,因而在Notificaiton
函数中也不能使用定时器服务。 - EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:它是
EVT_RUNTIME_CONTEXT
、EVT_RUNTIME
、EVT_NOTIFY_SIGNAL
和0x00000002
的组合。它不能和这 4 种类型之外的类型组合使用。当SetVirtualAddressMap()
被调用时触发此类事件。
2.优先级
CreateEvent
的第二个参数为NotifyTPL
(即任务优先级),它可以是 0 ~ 31 的一个整数。
UEFI 预定义了以下 4 个优先级:
- TPL_APPLICATION:预定义的 4 个级别中最低的一个优先级。应用程序运行(包括 Boot Manager 和 OS Loader)在这个级别。当程序运行在这个级别时,任务队列中没有任何处于就绪状态的事件
Notification
函数; - TPL_CALLBACK:比较耗时的操作通常在这个优先级执行,如文件系统、磁盘操作等;
- TPL_NOTIFY:运行在这个级别的程序不允许阻塞必须尽快执行完毕并且返回。如果需要更多操作,则需要使用
Event
由内核重新调度。通常,底层的 IO 操作允许在这个级别。大部分Event
的Notification
函数允许在这个级别; - TPL_HIGH_LEVEL:优先级最高级别。在此级别,中断被禁止。UEFI 内核全局变量的修改需要允许在这个级别。
3.Notification 函数 NotifyFunction
CreateEvent
的第三个参数NotifyFunction
是EFI_EVENT_NOTIFY
类型的函数指针。
如果事件的类型是 EVT_NOTIFY_WAIT
,则 EFI_EVENT_NOTIFY
函数会在等待此事件的过程中调用;如果事件的类型是EVT_NOTIFY_SIGNAL
,则 EFI_EVENT_NOTIFY
函数会在事件触发时调用。既没有 EVT_NOTIFY_WAIT
属性也没有EVT_NOTIFY_SIGNAL
属性的事件,Notification
参数将被忽略。
CreateEvent
的第4个参数是NotifyContext
,将在Notification
函数被调用时作为第 2 个参数传递给该函数,用于指向这个Notification
函数的上下文。
CreateEventEx 服务
CreateEventEx
服务用于生成事件并将事件加入事件组。
由 CreateEventEx
生成的事件会加入到EventGroup
中。当EventGroup
中的任一事件被触发后,组中的所有其他事件都会被触发,进而同组内所有的Notification
函数都将被加入到待执行队列。同组内 NotifyTpl
(优先级)高的Notification
函数会先被执行。
如果输入参数EventGroup
为NULL
,则CreateEventEx
退化为 CreateEvent
。
Type
不能是 EVT_SIGNAL_EXIT_BOOT_SERVICES
或 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
,因为这两种类型有各自对应的Group
。
UEFI 预定义的 4 个 Event 组:
事件相关的其他函数
1.检查事件状态的服务CheckEvent()
CheckEvent
用于检测事件的状态。与WaitForEvent
不同的是,CheckEvent
调用后立刻返回。
2.触发事件的服务 SignalEvent
SignalEvent
用于将事件的状态设置为触发态。如果事件类型为EVT_NOTIFY_SIGNAL
,则将其 Notification
函数添加到就绪队列准备执行。如果该事件属于一个组,则将该组内所有事件都设置为触发态,并将组内所有EVT_NOTIFY_SIGNAL
事件的Notification
函数添加到就绪队列准备执行。
3.关闭事件的服务CloseEvent
事件使用完毕后,必须调用CloseEvent
关闭这个事件:
通常的原则是由事件的所有者(即调用CreateEvent
产生该事件的调用者)调用CloseEvent
函数。调用该函数后,指定的事件将从内核中删除。
定时器函数
定时器是一类特殊的事件,生成定时器事件后,可以通过SetTimer
服务设置定时器属性。
SetTimer
服务的函数原型:
Type
是定时器类别:
任务优先级
UEFI标准虽然不支持多线程,但是UEFI中有任务的概念:一个程序是一个任务,事件的Notification
函数也是一个任务。UEFI没有给开发者提供中断接口,但 UEFI 内核的运行需要时钟中断的支持,时钟中断处理函数也是一个任务。
例如,时钟中断任务的重要性要大于定时器的Notification
函数,而定时器的 Notification
函数的重要性大于普通应用程序。UEFI为任务定义了任务级别,以便有限的计算机资源可以相对合理地分配给众多的任务。
提升和恢复任务优先级
RaiseTPL(NewTpl)
用于提升当前任务的任务优先级至NewTpl
,该函数的返回值为原来的任务优先级。RestoreTPL
用于恢复(通常是降低)任务优先级至原来的优先级。
RaiseTPL
和 RestoreTPL
必须成对出现,执行了RaiseTPL
后,必须尽快调用 RaiseTPL
将任务优先级恢复到原来的值。
当任务优先级提升至TPL_HIGH_LEVEL
时,将关闭中断。当任务优先级从TPL_HIGH_LEVEL
恢复到原来的(比TPL_HIGH_LEVEL
低的)值时,中断被重新打开。
在任务优先级恢复到原优先级之前,所有高于原优先级的触发态事件的Notification
函数都要执行完毕。
UEFI是单CPU单线程系统,产生数据竞争的唯一可能来自中断处理函数,因而可以利用这一特性实现锁,这正是 UEFI 锁的实现机制。
UEFI 中的时钟中断
UEFI 用事件机制取代了 BIOS 中的中断机制,虽然 UEFI 不再提供中断接口,但其实现却离不开中断尤其是时钟中断。时钟中断是事件机制的基础。
1.时钟处理函数 CoreTimerTick
在时钟中断中调用,是时钟中断处理函数的主体。该函数执行期间必须关中断并且不能被其他任何任务干扰,因而进入函数时需要加锁,离开函数时需要解锁。它的主要功能是维持系统时间,检查定时器事件列表中是否有到期的事件。
2.设置时钟处理函数及安装时钟中断
mArchProtocols
数组是 UEFI 系统 DXE
阶段的全局变量,存放了体系结构相关的 Protocol
,系统初始化时会为 mArchProtocols
中的每个元素生成一个事件,当这个元素对应的 Protocol
安装时,该事件会触发,在事件的回调函数中会对该Protocol
做相应的初始化。
Protocol 在内核中的组织:
所有的 Protocol
均放在 mProtocolDatabase
指向的PROTOCOL_ENTRY
链表中。PROTOCOL_ENTRY
包含三个链表。
AllEntries
是PROTOCOL_ENTRY
链。
Protocols
指向此Protocol
的所有实例。
Notify
指向 PROTOCOL_NOTIFY
链表,当 PROTOCOL_ENTRY.ProtocolD
对应的 Protocol
安装时,Notify
链表中所有Event
都会触发。
例如,mArchProtocols[3]
为{&gEfiTimerArchProtocolGuid, (VOID**)&gTimer, NULL, NULL, FALSE}
,是EFI_TIMER_ARCH_PROTOCOL
对应的 EFI_CORE_PROTOCOL_NOTIFY_ENTRY
项;
CoreNotifyOnProtocolInstallation
执行后,mArchProtocols[3]
为{&gEfiTimerArchProtocolGuid, ( VOlD** )&gTimer, timerEvent, Registration, FALSE}
,TimerEvent
的 Notification
函数被 CoreRegisterProtocolNotify
函数注册到系统。
CoreRegisterProtocolNotify(…)
函数的主要功能是在 mProtocolDatabase
数据库中注册PROTOCOL_NOTIFY
。当Protocol
安装时,会检查该Protocol
对应的PROTOCOL_ENTRY.Notify
。如果PROTOCOL_ENTRY.Notify
存在,则触发它指向的事件。
当 EFI_TIMER_ARCH_PROTOCOL
安装时,mArchProtocols[3].Event
事件会触发,然后这个事件的响应函数 GenericProtocolNotify
会执行,在 GenericProtocoINotify
中通过 EFI_TIMER_ARCH_PROTOCOL
的RegisterHandler
时钟中断处理函数。
向 gimer 注册 CoreTimerTick 函数
gTimer
是EFI_TIMER_ARCH_PROTOCOL*
类型的全局变量。
gTimer->RegisterHandler
这个函数指针指向了函数 TimerDriverRegisterHandler
。
mTimerNotifyFunction
这个函数指针将在时钟中断处理函数TimerInterruptHandler
中被调用。
向 CPU 注册中断处理函数 TimerInterruptHandler
在 TimerDriverlnitialize
中,最终通过 EFI_CPU_ARCH_PROTOCOL
的 RegisterInterruptHandler
注册了 TimerInterruptHandler
。另外,在中断处理函数中将会调用 TimerInterruptHandler
,而TimerlnterruptHandler
又会调用 mTimerNotifyFunction
, 即 CoreTimerTick
。
而 mCpu->RegisterInterruptHandler
将会调用CpuRegisterInterruptHandler
函数:
此函数注册并启用由 InterruptHandler
为处理器中断或由InterruptType
指定的异常类型指定的处理程序。如果InterruptHandler
为NULL
,则取消安装由InterruptType
指定的处理器中断或异常类型的处理程序。安装的处理程序对于每个处理器中断或异常调用一次。
在 CPU 时钟中断向量中调用时钟中断处理函数
默认的中断向量主要功能是调用CommonInterruptEntry
。该函数主要完成以下任务:
1)保存寄存器;
2)调用ExternalVectorTable[InterruptType]
;
3)恢复寄存器,从中断处理返回。
在时钟中断向量中,ExternalVectorTable[InterruptType]
指向函数 TimerInterruptHandler
。
时钟中断的执行过程:
注册时钟中断函数和注册时钟处理函数的过程:
UEFI 事件 Notification 函数的派发
Event的一个重要作用是实现异步操作,事件 Notification
函数的派发是在gBS->RestoreTpl
服务中完成的。gBS->RestoreTpl
实际指向CoreRestoreTpl
函数:
内容来源于 《UEFI 原理与编程》。。。
相关文章:
UEFI 事件
UEFI 不再支持中断(准确地说,UEFI 不再为开发者提供中断支持,但在UEFI内部还是使用了时钟中断),所有的异步操作都要通过事件(Event)来完成。 启动服务为开发者提供了用于操作事件、定时器及TPL…...
大师开讲-图形学领域顶级专家王锐开讲Vulkan、VSG开源引擎
王锐,毕业于清华大学,图形学领域顶级专家,开源技术社区的贡献者与推广者。三维引擎OpenSceneGraph的核心基石开发者与维护者,倾斜摄影数据格式osgb的发明人。著有《OpenSceneGraph 3 Cookbook》,《OpenSceneGraph 3 Beginers Guid…...
小F的矩阵值调整
问题描述 小F得到了一个矩阵。如果矩阵中某一个格子的值是偶数,则该值变为它的三倍;如果是奇数,则保持不变。小F想知道调整后的矩阵是什么样子的。 测试样例 样例1: 输入:a [[1, 2, 3], [4, 5, 6]] 输出:…...
ORB-SLAM2 ----- LocalMapping::SearchInNeighbors()
文章目录 一、函数意义二、函数讲解三、函数代码四、本函数使用的匹配方法ORBmatcher::Fuse()1. 函数讲解2. 函数代码 四、总结 一、函数意义 本函数是用于地图点融合的函数,前面的函数生成了新的地图点,但这些地图点可能在前面的关键帧中已经生成过了&a…...
给UE5优化一丢丢编辑器性能
背后的原理 先看FActorIterator的定义 /*** Actor iterator* Note that when Playing In Editor, this will find actors only in CurrentWorld*/ class FActorIterator : public TActorIteratorBase<FActorIterator> {//..... }找到基类TActorIteratorBase /*** Temp…...
【Docker】常用命令汇总
Docker 是1个开源的应用容器引擎,基于Go 语言并遵从 Apache2.0 协议开源。 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 容器是完全使用沙箱机制,相…...
Mybatis:CRUD数据操作之多条件查询及动态SQL
Mybatis基础环境准备请看:Mybatis基础环境准备 本篇讲解Mybati数据CRUD数据操作之多条件查询 1,编写接口方法 在 com.itheima.mapper 包写创建名为 BrandMapper 的接口。在 BrandMapper 接口中定义多条件查询的方法。 而该功能有三个参数,…...
【笔记】轻型民用无人驾驶航空器安全操控
《轻型民用无人驾驶航空器安全操控》 理论考试培训材料 法规部分 【民用无人驾驶航空器的分类】 1、如何定义微型、轻型无人驾驶航空器? 微型无人驾驶航空器,是指空机重量小于0.25千克,最大平飞速度不超过40千米/小时,无线电发…...
TouchGFX设计模式代码实例说明
一)Model - View - Presenter (MVP) 模式在 TouchGFX 中的应用 1)Model(模型): 模型代表应用程序的数据和业务逻辑。例如,在一个简单的计数器应用中,模型可以是一个包含计数器当前值的类。 class CounterModel { pri…...
flink学习(7)——window
概述 窗口的长度(大小): 决定了要计算最近多长时间的数据 窗口的间隔: 决定了每隔多久计算一次 举例:每隔10min,计算最近24h的热搜词,24小时是长度,每隔10分钟是间隔。 窗口的分类 1、根据window前是否调用keyBy分为键控窗口和非键控窗口…...
restTemplate get请求
报错解释: 这个报错信息表明在使用RestTemplate进行GET请求时,需要提供一个请求类型(reqType),但是传入的值为空。这通常意味着在构建请求或者调用方法时,没有正确设置请求的Content-Type头部,…...
ffmpeg 预设的值 加速
centos 安装ffmpeg 编译安装 官网获取最新的linux ffmpeg 代码 https://ffmpeg.org//releases/ mkdir -p /data/app/ffmpeg cd /data/app/ffmpeg wget http://www.ffmpeg.org/releases/ffmpeg-7.1.tar.gz tar -zxvf ffmpeg-7.1.tar.gz#安装所需的编译环境 yum install -y \…...
maven <scope>compile</scope>作用
在 Maven 项目中, 元素用于定义依赖项的作用范围。 元素可以有多个值,每个值表示不同的作用范围。其中,scope compile scope 是默认的作用范围,表示该依赖项在编译、测试和运行时都需要。 scope compile scope 的含义 1、编译时…...
Ubuntu Server 22.04.5 从零到一:详尽安装部署指南
文章目录 Ubuntu Server 22.04.5 从零到一:详尽安装部署指南一、部署环境二、安装系统2.1 安装2.1.1 选择安装方式2.1.2 选择语言2.1.3 选择不更新2.1.4 选择键盘标准2.1.5 选择安装版本2.1.6 设置网卡2.1.7 配置代理2.1.8 设置镜像源2.1.9 选择装系统的硬盘2.1.10 …...
反射机制了解
反射概念 了解反射背景 存在某些变量或形参的声明类型是Object类型,但是程序却需要调用该对象运行时类型的方法,该方法不是Object中的方法,如何解决。转到如何获取该对象运行时类型的方法。 只能运行时才能获取,这就用到反射。 …...
机器学习策略Ⅰ
机器学习策略Ⅰ 在构建一个好的监督学习系统时,通常需要确保以下四个方面: 系统需要在训练集上能够很好地拟合数据,达到某种可接受的性能水平(如接近人类水平)。如果训练集表现不好,可以使用更大的模型&…...
redis中的bigkey及读取优化
一、bigKey介绍 1、简介 在 Redis 中,Big Key(大键)指的是占用大量内存的单个键。通常,Redis 是一个高性能的内存数据库,但是当某些键变得非常大时,会带来性能上的影响。例如,大量的内存消耗、长时间的操作延迟,甚至可能导致 Redis 停止响应或崩溃。 通俗的来说,指…...
【西瓜书】支持向量机(SVM)
支持向量机(Support Vector Machine,简称SVM)。 超平面 分类学习最基本的想法就是基于训练集合D在样本空间中找到一个划分超平面,将不同类别的样本分开。 但能将训练样本分开的划分超平面可能有很多,应该努力去找到哪…...
三维渲染中顺序无关的半透明混合(OIT)(二——Stencil Route)
1、A-Buffer算法。 在谈到Stencil Route之前,需要先讨论A-Buffer算法。A-Buffer是一种图形学(渲染方向)上的用于可见面分析(Visble Surface Detection)的技术,是Z-Buffer的衍生方法。 Z-Buffer是用于剔除 不透明 物体的算法。假…...
(SAST检测规则-3)固定的 SessionID 缺陷详解
漏洞类型: 会话固定攻击(Session Fixation Attack) 漏洞描述: 会话固定攻击是利用服务器的会话管理机制存在漏洞,攻击者通过提前控制或预测用户的会话标识符(Session ID),当用户登录…...
【安卓开发】【Android Studio】项目构建(Build)时报错:Integer Overflow
一、问题描述 在安卓项目中,构建(Build)失败并报错:xxxxx Integer Overflow(整型溢出)。 二、相关代码 刚开始以为是某个整数(例如控件、java类)不匹配造成的,检查如下…...
STM32主要功能
STM32 是由意法半导体(STMicroelectronics)推出的一系列基于 ARM Cortex-M 内核的微控制器(MCU)。STM32 微控制器广泛应用于嵌入式系统中,因其高性能、低功耗、丰富的外设接口和多种封装形式而被广泛采用。其主要功能和…...
MacOS 如何连接 Linux NFS 服务器
以 Ubuntu 为例。 Ubuntu 服务器端设置 1. 进入 root 权限,安装 NFS 服务: apt-get update apt-get install nfs-kernel-server2. 创建共享目录: mkdir /data chown nobody:nogroup /data chmod 777 /data3. 配置 /etc/exports 文件: vi …...
【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-39
文件下载与邀请翻译者 学习英特尔开发手册,最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册,会是一件耗时费力的工作。如果有愿意和我一起来做这件事的,那么ÿ…...
摄影相关常用名词
本文介绍与摄影相关的常用名词。 曝光 Exposure 感光元件接收光线的过程,决定图像的明暗程度和细节表现。 光圈 Aperture 控制镜头进光量的孔径大小,用 F 值(f-stop) 表示。 光圈越大(F 值越小),…...
02.06、回文链表
02.06、[简单] 回文链表 1、题目描述 编写一个函数,检查输入的链表是否是回文的。 2、解题思路: 快慢指针找中点: 利用快慢指针的技巧来找到链表的中间节点。慢指针 slow 每次移动一步,而快指针 fast 每次移动两步。这样&…...
Shell脚本小练习
学习了这么长时间Shell脚本,总得来一次小小的练习吧,那么请看下文! 1.用Shell写一个小计算器。 通过read命令获取用户输入的表达式,表达式的格式设定为操作数1 运算符 操作数2,例如53,然后利用设计的脚本…...
四轮转向轮式里程计设计(python)
目录 写在前面的话参考教程官方教程参考代码(c) 关键代码解析订阅车轮速度订阅车轮转向订阅四轮转向控制模式积累速度和转向角发布里程计 完整代码完整视频演示 写在前面的话 上一篇博客:键盘控制车子四轮转向 这篇文章通过订阅车轮的速度和…...
多方法做配对样本t检验(三)
Wilcoxon符号秩检验 Wilcoxon符号秩检验(Wilcoxon Signed-Rank Test) 是一种非参数统计方法,用于检验两组相关样本(配对样本)之间的差异是否显著。它通常用来代替配对样本t检验,特别是在数据不符合正态分布…...
Vue 将推出「无虚拟DOM」版本,又是新的前端框架趋势?
文章目录 背景无虚拟DOM版的Vue3Vue Vapor 在线演练题外话:渲染流程 背景 随着 React 和 Vue 这些前端框架的爆火,他们的渲染方式,虚拟DOM,也跟着火了起来,大家都认为这是一种高性能批量更新DOM的方式但是近一两年有不…...
做asp动态网站制作流程/建站软件可以不通过网络建设吗
栈与队列就像一对兄弟一样,学习的时候可以一块学习。 栈的特点:先进后出 队列的特点:先进先出 一、头文件 栈的头文件 #include<stack> 队列的头文件 #include<queue> 二、定义 栈的定义:stack<TYPE> s; 队列…...
我的世界做图片网站/口碑营销什么意思
集合-set集合是高中数学中的一个概念一堆确定的无序的唯一的数据,集合中每一个数据成为一个元素#集合的定义s set()print(type(s))print(s)print("*"*30)#此时,大括号内一定要有值,否则定义出的是一个dicts {}print(type(s))print(…...
网站论坛怎么建设/进行seo网站建设
在《人月神话》中,布鲁克斯老先生将维护软件的" 概念完整性" 作为软件开发的核心问题。软件之所以很复杂、难以维护,根本原因就在于软件的概念完整性遭到了破坏,甚至开发团队的成员从来就没有意识到有必要去维护软件的概念完整性&a…...
中国诗歌网个人网页/东莞seo优化推广
由于注释表明您希望使用初始化程序和initargs参数传递featureVector.在Unix类型的系统上,这将导致大量的性能提升(即使selLabel中只有1个项目),因为该值将使用os.fork基本上免费传递给子进程.否则,每次调用foo时,featureVector都将被父进程pickle,通过管道传递并由子进程进行un…...
帮别人做彩票网站/口碑seo推广公司
linux下给目录下所有子目录和文件赋权 chmod -R 777 * 给所有文件指定用户和用户组 chown - R wang.users /his 把目录/his及其下的所有文件和子目录的属主改成wang,属组改成users。...
深圳网站建设推广平台/黑龙江新闻头条最新消息
数据类型介绍MySQL 数据类型分类整型浮点型字符类型(char与varchar)日期类型枚举与集合具体数据类型见这篇博客MySQL表操作中的约束primary key 主键约束 非空唯一unique key 唯一约束not null 非空约束foreign key 外键约束创建表的的语法CREATE TABLE[IF NOT EXISTS] tbl_nam…...