技术标签: 微服务 # gin框架开发 golang # golang微服务 gin 验证码微服务
本次内容需要 gin框架基础知识, golang微服务基础知识才能更好理解
在前面,讲解了微服务的架构等,这里,来讲解前面商城项目的 Captcha验证码 微服务 ,captcha验证码功能在前台,后端 都要用到 ,可以把它 抽离出来 ,做成微服务功能
编辑
这个验证码功能封装代码captcha.go如下:
package models
//验证码属性: https://captcha.mojotv.cn/
import (
"github.com/mojocn/base64Captcha"
"image/color"
)
//创建store,保存验证码的位置,默认为mem(内存中)单机部署,如果要布置多台服务器,则可以设置保存在redis中
//var store = base64Captcha.DefaultMemStore
//配置RedisStore, 保存验证码的位置为redis, RedisStore实现base64Captcha.Store接口
var store base64Captcha.Store = RedisStore{}
//获取验证码
func MakeCaptcha(height int, width int, length int) (string, string, error) {
//定义一个driver
var driver base64Captcha.Driver
//创建一个字符串类型的验证码驱动DriverString, DriverChinese :中文驱动
driverString := base64Captcha.DriverString{
Height: height, //高度
Width: width, //宽度
NoiseCount: 0, //干扰数
ShowLineOptions: 2 | 4, //展示个数
Length: length, //长度
Source: "1234567890qwertyuioplkjhgfdsazxcvbnm", //验证码随机字符串来源
BgColor: &color.RGBA{ // 背景颜色
R: 3,
G: 102,
B: 214,
A: 125,
},
Fonts: []string{"wqy-microhei.ttc"}, // 字体
}
driver = driverString.ConvertFonts()
//生成验证码
c := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := c.Generate()
return id, b64s, err
}
//校验验证码
func VerifyCaptcha(id string, VerifyValue string) bool {
// 参数说明: id 验证码id, verifyValue 验证码的值, true: 验证成功后是否删除原来的验证码
if store.Verify(id, VerifyValue, true) {
return true
} else {
return false
}
}
把这个验证码做成微服务的话,就需要实现上面的两个方法: 获取验证码(MakeCaptcha), 校验验证码(VerifyCaptcha)
在server目录下运行: go-micro new service captcha,生成captcha服务端代码
运行命令后,生成的服务端目录如下:
在这个文件中编写 获取验证码,验验证码相关代码
syntax = "proto3";
package captcha;
option go_package = "./proto/captcha";
service Captcha {
//获取验证码: MakeCaptchaRequest请求, MakeCaptchaRequest返回
rpc MakeCaptcha(MakeCaptchaRequest) returns (MakeCaptchaResponse) {}
//校验验证码: VerifyCaptchaRequest请求, VerifyCaptchaResponse返回
rpc VerifyCaptcha(VerifyCaptchaRequest) returns (VerifyCaptchaResponse) {}
}
//以下具体参数类型参考captcha.go中对应的方法
//获取验证码请求参数
message MakeCaptchaRequest {
//验证码高度
int32 height =1;
//验证码宽度
int32 width = 2;
//验证码长度
int32 length = 3;
}
//获取验证码返回数据
message MakeCaptchaResponse {
//验证码id
string id = 1;
//验证码base64编码
string b64s = 2;
}
//校验验证码请求参数
message VerifyCaptchaRequest {
//验证码id
string id = 1;
//输入的验证码
string verifyValue = 2;
}
//校验验证码返回数据
message VerifyCaptchaResponse {
//校验的结果
bool verifyResult = 1;
}
参考 [golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例,windows下运行 Makefile里面的proto下的代码 :protoc --proto_path=. --micro_out=. --go_out=:. proto/captcha.proto, 当然,如果是初次使用go-micro,则还需运行init下面的代码(@go xxx),引入相关包
在captcha目录下运行命令: go mod init captcha,初始化项目
删除go.mod后再次执行 go mod init captcha命令:
运行命令 :go mod tidy,加载项目需要的包:
上面表示:下载 "go-micro.dev/v4"这个包失败了,这时则需运行命令 go get go-micro.dev/v4, 具体参考 : [golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例
在这里可能会出现 import中始终报红 的情况,解决见 : golang开启mod后import报红解决方案
在cmd中运行命令: consul agent -dev,具体参考: [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群
具体参考: [golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例,代码如下:
package main
import (
"captcha/handler"
pb "captcha/proto/captcha"
"go-micro.dev/v4"
"go-micro.dev/v4/logger"
"github.com/go-micro/plugins/v4/registry/consul"
)
var (
service = "captcha"
version = "latest"
)
func main() {
//集成consul
consulReg := consul.NewRegistry()
// Create service
srv := micro.NewService(
micro.Address("127.0.0.1:8081"), //指定微服务的ip: 选择注册服务器地址,也可以不配置,默认为本机,也可以选择consul集群中的client
micro.Name(service),
micro.Version(version),
//注册consul
micro.Registry(consulReg),
)
srv.Init(
micro.Name(service),
micro.Version(version),
)
// Register handler
if err := pb.RegisterCaptchaHandler(srv.Server(), new(handler.Captcha)); err != nil {
logger.Fatal(err)
}
// Run service
if err := srv.Run(); err != nil {
logger.Fatal(err)
}
}
参考 proto/captcha.proto里面的 service Captcha 方法实现,也可以参考生成的 .pb.micro.go里面生成的方法进行实现
// Client API for Captcha service
type CaptchaService interface {
// 获取验证码: MakeCaptchaRequest请求, MakeCaptchaRequest返回
MakeCaptcha(ctx context.Context, in *MakeCaptchaRequest, opts ...client.CallOption) (*MakeCaptchaResponse, error)
// 校验验证码: VerifyCaptchaRequest请求, VerifyCaptchaResponse返回
VerifyCaptcha(ctx context.Context, in *VerifyCaptchaRequest, opts ...client.CallOption) (*VerifyCaptchaResponse, error)
}
把 一.Captcha验证码功能引入中captcha.go的代码复制到 handler/captcha.go中, 然后修修改改就可以了
把" github.com/mojocn/base64Captcha"放入import中,然后通过 go mod tidy或者 go get
github.com/mojocn/base64Captcha 引入
把 var store base64Captcha.Store = RedisStore{}复制进去
//创建store,保存验证码的位置,默认为mem(内存中)单机部署,如果要布置多台服务器,则可以设置保存在redis中
//var store = base64Captcha.DefaultMemStore
//配置RedisStore, 保存验证码的位置为redis, RedisStore实现base64Captcha.Store接口
var store base64Captcha.Store = RedisStore{}
这里使用的是 redis的存储方式,故需要 初始化redis,以及实现 设置 captcha 的方法的代码,故需要在captcha下创建 models/redisCore.go, models/redisStore.go文件,具体参考: [golang gin框架] 12.Gin 商城项目-base64Captcha生成图形验证码以及分布式架构中配置Captcha
redisCore.go代码如下:
package models
//redis官网: github.com/go-redis
//下载go-redis: go get github.com/redis/go-redis/v9
//连接redis数据库核心代码
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
"gopkg.in/ini.v1"
"os"
)
//全局使用,就需要把定义成公有的
var ctxRedis = context.Background()
var (
RedisDb *redis.Client
)
//是否开启redis
var redisEnable bool
//自动初始化数据库
func init() {
//加载配置文件
config, iniErr := ini.Load("./conf/app.ini")
if iniErr != nil {
fmt.Printf("Fail to read file: %v", iniErr)
os.Exit(1)
}
//获取redis配置
ip := config.Section("redis").Key("ip").String()
port := config.Section("redis").Key("port").String()
redisEnable, _ = config.Section("redis").Key("redisEnable").Bool()
//判断是否开启redis
if redisEnable {
RedisDb = redis.NewClient(&redis.Options{
Addr: ip + ":" + port,
Password: "", // no password set
DB: 0, // use default DB
})
//连接redis
_, err := RedisDb.Ping(ctxRedis).Result()
//判断连接是否成功
if err != nil {
println(err)
}
}
}
redisStore.go代码如下:
package models
/**
使用redis需实现Store中的三个方法
type Store interface {
// Set sets the digits for the captcha id.
Set(id string, value string)
// Get returns stored digits for the captcha id. Clear indicates
// whether the captcha must be deleted from the store.
Get(id string, clear bool) string
//Verify captcha's answer directly
Verify(id, answer string, clear bool) bool
}
*/
import (
"context"
"fmt"
"time"
)
var ctx = context.Background()
const CAPTCHA = "captcha:"
type RedisStore struct {
}
//实现设置 captcha 的方法
func (r RedisStore) Set(id string, value string) error {
key := CAPTCHA + id
err := RedisDb.Set(ctx, key, value, time.Minute*2).Err()
return err
}
//实现获取 captcha 的方法
func (r RedisStore) Get(id string, clear bool) string {
key := CAPTCHA + id
//获取 captcha
val, err := RedisDb.Get(ctx, key).Result()
if err != nil {
fmt.Println(err)
return ""
}
//如果clear == true, 则删除
if clear {
err := RedisDb.Del(ctx, key).Err()
if err != nil {
fmt.Println(err)
return ""
}
}
return val
}
//实现验证 captcha 的方法
func (r RedisStore) Verify(id, answer string, clear bool) bool {
v := RedisStore{}.Get(id, clear)
return v == answer
}
参考: [golang gin框架] 9.Gin GORM 中使用事务以及go-ini加载.ini配置文件
把 一.Captcha验证码功能引入中captcha.go 获取验证码方法代码复制到handler/captcha.go的
MakeCaptcha,然后修修改改就可以了,代码如下
//获取验证码的方法
func (e *Captcha) MakeCaptcha(ctx context.Context, req *pb.MakeCaptchaRequest, rsp *pb.MakeCaptchaResponse) error {
//实现业务逻辑代码
//定义一个driver
var driver base64Captcha.Driver
//创建一个字符串类型的验证码驱动DriverString, DriverChinese :中文驱动
driverString := base64Captcha.DriverString{
Height: int(req.Height), //高度
Width: int(req.Width), //宽度
NoiseCount: 0, //干扰数
ShowLineOptions: 2 | 4, //展示个数
Length: int(req.Length), //长度
Source: "1234567890qwertyuioplkjhgfdsazxcvbnm", //验证码随机字符串来源
BgColor: &color.RGBA{ // 背景颜色
R: 3,
G: 102,
B: 214,
A: 125,
},
Fonts: []string{"wqy-microhei.ttc"}, // 字体
}
driver = driverString.ConvertFonts()
//生成验证码
c := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := c.Generate()
//把生成的验证码id,base64编码赋值给返回的rsp参数
rsp.Id = id
rsp.B64S = b64s
return err
}
把 一.Captcha验证码功能引入中captcha.go 校验验证码的方法代码复制到handler/captcha.go的
MakeCaptcha,然后修修改改就可以了,代码如下:
//校验验证码的方法
func (e *Captcha) VerifyCaptcha(ctx context.Context, req *pb.VerifyCaptchaRequest, rsp *pb.VerifyCaptchaResponse) error {
// 参数说明: id 验证码id, verifyValue 验证码的值, true: 验证成功后是否删除原来的验证码
if store.Verify(req.Id, req.VerifyValue, true) {
rsp.VerifyResult = true //校验成功
} else {
rsp.VerifyResult = false //校验失败
}
return nil
}
package handler
import (
"captcha/models"
pb "captcha/proto/captcha"
"context"
"github.com/mojocn/base64Captcha"
"image/color"
)
//创建store,保存验证码的位置,默认为mem(内存中)单机部署,如果要布置多台服务器,则可以设置保存在redis中
//var store = base64Captcha.DefaultMemStore
//配置RedisStore, 保存验证码的位置为redis, RedisStore实现base64Captcha.Store接口
var store base64Captcha.Store = models.RedisStore{}
type Captcha struct{}
//获取验证码的方法
func (e *Captcha) MakeCaptcha(ctx context.Context, req *pb.MakeCaptchaRequest, rsp *pb.MakeCaptchaResponse) error {
//实现业务逻辑代码
//定义一个driver
var driver base64Captcha.Driver
//创建一个字符串类型的验证码驱动DriverString, DriverChinese :中文驱动
driverString := base64Captcha.DriverString{
Height: int(req.Height), //高度
Width: int(req.Width), //宽度
NoiseCount: 0, //干扰数
ShowLineOptions: 2 | 4, //展示个数
Length: int(req.Length), //长度
Source: "1234567890qwertyuioplkjhgfdsazxcvbnm", //验证码随机字符串来源
BgColor: &color.RGBA{ // 背景颜色
R: 3,
G: 102,
B: 214,
A: 125,
},
Fonts: []string{"wqy-microhei.ttc"}, // 字体
}
driver = driverString.ConvertFonts()
//生成验证码
c := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := c.Generate()
//把生成的验证码id,base64编码赋值给返回的rsp参数
rsp.Id = id
rsp.B64S = b64s
return err
}
//校验验证码的方法
func (e *Captcha) VerifyCaptcha(ctx context.Context, req *pb.VerifyCaptchaRequest, rsp *pb.VerifyCaptchaResponse) error {
// 参数说明: id 验证码id, verifyValue 验证码的值, true: 验证成功后是否删除原来的验证码
if store.Verify(req.Id, req.VerifyValue, true) {
rsp.VerifyResult = true //校验成功
} else {
rsp.VerifyResult = false //校验失败
}
return nil
}
captcha目录下运行go run main.go,然后在consul UI 查看,是否注册成功
注册成功了
前面单体架构商城中调用captcha验证码接口代码是通过接口 http://127.0.0.1:8080/admin/captcha这个访问的,具体代码如下:
//验证码
adminRouters.GET("/captcha", admin.LoginController{}.Captcha)
//获取验证码,验证验证码func(con LoginController) Captcha(c *gin.Context) {
id, b64s, err := models.MakeCaptcha(50, 100 ,1)
if err != nil {
fmt.Println(err)
}
c.JSON(http.StatusOK, gin.H{
"captchaId": id,
"captchaImage": b64s,
})
}
上面调用models下 captcha.go中的方法 MakeCaptcha()获取验证码,该captcha.go也就是 一.Captcha验证码功能引入 中captcha.go代码,这是 原来单体架构的做法,访问如下:
现在就要交给 captcha验证码微服务来处理
前面章节对于验证码这块儿, 前端和 后台都需要进行 验证码逻辑处理,调用的方法都是models/captcha.go下面的方法,故在进行微服务客户端处理时,也在这里面进行修改
首先,在models下创建initCaptchaConsul.go,配置consul服务发现,以便调用,代码如下:
package models
//微服务客户端配置: 初始化consul配置,当一个项目中多个微服务时,就很方便了
//建议:一个微服务对应一个客户端,这样好管理
import (
"github.com/go-micro/plugins/v4/registry/consul"
"go-micro.dev/v4/client"
"go-micro.dev/v4/registry"
)
//CaptchaClient: 全局变量 在外部的包中可以调用
var CaptchaClient client.Client
//init 方法: 当程序运行时就会自动执行
func init() {
consulRegistry := consul.NewRegistry(
//指定微服务的ip: 选择注册服务器地址,默认为本机,也可以选择consul集群中的client,建议一个微服务对应一个consul集群的client
registry.Addrs("127.0.0.1:8500"),
)
// Create service
srv := micro.NewService(
micro.Registry(consulRegistry),
)
srv.Init()
CaptchaClient = srv.Client()
}
在这里,也许没有引入,执行命令:go mod tidy引入对应的包
在该方法中实现调用获取验证码微服务逻辑功能
//调用获取验证码微服务
func MakeCaptcha(height int, width int, length int) (string, string, error) {
// Create client: 这里的服务名称需要和服务端注册的名称一致
captchaClient := pbCaptcha.NewCaptchaService("captcha", CaptchaClient)
// Call service: 创建连接captcha微服务的连接,并传递参数,
//该方法最终是请求server端handler中的captcha.go中的MakeCaptcha方法
rsp, err := captchaClient.MakeCaptcha(context.Background(), &pbCaptcha.MakeCaptchaRequest{
Height: int32(height), //验证码高度
Width: int32(width), //验证码宽度
Length: int32(length), //验证码长度
})
//判断是否获取成功
if err != nil {
log.Fatal(err)
}
//记录log
log.Info(rsp)
//返回
return rsp.Id, rsp.B64S, err
}
在该方法中实现调用校验验证码微服务逻辑功能
//调用校验验证码微服务
func VerifyCaptcha(id string, VerifyValue string) bool {
// Create client: 这里的服务名称需要和服务端注册的名称一致
captchaClient := pbCaptcha.NewCaptchaService("captcha", CaptchaClient)
// Call service: 创建连接captcha微服务的连接,并传递参数,
//该方法最终是请求server端handler中的captcha.go中的VerifyCaptcha方法
rsp, err := captchaClient.VerifyCaptcha(context.Background(), &pbCaptcha.VerifyCaptchaRequest{
Id: id, //验证码Id
VerifyValue: VerifyValue, //验证码
})
//判断是否获取成功
if err != nil {
log.Fatal(err)
}
//记录log
log.Info(rsp)
//返回
return rsp.VerifyResult
}
package models
//验证码属性: https://captcha.mojotv.cn/
import (
"context"
"github.com/prometheus/common/log"
pbCaptcha "goshop/proto/captcha"
)
//调用获取验证码微服务
func MakeCaptcha(height int, width int, length int) (string, string, error) {
// Create client: 这里的服务名称需要和服务端注册的名称一致
captchaClient := pbCaptcha.NewCaptchaService("captcha", CaptchaClient)
// Call service: 创建连接captcha微服务的连接,并传递参数,
//该方法最终是请求server端handler中的captcha.go中的MakeCaptcha方法
rsp, err := captchaClient.MakeCaptcha(context.Background(), &pbCaptcha.MakeCaptchaRequest{
Height: int32(height), //验证码高度
Width: int32(width), //验证码宽度
Length: int32(length), //验证码长度
})
//判断是否获取成功
if err != nil {
log.Fatal(err)
}
//记录log
log.Info(rsp)
//返回
return rsp.Id, rsp.B64S, err
}
//调用校验验证码微服务
func VerifyCaptcha(id string, VerifyValue string) bool {
// Create client: 这里的服务名称需要和服务端注册的名称一致
captchaClient := pbCaptcha.NewCaptchaService("captcha", CaptchaClient)
// Call service: 创建连接captcha微服务的连接,并传递参数,
//该方法最终是请求server端handler中的captcha.go中的VerifyCaptcha方法
rsp, err := captchaClient.VerifyCaptcha(context.Background(), &pbCaptcha.VerifyCaptchaRequest{
Id: id, //验证码Id
VerifyValue: VerifyValue, //验证码
})
//判断是否获取成功
if err != nil {
log.Fatal(err)
}
//记录log
log.Info(rsp)
//返回
return rsp.VerifyResult
}
见前面代码
在项目根目录下运行 :go run main.go,启动项目
访问 http://127.0.0.1:8080/admin/captcha看看是否显示验证码相关数据
显示了,说明调用了验证码微服务操作
访问后台登录页面,输入用户名,密码,验证码,看看是否成功
好了,captcha验证码微服务客户端操作完成,在这里,上面讲解的是web页面调用captcha验证码微服务功能,下面则讲解Go Web Restfull APi 调用Captcha验证码微服务
Go Web Restfull APi 调用Captcha验证码微服务主要是给手机app,微信小程序等提供接口,架构如下
这里直接以上面项目为案例,在routers下创建 apiRouters.go路由文件
在controllers/api/ CaptchaController.go下编写获取验证码,校验验证码相关逻辑,代码如下:
package api
import (
"context"
"github.com/gin-gonic/gin"
"github.com/prometheus/common/log"
"goshop/models"
pbCaptcha "goshop/proto/captcha"
"net/http"
)
type CatpchaController struct {
}
//获取验证码的接口(调用验证码微服务操作)
func (con CatpchaController) MakeCaptcha(c *gin.Context) {
// Create client: 这里的服务名称需要和服务端注册的名称一致
captchaClient := pbCaptcha.NewCaptchaService("captcha", models.CaptchaClient)
// Call service: 创建连接captcha微服务的连接,并传递参数,
//该方法最终是请求server端handler中的captcha.go中的MakeCaptcha方法
rsp, err := captchaClient.MakeCaptcha(context.Background(), &pbCaptcha.MakeCaptchaRequest{
Height: 100, //验证码高度
Width: 200, //验证码宽度
Length: 4, //验证码长度
})
//判断是否获取成功
if err != nil {
log.Fatal(err)
}
//记录log
log.Info(rsp)
//返回
c.JSON(http.StatusOK, gin.H{
"captchaId": rsp.Id,
"B64s": rsp.B64S,
})
}
//校验验证码接口
func (con CatpchaController) VerifyCaptcha(c *gin.Context) {
//获取请求参数
verifyId := c.PostForm("verifyId")
verifyValue := c.PostForm("verifyValue")
// Create client: 这里的服务名称需要和服务端注册的名称一致
captchaClient := pbCaptcha.NewCaptchaService("captcha", models.CaptchaClient)
// Call service: 创建连接captcha微服务的连接,并传递参数,
//该方法最终是请求server端handler中的captcha.go中的VerifyCaptcha方法
rsp, err := captchaClient.VerifyCaptcha(context.Background(), &pbCaptcha.VerifyCaptchaRequest{
Id: verifyId, //验证码Id
VerifyValue: verifyValue, //验证码
})
//判断是否获取成功
if err != nil {
log.Fatal(err)
}
//记录log
log.Info(rsp)
//返回
if rsp.VerifyResult == true { // 说明验证通过
c.JSON(http.StatusOK, gin.H{
"message": "验证验证码成功",
"success": true,
})
} else {
c.JSON(http.StatusOK, gin.H{
"message": "验证验证码失败",
"success": false,
})
}
}
请求http://127.0.0.1:8080/api/MakeCaptcha,看看是否返回对应的验证码json请求
从上图看得出来,返回了对应验证码的数据的,把 B64s中的数据放入<img src="B64s" />中,就可以了,展示的图片如下:
然后校验验证码,一般通过postman校验
好了,Go Web Restfull APi 调用Captcha验证码微服务 获取验证码,以及校验验证码api接口操作就完成了
[上一节][golang gin框架] 39.Gin商城项目-微服务实战之微服务架构
[下一节][golang gin框架] 41.Gin商城项目-微服务实战之后台Rbac微服务(用户登录 、Gorm数据库配置单独抽离、 Consul配置单独抽离)
文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态
文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境
文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn
文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker
文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机
文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk
文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入
文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。 Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。
文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动
文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计
文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;gt;Jni-&amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图
文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法