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

移植FlashDB、SFUD到STM32f407

个人上篇文章  搭建STM32F407的SPI-Flash(基于STM32CubeMX)_小刚学長的博客-CSDN博客

主要是解决STM32CubeMX这边的配置,对code端侧是简单介绍了下

实际项目上一般都是拿片外flash存储一些东西,比如一些比较多的配置、参数,偶尔修改下,还有一些程序文件,日志之类的。存在读写操作,而nor flash是每次擦除后才可以写入(也就是说你要更新内容,也是要先擦除再写入新的数据),往往这种操作比较麻烦(最近简单的方法,先把当簇内容读出来,然后对相应的位置进行修改,然后先擦除当前簇,再写入),如果更新内容存在跨簇,那更麻烦点,需要判断。另外,还有个特点,nor flash存在擦除次数上限,如果超过一定次数,此区域容易坏。

对于windows、linux,存在文件系统,文件系统就可以很好规避以上问题,使用时也不用去关心、去计算这些值。对于STM32显然文件系统开销很大,不太合适

那么STM32有没有轻量点库之类的,答案是有的:

FlashDB + SFUD + SPI Flash 

FlashDB就是个简单版本的DB,也是专门适合MCU环境,而且针对Flash特点,对相同簇写入次数也有优化(写入均衡)。FlashDB 支持kv类型数据库、也支持时间序列数据库,一般也足够用了。关键还是占资源少,写flash均衡,这样应用者可更关注逻辑部分。是个好东西,记得早些年,都是自己造轮子的,又无法证明自己造轮子是可靠的,因此经常被吊。

当然,FlashDB 不仅仅是 通过SFUD去访问SPI Flash,也可以通过自己封装的SPI FLASH驱动代码去访问,也支持文件系统(文件方式)去访问外部flash。但经典组合,还是 

由于芯片本身不同,这里芯片不仅仅是FLASH芯片,还包括MCU,因此要实现自己的代码,需要做相应的改进(调整),以下的方案是基于STM32F407芯片,具体硬件配置,参考上篇

1. 把相关代码复制到工程里面:(包括对应 h文件)

  

2. fal_cfg.h  fal 配置

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_#include "main.h"#define FAL_DEBUG 1
#define FAL_PART_HAS_TABLE_CFG
#define FAL_USING_SFUD_PORT/* ===================== Flash device Configuration ========================= */
extern struct fal_flash_dev nor_flash0;/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \&nor_flash0,                                                     \  //nor flash 基本信息以及读写擦除接口等。是fal_flash_sfud_port.c 有描述,也是需要初始化的对象
}/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                                 \
{                                                                                      \{FAL_PART_MAGIC_WROD,  "fdb_kvdb1",       "norflash0",           0, 1024*1024, 0}, \
/* 1M(FLASH 地址0~1M) 大小的table, 这里只是一张表,根据实际情况配置*/
}
#endif /* FAL_PART_HAS_TABLE_CFG */#endif /* _FAL_CFG_H_ */

3. fal_flash_sfud_port.c 修改,印象中只修改过 init 

#ifndef FAL_USING_NOR_FLASH_DEV_NAME
#define FAL_USING_NOR_FLASH_DEV_NAME             "norflash0"
#endifstatic int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);static sfud_flash_t sfud_dev = NULL;
struct fal_flash_dev nor_flash0 =
{.name       = FAL_USING_NOR_FLASH_DEV_NAME,.addr       = 0,.len        = 1024 * 1024,.blk_size   = 4096,.ops        = {init, read, write, erase},.write_gran = 1
};static int init(void)
{#ifdef RT_USING_SFUD/* RT-Thread RTOS platform */sfud_dev = rt_sfud_flash_find_by_dev_name(FAL_USING_NOR_FLASH_DEV_NAME);
#else/* bare metal platform */extern sfud_flash flash_table[1];  // 这里table实际上是 指 SFUD_FLASH_DEVICE_TABLEsfud_dev = &flash_table[0];  // sfud_dev 指向 table[0] 这个非常重要
#endifif (NULL == sfud_dev){return -1;}/* update the flash chip information */nor_flash0.blk_size = sfud_dev->chip.erase_gran;nor_flash0.len = sfud_dev->chip.capacity;return 0;
}static int read(long offset, uint8_t *buf, size_t size)
{assert(sfud_dev);assert(sfud_dev->init_ok);sfud_read(sfud_dev, nor_flash0.addr + offset, size, buf);return size;
}static int write(long offset, const uint8_t *buf, size_t size)
{assert(sfud_dev);assert(sfud_dev->init_ok);if (sfud_write(sfud_dev, nor_flash0.addr + offset, size, buf) != SFUD_SUCCESS){return -1;}return size;
}static int erase(long offset, size_t size)
{assert(sfud_dev);assert(sfud_dev->init_ok);if (sfud_erase(sfud_dev, nor_flash0.addr + offset, size) != SFUD_SUCCESS){return -1;}return size;
}

4. sfud_cfg.h 配置 SFUD_FLASH_DEVICE_TABLE


#ifndef _SFUD_CFG_H_
#define _SFUD_CFG_H_#define SFUD_DEBUG_MODE#define SFUD_USING_SFDP#define SFUD_USING_FLASH_INFO_TABLEenum {SFUD_W25Q128_DEVICE_INDEX = 0,   // 如果多个,往下加,名字自己取,但要跟其他对应好
};// 上下要对应好
#define SFUD_FLASH_DEVICE_TABLE                                                \
{                                                                              \[SFUD_W25Q128_DEVICE_INDEX] = {.name = "W25Q128B", .spi.name = "SPI1"},       \
}#endif /* _SFUD_CFG_H_ */

5. sfud_port.c 修改,就是要实现 对接SPI接口

    要做:

     SPI相关配置:是通过HAL访问SPI,还是其他?片选信号对应GPIO信息

     SPI延时函数、锁、解锁等

     SPI 读写接口封装

#include "spi.h"typedef struct {SPI_HandleTypeDef *spix;GPIO_TypeDef *cs_gpiox;uint32_t cs_gpio_pin;
} spi_user_data, *spi_user_data_t;void sfud_log_debug(const char *file, const long line, const char *format, ...);static void spi_configuration(spi_user_data_t spi) {}static void spi_lock(const sfud_spi *spi) {__disable_irq();
}static void spi_unlock(const sfud_spi *spi) {__enable_irq();
}/*** 这个函数要重新写*/
static sfud_err spi_write_read(const sfud_spi *spi, uint8_t *write_buf, size_t write_size, uint8_t *read_buf,size_t read_size) {sfud_err result = SFUD_SUCCESS;spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;uint16_t blockSize = 0;uint32_t offset = 0;if (write_size) {SFUD_ASSERT(write_buf);}if (read_size) {SFUD_ASSERT(read_buf);}// HAL - 片选拉低HAL_GPIO_WritePin(spi_dev->cs_gpiox,spi_dev->cs_gpio_pin,GPIO_PIN_RESET); if (write_size){if (HAL_SPI_Transmit(spi_dev->spix, write_buf, write_size, 100) != HAL_OK){result = SFUD_ERR_WRITE;goto exit;}}while (read_size){blockSize = read_size > 0xFFFF ? 0xFFFF : read_size;read_size -= blockSize;if (HAL_SPI_Receive(spi_dev->spix, read_buf + offset, blockSize, 100) != HAL_OK){result = SFUD_ERR_READ;goto exit;}offset += blockSize;}exit:
// HAL - 片选拉高HAL_GPIO_WritePin(spi_dev->cs_gpiox,spi_dev->cs_gpio_pin,GPIO_PIN_SET);return result;
}/* about 100 microsecond delay */
static void retry_delay_100us(void) {DWT_Delay(100); // 这里要自己去实现一个,主要是100微秒,不是100ms
}// spi 关键信息配置,对应spi多少,片选多少
static spi_user_data spi1 = { .spix = &hspi1, .cs_gpiox = SPI_FLASH_CS_GPIO_Port, .cs_gpio_pin = SPI_FLASH_CS_Pin };
sfud_err sfud_spi_port_init(sfud_flash *flash) {sfud_err result = SFUD_SUCCESS;switch (flash->index) {case SFUD_W25Q128_DEVICE_INDEX: {/* SPI 外设初始化 */spi_configuration(&spi1);/* 同步 Flash 移植所需的接口及数据 */flash->spi.wr = spi_write_read;flash->spi.lock = spi_lock;flash->spi.unlock = spi_unlock;flash->spi.user_data = &spi1;/* about 100 microsecond delay */flash->retry.delay = retry_delay_100us;/* about 60 seconds timeout */flash->retry.times = 60 * 10000;break;}}return result;
}/*** This function is print debug info.** @param file the file which has call this function* @param line the line number which has call this function* @param format output format* @param ... args*/
void sfud_log_debug(const char *file, const long line, const char *format, ...) {va_list args;printf("[%s,%d] ", file, line);va_start(args, format);printf(format, args);va_end(args);printf("\n");
}/*** This function is print routine info.** @param format output format* @param ... args*/
void sfud_log_info(const char *format, ...) {va_list args;va_start(args, format);printf(format, args);va_end(args);printf("\n");
}

以上信息,一般网上例子就最多那么多,实际还有两个关键:

1. printf 要重定向,还不能用Micro LIB的方式

在usart.c 添加如下代码,并不要勾选Micro LIB!!

/* USER CODE BEGIN 1 */
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */#if 1
#if (__ARMCC_VERSION >= 6010050)                    /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");          /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");            /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)struct __FILE
{int handle;/* Whatever you require here. If the only file you are using is *//* standard output using printf() for debugging, no file handling *//* is required. */
};#endif/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{ch = ch;return ch;
}/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{x = x;
}char *_sys_command_string(char *cmd, int len)
{return NULL;
}/* FILE 在 stdio.h里面定义. */
FILE __stdout;/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{while ((USART1->SR & 0X40) == 0);               /* 等待上一个字符发送完成 */USART1->DR = (uint8_t)ch;                       /* 将要发送的字符 ch 写入到DR寄存器 */	return ch;
}
#endif/* USER CODE END 1 */

2. 增加芯片信息    SFUD_FLASH_CHIP_TABLE   最后一个就是我的芯片信息!!如果没有,需要手动添加,注意 "W25Q128B" 的name 关键字,这个也不是随便取的,要注意与前面的对应!!

#define SFUD_FLASH_CHIP_TABLE                                                                                    \
{                                                                                                                \{"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2*1024*1024, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81},      \{"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512*1024, SFUD_WM_PAGE_256B, 4096, 0x20},                       \{"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2*1024*1024, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \{"M25P32", SFUD_MF_ID_MICRON, 0x20, 0x16, 4*1024*1024, SFUD_WM_PAGE_256B, 64*1024, 0xD8},                    \{"EN25Q32B", SFUD_MF_ID_EON, 0x30, 0x16, 4*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20},                        \{"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20},                 \{"S25FL216K", SFUD_MF_ID_CYPRESS, 0x40, 0x15, 2*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20},                   \{"A25L080", SFUD_MF_ID_AMIC, 0x30, 0x14, 1*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20},                        \{"F25L004", SFUD_MF_ID_ESMT, 0x20, 0x13, 512*1024, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},                    \{"PCT25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2*1024*1024, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \{"W25Q128B", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20},                   \
}

这样应该可以了。我记得就这么多!

相关文章:

移植FlashDB、SFUD到STM32f407

个人上篇文章 搭建STM32F407的SPI-Flash(基于STM32CubeMX)_小刚学長的博客-CSDN博客 主要是解决STM32CubeMX这边的配置,对code端侧是简单介绍了下 实际项目上一般都是拿片外flash存储一些东西,比如一些比较多的配置、参数&…...

【算法基础】时间复杂度和空间复杂度

目录 1 算法的评价 2 算法复杂度 2.1 时间复杂度(Time Complexity) 2.1.1 如何计算时间复杂度: 2.1.2 常见的时间复杂度类别与示例 2.2 空间复杂度 2.2.1 如何计算空间复杂度 2.2.2 常见的空间复杂度与示例 3 时间复杂度和空间复杂度…...

解决微信小程序不支持TextEncoder/TextDecoder对象

问题描述:在使用小程序开发者工具开发小程序中使用到了CRC算法,其中有一行代码使用到了TextEncoder对象,在开发工具中一切正常,到手机上会报出错误错误如下: MiniProgramError TextEncoder is not defined ReferenceEr…...

Qt下SVG格式图片应用

SVG格式图片介绍 svg格式图片又称矢量图,该种格式的图片不同于png等格式的图片,采用的并不是位图的形式来组织图片,而是采用线条等组织图片,svg格式是图片的文件格式是xml,可以通过文件编译器打开查看svg格式内容。 …...

python异常处理

参考语法:https://docs.python.org/zh-cn/3/tutorial/errors.html 在编写代码的时候,如果你写的程序出现报错,程序就会停止运行,后面的代码就不再执行。 如果程序发生错误,可以在代码中添加异常处理,保证程…...

go get命令不再具有安装功能

go get功能呢 一直以来,我们知道go get命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装。整个过程就像安装一个App一样简单。 go get命令可以动态获取远程代码包,命令在内部实际上分成了两步操作&#x…...

合宙Air724UG LuatOS-Air lvgl7-lvgl(矢量字体)

如何用开发板实现lvgl加载外部矢量字体功能 目录名称 如何用开发板实现lvgl加载外部矢量字体功能 简介材料准备API 说明步骤 1. 将字库芯片接在模块spi上2. 版本定制3. 初始化spi4. 设置字体5.字体使用测试固件和脚本显示效果字号灰度最佳粗细值对应表常见问题 1. 设置68号字体…...

LRU的实现

题目内容 实现一个 LRUCache 类,三个接口: LRUCache(int capacity) 创建一个大小为 capacity 的缓存get(int key) 从缓存中获取键为 key 的键值对的 valueput(int key, int value) 向缓存中添加键值对 (key, value) 要求 get 和 put 的均摊时间复杂度…...

consul 备份还原导入导出

正文 工作中要保证生产环境部署的consul的集群能够安全稳定地对外提供服务,即使出现系统故障也能快速恢复,这里将讲述部分的备份还原操作及KV的导入导出操作。 备份与还原 配置文件、服务器状态 需要备份的主要有两类数据:consul相关的配置文…...

6.网络编程套接字(下)

文章目录 4.TCP流套接字编程4.1ServerSocket API4.2Socket API4.3TCP中的长短连接4.4示例一:一发一收(长连接)4.4.1TCP服务端4.4.2TCP客户端 4.5示例二:请求响应(短连接)4.5.1TCP服务端4.5.2TCP客户端 4.6再…...

4.3-内置后置PostProcess处理器深度讲解

在reader里面注册了很多Bean定义 reader会调取register()来注册配置类 调用上句,就会把配置类注册到BeanDefinitionMap中去 配置类有了、解析配置类的处理器有了 然后, 在第三步refresh() 进行IOC容器刷新中的invokeBeanPostProcessors(beanFactory…...

LeetCode(力扣)45. 跳跃游戏 IIPython

LeetCode45. 跳跃游戏 II 题目链接代码 题目链接 https://leetcode.cn/problems/jump-game-ii/description/ 代码 class Solution:def jump(self, nums: List[int]) -> int:if len(nums) 1:return 0curdis 0nextdis 0step 0for i in range(len(nums)):nextdis max(…...

mysql5.8 免安装版(压缩包)win10 安装

目录 1、下载MySQL5.82、如何安装、配置my.ini配置注意 3初始化mysql3.1. 初始化mysql3.2. 安装mysql服务3.3. 启动mysql3.4. 登录mysql3.5. 修改root密码3.6. 配置远程连接 Mysql5.8安装踩坑记录,推荐使用Docker安装,我是电脑虚拟化可能会蓝屏没用这个功…...

STM32-HAL库06-硬件IIC驱动FM24CL16B非易失存储器

STM32-HAL库06-IIC驱动FM24CL16B非易失存储器 一、所用材料: STM32VGT6自制控制板 STM32CUBEMX(HAL库软件) MDK5 二、所学内容: 通过HAL库的硬件IIC对FM24CL16B存储器进行写与读取操作。 三、CUBEMX配置: 第一步…...

python-wordcloud词云

导入模块 from wordcloud import WordCloud import jieba import imageio import matplotlib.pyplot as plt from PIL import ImageGrab import numpy as npwordcloud以空格为分隔符号,来将文本分隔成单词 PIL pillow模块 img imageio.imread(image.png)这行代码…...

单元测试与自测

单元测试在百度百科的定义: 自测在百度百科的定义: 单元测试是测一个类或一个函数,自立门第main函数,不依赖于项目,预期的是这个类或函数是没有问题的。程序编码完成之后至各种测试再到用户使用出现的任何bug都是单元测…...

2023-09-12 LeetCode每日一题(课程表 IV)

2023-03-29每日一题 一、题目编号 1462. 课程表 IV二、题目链接 点击跳转到题目位置 三、题目描述 你总共需要上 numCourses 门课,课程编号依次为 0 到 numCourses-1 。你会得到一个数组 prerequisite ,其中 prerequisites[i] [ai, bi] 表示如果你…...

RabbitMQ基础

目录 MQ MQ概述 MQ 的优势 1.应用解耦 2.异步提速 3.削峰填谷 MQ 的劣势 1.系统可用性降低 2.系统复杂度提高 3.一致性问题 使用 MQ 需要满足什么条件呢? RabbitMQ 简介 ​编辑RabbitMQ 中的相关概念 RabbitMQ 提供了 6 种工作模式 JMS java实现Ra…...

ITIL 4—创建、交付和支持—创建、交付和支持服务的价值流

4. 创建、交付和支持服务的价值流 本章节提供了有关如何: 记录一个价值流以理解工作流程如何贯穿该组织了解创建一个新服务的原型价值流了解支持一个现场服务的原型价值流 本章将帮助从业者理解: 价值流在 服务价值系统(SVS) 中的作用价值流的分类如…...

微信怎么给自己发消息

前段时间看到一份数据调查,说是到目前为止,全球使用微信的用户已达到10亿多人次,天啊,多么强大的用户群体! 这么多人喜欢使用微信,相信大家都知道,微信里面有一个特俗功能,可以自己…...

正交试验设计法

正交实验设计 一、什么是正交试验设计法? 是一种成对测试交互的系统的统计方法。它提供了一种能对所有变量对的组合进行典型覆盖(均匀分布)的方法。 可以从大量的试验点中挑出适量的、有代表性的点,利用“正交表”,…...

Scrum工具:助力快速迭代和高效交付

​随着软件开发行业的不断发展,敏捷开发方法逐渐成为了主流。Scrum作为敏捷开发中最具代表性的工具之一,其在流程设计、团队协作以及项目管理等方面发挥着重要作用。本文将深入探讨Scrum的优势以及如何运用Scrum提升团队效率与质量。 一、Scrum敏捷开发工…...

通过Python行命令搭建HTTP服务器结合内网穿透实现外网访问

文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Python作为热度比较高的编程语言,其语法简单且语句清晰,而且python有…...

Android T 窗口层级其三 —— 层级结构树添加窗口

文章目录 序节点添加Task以DefaultTaskDisplayArea为父节点以Task为父节点 ActivityRecordWindowTokenWindowState以WindowToken为父节点以ActivityRecord为父节点 小结调用场景添加差异 流程分析添加log堆栈打印流程LauncherStatusBar 序 尚未添加窗口的层级结构树&#xff0…...

3D虚拟数字人定制,推动传统文化传播新高度

“数字人”成为“汉语盘点2022”年度十大新词语。伴随着科技发展成长的年轻人逐渐成为消费主力军,如何在虚拟世界与年轻一代用户互动以抓住95后年轻人受众,成为不少传统文化品牌发力的重点。 数字人“天妤”,在3D虚拟数字人定制中&#xff0…...

kubernetes进阶 (三) 基础练习

前两天朋友给了我几道题,看着挺简单的,但实际做的时候发现坑不少,这里做下笔记 一、镜像构建部署lnmp 1、构建镜像 nginx、php、mysql 要求使用centos7作为基础镜像 2、使用deployment部署上面的容器,要求3个服务要放到一个pod中(虽然这样是…...

数据结构 排序

目录 第八章 排序8.1排序的基本概念1. 概念2. 排序算法的分类 8.2 插入排序8.2.1 直接插入排序8.2.2 算法效率分析8.2.2 折半插入排序总结8.2.3 希尔排序 8.3 交换排序8.3.1冒泡排序8.3.2快速排序(了解栈的过程) 8.4 选择排序8.4.1 简单选择排序8.4.2 堆…...

Cpp/Qtday050912cpp基础

目录 实现一个图形类(Shape),包含受保护成员属性:周长、面积, 公共成员函数:特殊成员函数书写 定义一个圆形类(Circle),继承自图形类,包含私有属性&#x…...

Git diff 使用 vimdiff 对比差异

在Ubuntu中使用Git时,可使用命令行的git diff命令来对比两次提交的差异,但是这种对比查看方式无法直观地查看修改的差异,在对比和查看时不太方便。 可以使用vimdiff作为Git diff的对比工具,这样就方便了许多,Git的配置…...

c小白勇闯结构体!!!!

目录 1.结构体类型的声明 1.结构的基础 2.结构体的声明 3.结构体成员的类型 4结构体变量的定义和初始化 2.结构体成员的访问 3.结构体传参 1.结构体类型的声明 1.结构的基础 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量 结构体变量的创…...

怎么做网站用于推广/千锋教育培训机构就业率

关于C语言如何有效正确的学习,我写了一个专栏:你可以这样学习C语言,有兴趣的小伙伴可以来看看哦,希望能对你有收获!需要本文源代码的可以关注我后私信我!阅读本文之前,请先阅读:C语言…...

问鼎电子娱乐下载官方网站/seo百度推广

SDOUG简介 SDOUG会员项目(SDOUG MEMBERSHIP PROGRAM),又称为Oracle山东用户组,简称SDOUG,是由葛云杰、杨云龙、类延良等共同发起,旨在认可和表彰那些在SDOUG技术社区有贡献的人士。这些人的技术娴熟并且乐于分享他们的知识和经验。Oracle…...

服装网站模块方案/广州seo优化公司

随便指定一个目录,判断它是否是一个合法的JDK目录(by quqi99) 作者:张华 发表于:2006-11-01 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明。 http://blog.csdn.net/quqi99…...

自己如何做独立网站/免费推广app软件下载

不经过Postmaster以单用户模式直接启动,为单一用户提供服务,这种方式由–single选项启动。在这种模式下,Postgres服务器进程必须自己完成初始化内存环境、配置参数等操作。 /* Initialize startup process environment if necessary. */if (!…...

网站管理建设落实报告/社群营销方案

初次阅读《平凡的世界》实在中考完的那个暑假,高中推荐我们阅读这本书。记得刚刚拿到这本书时,就被它的大块头吓到了,只是觉得太厚了,从来没有阅读过这么厚的书。书一开篇便是描述孙少平打饭的情景,描写了天气的恶劣以…...

张槎网站建设/百度关键词排名优化

作者:jason cnblogs.com/baizhanshi/p/7211802.html 之前栈长分享了重入锁的概念:《到底什么是重入锁,拜托,一次搞清楚!》,今天现来深入了解下 Synchronized 与 ReentrantLock 的区别! 可重入性…...