app开发专业公司/seo全称
本例主要讲一下,用VC6如何生成DLL,用工具WinHex取得DLL全部内容,VC2015项目加载内存中的DLL函数,并调用函数的示例。
本例中的示例代码下载,点击可以下载
一、VC++6.0生成示例DLL项目
1.新建项目,这里选择Win32 Dynamic-link Library,如下图:
2.选择“A simple DLL project”,然后点击完成,如下:
3.生成示例项目后,如下图:
4.添加自己的示例函数,这里以简单的求和函数为例:
/*
程序功能:DLL生成项目,生成测试的DLL文件,
作者:依星
QQ:34596561,312337667
日期:2023/8/15
*/
#include "stdafx.h"extern "C" __declspec(dllexport) int sum(int a,int b);BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{return TRUE;
}extern "C" __declspec(dllexport) int sum(int a,int b)
{return a+b;
}
5.设置项目为release,开始编译构建DLL文件,按“F7”。
二、用WinHex复制取得DLL文件的全部数据
这里使用WinHex来取得DLL的全部数据,具体使用流程如下:
1.打开WinHex,然后将DLL文件拖入到主界面中,如下图:
2.选择“编辑”---“复制所有”---“C源码”,这里实际是复制了所有的数据,如下图:
3.新建一个记事本,命名为“dll.h” ,将上面复制的数据粘贴到记事本中,然后将此文件复制到VC2015项目中。
三、建立VC2015示例工程,调用CMemLoadDll类源码
1. 这里先用VC2015建立一个标准的MFC工程项目,新建---项目,如下:
2. 选择MFC--MFC应用程序,然后选择保存的目录,并命名项目名称,如下图:
3.下一步,然后再选择“基于对话框”,点击“在静态库中使用MFC”,如下图:
4.至此没有特别要设置的了,点击下一步,直到完成。
5.项目创建后,默认为Unicode字符集,这里改为多字节;(PS:其实改不改都行,主要是项目中都是使用的多字节,习惯了)如下图:
6.将上一步生成的Dll.h文件添加到解决方案的头文件中,然后再新建一个头文件和源文件,用于把网上的CMemLoadDll类源码复制过来,源码将在后面贴出来,咱们先说流程。添加好之后,如下图工程目录:
7.在主对话框中,加一个按钮,用于调用示例:
8.双击按钮,显示点击方法(MemRunDllDlg.cpp):
/*
调用CMemLoadDll,
加载内存中的DLL,
并运行DLL中的函数
//
dllData:为生成的测试DLL数据文件dll.h;(注:此处也可以把这个DLL文件加到资源中加载,或者以文件形式读取到内存中,都是可以的)
为安全起见,可以把DLL的数据加密存储到DLL.H中,本例不再展示。
*/
void CMemRunDllDlg::OnBnClickedButton1()
{// TODO: 在此添加控件通知处理程序代码CMemLoadDll *pMemLoadDll = new CMemLoadDll();if (!pMemLoadDll->MemLoadLibrary(&dllData, sizeof(dllData))) //加载dll到当前进程的地址空间{AfxMessageBox("Load DLL error!");return ;}addNumberProc addNumber = (addNumberProc)pMemLoadDll->MemGetProcAddress("sum");if (addNumber == NULL){AfxMessageBox("Find Add function failed!");return ;}int c = addNumber(1, 2);char itc[10];sprintf(itc, "%d", c);AfxMessageBox(itc);}
9 .在此文件头部(MemRunDllDlg.cpp),加入文件引用及DLL函数声明,如下:
#include "dll.h"
#include "MemLoadDll.h"typedef int(*addNumberProc)(int, int);
10.生成EXE并运行,正常运行,如下:
四、CMemLoadDll类源码,网上搜索的,作者不详
1.MemLoadDll.h头文件
#pragma once typedef BOOL(__stdcall *ProcDllMain)(HINSTANCE, DWORD, LPVOID);class CMemLoadDll
{
public:CMemLoadDll();~CMemLoadDll();BOOL MemLoadLibrary(void *lpFileData, int DataLength); // Dll file data buffer FARPROC MemGetProcAddress(LPCSTR lpProcName);
private:BOOL isLoadOk;BOOL CheckDataValide(void *lpFileData, int DataLength);int CalcTotalImageSize();void CopyDllDatas(void *pDest, void *pSrc);BOOL FillRavAddress(void *pBase);void DoRelocation(void *pNewBase);int GetAlignedSize(int Origin, int Alignment);
private:ProcDllMain pDllMain;private:DWORD pImageBase;PIMAGE_DOS_HEADER pDosHeader;PIMAGE_NT_HEADERS pNTHeader;PIMAGE_SECTION_HEADER pSectionHeader;};
2.MemLoadDll.cpp源文件
#include "stdafx.h"
#include <windows.h>
#include <assert.h>
#include "MemLoadDll.h" CMemLoadDll::CMemLoadDll()
{isLoadOk = FALSE;pImageBase = NULL;pDllMain = NULL;
}CMemLoadDll::~CMemLoadDll()
{if (isLoadOk){assert(pImageBase != NULL);assert(pDllMain != NULL);//脱钩,准备卸载dll pDllMain((HINSTANCE)pImageBase, DLL_PROCESS_DETACH, 0);VirtualFree((LPVOID)pImageBase, 0, MEM_RELEASE);}
}//MemLoadLibrary函数从内存缓冲区数据中加载一个dll到当前进程的地址空间,缺省位置0x10000000
//返回值: 成功返回TRUE , 失败返回FALSE
//lpFileData: 存放dll文件数据的缓冲区
//DataLength: 缓冲区中数据的总长度
BOOL CMemLoadDll::MemLoadLibrary(void *lpFileData, int DataLength)
{if (pImageBase != NULL){return FALSE; //已经加载一个dll,还没有释放,不能加载新的dll }//检查数据有效性,并初始化 if (!CheckDataValide(lpFileData, DataLength)){return FALSE;}//计算所需的加载空间 int ImageSize = CalcTotalImageSize();if (ImageSize == 0){return FALSE;}// 分配虚拟内存 void *pMemoryAddress = VirtualAlloc((LPVOID)NULL, ImageSize,MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (pMemoryAddress == NULL){return FALSE;}else{CopyDllDatas(pMemoryAddress, lpFileData); //复制dll数据,并对齐每个段 //重定位信息 if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress > 0&& pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0){DoRelocation(pMemoryAddress);}//填充引入地址表 if (!FillRavAddress(pMemoryAddress)) //修正引入地址表失败 {VirtualFree(pMemoryAddress, 0, MEM_RELEASE);return FALSE;}//修改页属性。应该根据每个页的属性单独设置其对应内存页的属性。这里简化一下。 //统一设置成一个属性PAGE_EXECUTE_READWRITE unsigned long old;VirtualProtect(pMemoryAddress, ImageSize, PAGE_EXECUTE_READWRITE, &old);}//修正基地址 pNTHeader->OptionalHeader.ImageBase = (DWORD)pMemoryAddress;//接下来要调用一下dll的入口函数,做初始化工作。 pDllMain = (ProcDllMain)(pNTHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)pMemoryAddress);BOOL InitResult = pDllMain((HINSTANCE)pMemoryAddress, DLL_PROCESS_ATTACH, 0);if (!InitResult) //初始化失败 {pDllMain((HINSTANCE)pMemoryAddress, DLL_PROCESS_DETACH, 0);VirtualFree(pMemoryAddress, 0, MEM_RELEASE);pDllMain = NULL;return FALSE;}isLoadOk = TRUE;pImageBase = (DWORD)pMemoryAddress;return TRUE;
}//MemGetProcAddress函数从dll中获取指定函数的地址
//返回值: 成功返回函数地址 , 失败返回NULL
//lpProcName: 要查找函数的名字或者序号
FARPROC CMemLoadDll::MemGetProcAddress(LPCSTR lpProcName)
{if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0 ||pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0){return NULL;}if (!isLoadOk){return NULL;}DWORD OffsetStart = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;DWORD Size = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pImageBase + pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);int iBase = pExport->Base;int iNumberOfFunctions = pExport->NumberOfFunctions;int iNumberOfNames = pExport->NumberOfNames; //<= iNumberOfFunctions LPDWORD pAddressOfFunctions = (LPDWORD)(pExport->AddressOfFunctions + pImageBase);LPWORD pAddressOfOrdinals = (LPWORD)(pExport->AddressOfNameOrdinals + pImageBase);LPDWORD pAddressOfNames = (LPDWORD)(pExport->AddressOfNames + pImageBase);int iOrdinal = -1;if (((DWORD)lpProcName & 0xFFFF0000) == 0) //IT IS A ORDINAL! {iOrdinal = (DWORD)lpProcName & 0x0000FFFF - iBase;}else //use name {int iFound = -1;for (int i = 0; i < iNumberOfNames; i++){char *pName = (char *)(pAddressOfNames[i] + pImageBase);if (strcmp(pName, lpProcName) == 0){iFound = i;break;}}if (iFound >= 0){iOrdinal = (int)(pAddressOfOrdinals[iFound]);}}if (iOrdinal < 0 || iOrdinal >= iNumberOfFunctions){return NULL;}else{DWORD pFunctionOffset = pAddressOfFunctions[iOrdinal];if (pFunctionOffset > OffsetStart && pFunctionOffset < (OffsetStart + Size)) //maybe Export Forwarding {return NULL;}else{return (FARPROC)(pFunctionOffset + pImageBase);}}}// 重定向PE用到的地址
void CMemLoadDll::DoRelocation(void *NewBase)
{/* 重定位表的结构:// DWORD sectionAddress, DWORD size (包括本节需要重定位的数据)// 例如 1000节需要修正5个重定位数据的话,重定位表的数据是// 00 10 00 00 14 00 00 00 xxxx xxxx xxxx xxxx xxxx 0000// ----------- ----------- ----// 给出节的偏移 总尺寸=8+6*2 需要修正的地址 用于对齐4字节// 重定位表是若干个相连,如果address 和 size都是0 表示结束// 需要修正的地址是12位的,高4位是形态字,intel cpu下是3*///假设NewBase是0x600000,而文件中设置的缺省ImageBase是0x400000,则修正偏移量就是0x200000 DWORD Delta = (DWORD)NewBase - pNTHeader->OptionalHeader.ImageBase;//注意重定位表的位置可能和硬盘文件中的偏移地址不同,应该使用加载后的地址 PIMAGE_BASE_RELOCATION pLoc = (PIMAGE_BASE_RELOCATION)((unsigned long)NewBase+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);while ((pLoc->VirtualAddress + pLoc->SizeOfBlock) != 0) //开始扫描重定位表 {WORD *pLocData = (WORD *)((int)pLoc + sizeof(IMAGE_BASE_RELOCATION));//计算本节需要修正的重定位项(地址)的数目 int NumberOfReloc = (pLoc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);for (int i = 0; i < NumberOfReloc; i++){if ((DWORD)(pLocData[i] & 0xF000) == 0x00003000) //这是一个需要修正的地址 {// 举例: // pLoc->VirtualAddress = 0x1000; // pLocData[i] = 0x313E; 表示本节偏移地址0x13E处需要修正 // 因此 pAddress = 基地址 + 0x113E // 里面的内容是 A1 ( 0c d4 02 10) 汇编代码是: mov eax , [1002d40c] // 需要修正1002d40c这个地址 DWORD *pAddress = (DWORD *)((unsigned long)NewBase + pLoc->VirtualAddress + (pLocData[i] & 0x0FFF));*pAddress += Delta;}}//转移到下一个节进行处理 pLoc = (PIMAGE_BASE_RELOCATION)((DWORD)pLoc + pLoc->SizeOfBlock);}
}//填充引入地址表
BOOL CMemLoadDll::FillRavAddress(void *pImageBase)
{// 引入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组,全部是0表示结束 // 数组定义如下: // // DWORD OriginalFirstThunk; // 0表示结束,否则指向未绑定的IAT结构数组 // DWORD TimeDateStamp; // DWORD ForwarderChain; // -1 if no forwarders // DWORD Name; // 给出dll的名字 // DWORD FirstThunk; // 指向IAT结构数组的地址(绑定后,这些IAT里面就是实际的函数地址) int i;unsigned long Offset = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;if (Offset == 0){return TRUE; //No Import Table }PIMAGE_IMPORT_DESCRIPTOR pID = (PIMAGE_IMPORT_DESCRIPTOR)((unsigned long)pImageBase + Offset);while (pID->Characteristics != 0){PIMAGE_THUNK_DATA pRealIAT = (PIMAGE_THUNK_DATA)((unsigned long)pImageBase + pID->FirstThunk);PIMAGE_THUNK_DATA pOriginalIAT = (PIMAGE_THUNK_DATA)((unsigned long)pImageBase + pID->OriginalFirstThunk);//获取dll的名字 TCHAR buf[256]; //dll name; BYTE *pName = (BYTE *)((unsigned long)pImageBase + pID->Name);for (i = 0; i < 256; i++){if (pName[i] == 0){break;}buf[i] = pName[i];}if (i >= 256){return FALSE; // bad dll name }else{buf[i] = 0;}HMODULE hDll = GetModuleHandle(buf);if (hDll == NULL){hDll = LoadLibrary(buf);}if (hDll == NULL){return FALSE; //NOT FOUND DLL }//获取DLL中每个导出函数的地址,填入IAT //每个IAT结构是 : // union { PBYTE ForwarderString; // PDWORD Function; // DWORD Ordinal; // PIMAGE_IMPORT_BY_NAME AddressOfData; // } u1; // 长度是一个DWORD ,正好容纳一个地址。 for (i = 0; ; i++){if (pOriginalIAT[i].u1.Function == 0){break;}FARPROC lpFunction = NULL;if (pOriginalIAT[i].u1.Ordinal & IMAGE_ORDINAL_FLAG) //这里的值给出的是导出序号 {lpFunction = GetProcAddress(hDll, (LPCSTR)(pOriginalIAT[i].u1.Ordinal & 0x0000FFFF));}else //按照名字导入 {//获取此IAT项所描述的函数名称 PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pImageBase + (DWORD)(pOriginalIAT[i].u1.AddressOfData));// if(pByName->Hint !=0) // lpFunction = GetProcAddress(hDll, (LPCSTR)pByName->Hint); // else lpFunction = GetProcAddress(hDll, (char *)pByName->Name);}if (lpFunction != NULL) //找到了! {pRealIAT[i].u1.Function = (DWORD)lpFunction;//(PDWORD) lpFunction; }else{return FALSE;}}//move to next pID = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pID + sizeof(IMAGE_IMPORT_DESCRIPTOR));}return TRUE;
}//CheckDataValide函数用于检查缓冲区中的数据是否有效的dll文件
//返回值: 是一个可执行的dll则返回TRUE,否则返回FALSE。
//lpFileData: 存放dll数据的内存缓冲区
//DataLength: dll文件的长度
BOOL CMemLoadDll::CheckDataValide(void *lpFileData, int DataLength)
{//检查长度 if (DataLength < sizeof(IMAGE_DOS_HEADER)){return FALSE;}pDosHeader = (PIMAGE_DOS_HEADER)lpFileData; // DOS头 //检查dos头的标记 if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE){return FALSE; //0x5A4D : MZ }//检查长度 if ((DWORD)DataLength < (pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS))){return FALSE;}//取得pe头 pNTHeader = (PIMAGE_NT_HEADERS)((unsigned long)lpFileData + pDosHeader->e_lfanew); // PE头 //检查pe头的合法性 if (pNTHeader->Signature != IMAGE_NT_SIGNATURE){return FALSE; //0x00004550 : PE00 }if ((pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) //0x2000 : File is a DLL {return FALSE;}if ((pNTHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0) //0x0002 : 指出文件可以运行 {return FALSE;}if (pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)){return FALSE;}//取得节表(段表) pSectionHeader = (PIMAGE_SECTION_HEADER)((int)pNTHeader + sizeof(IMAGE_NT_HEADERS));//验证每个节表的空间 for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++){if ((pSectionHeader[i].PointerToRawData + pSectionHeader[i].SizeOfRawData) >(DWORD)DataLength){return FALSE;}}return TRUE;
}//计算对齐边界
int CMemLoadDll::GetAlignedSize(int Origin, int Alignment)
{return (Origin + Alignment - 1) / Alignment * Alignment;
}//计算整个dll映像文件的尺寸
int CMemLoadDll::CalcTotalImageSize()
{int Size;if (pNTHeader == NULL){return 0;}int nAlign = pNTHeader->OptionalHeader.SectionAlignment; //段对齐字节数 // 计算所有头的尺寸。包括dos, coff, pe头 和 段表的大小 Size = GetAlignedSize(pNTHeader->OptionalHeader.SizeOfHeaders, nAlign);// 计算所有节的大小 for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; ++i){//得到该节的大小 int CodeSize = pSectionHeader[i].Misc.VirtualSize;int LoadSize = pSectionHeader[i].SizeOfRawData;int MaxSize = (LoadSize > CodeSize) ? (LoadSize) : (CodeSize);int SectionSize = GetAlignedSize(pSectionHeader[i].VirtualAddress + MaxSize, nAlign);if (Size < SectionSize){Size = SectionSize; //Use the Max; }}return Size;
}
//CopyDllDatas函数将dll数据复制到指定内存区域,并对齐所有节
//pSrc: 存放dll数据的原始缓冲区
//pDest:目标内存地址
void CMemLoadDll::CopyDllDatas(void *pDest, void *pSrc)
{// 计算需要复制的PE头+段表字节数 int HeaderSize = pNTHeader->OptionalHeader.SizeOfHeaders;int SectionSize = pNTHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);int MoveSize = HeaderSize + SectionSize;//复制头和段信息 memmove(pDest, pSrc, MoveSize);//复制每个节 for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; ++i){if (pSectionHeader[i].VirtualAddress == 0 || pSectionHeader[i].SizeOfRawData == 0){continue;}// 定位该节在内存中的位置 void *pSectionAddress = (void *)((unsigned long)pDest + pSectionHeader[i].VirtualAddress);// 复制段数据到虚拟内存 memmove((void *)pSectionAddress,(void *)((DWORD)pSrc + pSectionHeader[i].PointerToRawData),pSectionHeader[i].SizeOfRawData);}//修正指针,指向新分配的内存 //新的dos头 pDosHeader = (PIMAGE_DOS_HEADER)pDest;//新的pe头地址 pNTHeader = (PIMAGE_NT_HEADERS)((int)pDest + (pDosHeader->e_lfanew));//新的节表地址 pSectionHeader = (PIMAGE_SECTION_HEADER)((int)pNTHeader + sizeof(IMAGE_NT_HEADERS));return;
}
相关文章:

VS2015项目中,MFC内存中调用DLL函数(VC6生成的示例DLL)
本例主要讲一下,用VC6如何生成DLL,用工具WinHex取得DLL全部内容,VC2015项目加载内存中的DLL函数,并调用函数的示例。 本例中的示例代码下载,点击可以下载 一、VC6.0生成示例DLL项目 1.新建项目,…...

人流目标跟踪pyqt界面_v5_deepsort
直接上效果图 代码仓库和视频演示b站视频006期: 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 代码展示: YOLOv5 DeepSORT介绍 YOLOv5 DeepSORT是一个结合了YOLOv5和DeepSORT算法的目标检测与多目标跟踪系统。让我为您详细解释一…...

angular 子组件ngOnChanges监听@input传入的输入属性
在进入主题之前,先了解一下angular的生命周期。 生命周期 钩子分类 指令与组件共有的钩子 ngOnChangesngOnInitngDoCheckngOnDestroy 组件特有的钩子 ngAfterContentInitngAfterContentCheckedngAfterViewInitngAfterViewChecked 生命周期钩子的作用及调用顺序 …...

移植PeerTalk开源库IOS的USB通信监听服务到QT生成的FFmpeg工程
1.添加生成的PeerTalk库 下图选中部分为FFmpeg依赖库 将USB通信服务的m与h文件添加到工程 因为OC文件使用了弱指针,所以要启用弱指针支持 因为FFmpeg拉流动用到本地网络,所以要在plist文件中启动本地网络使用 设置PeerTalk为嵌入模式 设置Runpath Search Paths为@executable_p…...

PHREEQC模型化学热力学理论和数据库.dat、各种模拟反应平衡反应模拟、化学动力模拟、反应迁移模拟
PHREEQC是一个用于计算多种低温水文地球化学反应的计算机软件,以离子缔合水模型为基础的PHREEQC能够(1)计算物质形成种类与饱和指数;(2)模拟地球化学反演过程;(3)计算批反…...

centos下使用jemalloc解决Mysql内存泄漏问题
参考: MySQL bug:https://bugs.mysql.com/bug.php?id83047&tdsourcetags_pcqq_aiomsg https://github.com/jemalloc/jemalloc/blob/dev/INSTALL.md (1)ptmalloc 是glibc的内存分配管理 (2)tcmalloc…...

【100天精通python】Day41:python网络爬虫开发_爬虫基础入门
目录 专栏导读 1网络爬虫概述 1.1 工作原理 1.2 应用场景 1.3 爬虫策略 1.4 爬虫的挑战 2 网络爬虫开发 2.1 通用的网络爬虫基本流程 2.2 网络爬虫的常用技术 2.3 网络爬虫常用的第三方库 3 简单爬虫示例 专栏导读 专栏订阅地址:https://blog.csdn.net/…...

开源和自研——机器人
双足机器人: MPC技术:封闭性非常高。没有开源方案可抄。 因为开源,不需要从0构建。 这也是前两年,国外一开源华为就遥遥领先。 射频芯片/射频天线:技术封闭。华为虽然做通信,但却没有攻破。 鸿蒙&#…...

【AIGC 讯飞星火 | 百度AI|ChatGPT| 】智能对比
AI智能对比 🍸 前言🍺 概念类对比🍵 讯飞🍵 百度AI🍵 chatGPT 🍹 功能类对比☕ 讯飞☕ 百度AI☕ chatGPT 🥃 可输入字数对比🥤 百度AI🥤 讯飞🥤 chatGPT &…...

Wazuh安装及使用
环境配置 官方网址Quickstart Wazuh documentation 可以选择Elastic Stack安装,也可以选择下载虚拟机(OVA)安装 这里展示虚拟机安装 下载好文档中提供的文件 虚拟机配置要求 在VM左上角 文件->打开->刚刚下载的.ova文件,…...

docker pull 设置代理 centos
On CentOS the configuration file for Docker is at: /etc/sysconfig/docker 用 root 权限打开 text editor sudo gedit 注意 加引号 Adding the below line helped me to get the Docker daemon working behind a proxy server: HTTP_PROXY“http://<proxy_host>:&…...

仪表板展示 | DataEase看中国:2023年中国电影市场分析
背景介绍 随着《消失的她》、《变形金刚:超能勇士崛起》、《蜘蛛侠:纵横宇宙》、《我爱你》等国内外影片的上映,2023年上半年的电影市场也接近尾声。据国家电影专资办初步统计,上半年全国城市院线票房达262亿元,已经超…...

在APP中如何嵌入小游戏?
APP内嵌游戏之所以能火爆,主要是因为互联网对流量的追求是无止境的,之前高速增长的红利期后,获取新的流量成为各大厂商的挑战,小游戏的引入,就是这个目的,为已有的产品赋能,抢占用户注意力和使用…...

神经网络基础-神经网络补充概念-02-逻辑回归
概念 逻辑回归是一种用于二分分类问题的统计学习方法,尽管名字中带有"回归"一词,但实际上它用于分类任务。逻辑回归的目标是根据输入特征来预测数据点属于某个类别的概率,然后将概率映射到一个离散的类别标签。 逻辑回归模型的核…...

DICOM图像的常用一些参数解析
医学图像DICOM医学影像文件格式详解 Dicom文件基本操作 DICOM图像参数? 像素:构成图片的小色点。图像每个维度的像素个数——该维度一共有多少个均匀分布的像素点。 分辨率(单位DPI):每英寸(Inch…...

Java虚拟机(JVM):虚拟机栈溢出
一、概念 Java虚拟机栈溢出(Java Virtual Machine Stack Overflow)是指在Java程序中,当线程调用的方法层级过深,导致栈空间溢出的情况。 Java虚拟机栈是每个线程私有的,用于存储方法的调用和局部变量的内存空间。每当…...

MySQL流程控制
流程控制 顺序结构: 程序从上往下依次执行分支结构: 程序按条件进行选择执行,从两条或多条路径中选择一条执行。循环结构: 程序满足一定条件下,重复执行一组语句 针对于MySQL的流程控制语句主要有3类。注意ÿ…...

智安网络|深入比较:Sass系统与源码系统的差异及选择指南
随着前端开发的快速发展,开发人员需要使用更高效和灵活的工具来处理样式表。在这个领域,Sass系统和源码系统是两个备受关注的选项。 Sass系统 Sass(Syntactically Awesome Style Sheets)是一种CSS预处理器,它扩展了CS…...

Day14 01-Shell脚本编程详解
文章目录 第一章 Shell编程【重点】1.1. Shell的概念介绍1.1.1. 命令解释器4.1.1.2. Shell脚本 1.2. Shell编程规范1.2.1. 脚本文件的结构1.2.2. 脚本文件的执行 1.3. Shell的变量1.3.1. 变量的用法1.3.2. 变量的分类1.3.3. 局部变量1.3.4. 环境变量1.3.5. 位置参数变量1.3.6. …...

NVIDIA GPU驱动和CUDA工具包 Linux CentOS 7 在线安装指南
挑选指定系统和对应的GPU型号下载驱动和CUDA工具包: Linux CentOS安装NVIDIA GPU驱动程序和NVIDIA CUDA工具包_centos安装显卡驱动和cuda_Entropy-Go的博客-CSDN博客 相比之下,本文是在线安装NVIDIA GPU驱动和CUDA工具包方式,省去挑选对应正确安装包的烦…...

Php“牵手”拼多多商品详情页数据采集方法,拼多多API接口申请指南
拼多多详情接口 API 是开放平台提供的一种 API 接口,它可以帮助开发者获取商品的详细信息,包括商品的标题、描述、图片等信息。在电商平台的开发中,详情接口API是非常常用的 API,因此本文将详细介绍详情接口 API 的使用。 一、拼…...

未来公文的智能化进程
随着技术的飞速发展,公文——这个有着悠久历史的官方沟通方式,也正逐步走向智能化的未来。自动化、人工智能、区块链...这些现代科技正重塑我们的公文制度,让其变得更加高效、安全和智慧。 1.语义理解与自动生成 通过深度学习和NLPÿ…...

C语言:深度学习知识储备
目录 数据类型 每种类型的大小是多少呢? 变量 变量的命名: 变量的分类: 变量的作用域和生命周期 作用域: 生命周期: 常量 字符串转义字符注释 字符串: 转义字符 操作符: 算术操作符…...

探索大模型时代下的算法工程师前景与发展路径
文章目录 大模型时代的挑战与机遇从算法到工程:技能升级的必要性发展路径与职业规划路径一:深耕研究领域路径二:工程实践与部署路径三:跨界合作与解决复杂问题路径四:教育培训和技术普及 不断学习与更新知识结论 &…...

【福建事业单位-综合基础知识】03行政法
【福建事业单位-综合基础知识】03行政法 1.行政法概述(原则重点)行政主体范围 行政行为总结 二.行政处罚2.1行政处罚的种类总结 行政法框架 1.行政法概述(原则重点) 行政法的首要原则是合法;自由裁量——合理行政&…...

CSS 背景属性
前言 背景属性 属性说明background-color背景颜色background-image背景图background-repeat背景图平铺方式background-position背景图位置background-size背景图缩放background-attachment背景图固定background背景复合属性 背景颜色 可以使用background-color属性来设置背景…...

小白到运维工程师自学之路 第七十五集 (Kubernetes 企业级高可用部署)2
8、添加master节点 在k8s-master2和k8s-master3节点创建文件夹 mkdir -p /etc/kubernetes/pki/etcd在k8s-master1节点执行 从k8s-master1复制密钥和相关文件到k8s-master2和k8s-master3 scp /etc/kubernetes/admin.conf root192.168.77.15:/etc/kubernetes scp /etc/kubernet…...

Educational Codeforces Round 62 (Rated for Div. 2) C. Playlist
一开始肯定要排个序,b相同时t大的在前边,不同时b大的在前面。 然后想最多只能选k个的限制,可以这样想,每次用到的b只能用已选到的最小的值,那可以把每个b都枚举一遍,然后每一次选时长最长的,且…...

postgresql中基础sql查询
postgresql中基础sql查询 创建表插入数据创建索引删除表postgresql命令速查简单查询计算查询结果 利用查询条件过滤数据模糊查询 创建表 -- 部门信息表 CREATE TABLE departments( department_id INTEGER NOT NULL -- 部门编号,主键, department_name CHARACTE…...

如何做好科技文献资料的翻译!
我们知道,科技文献是工程技术人员的重要参考文献,翻译科技文献资料有助于促进国内外科技知识和技术的传播。那么,如何做好科技文献资料的翻译,专业科技文献翻译哪家好? 据了解,科技文献翻译是一种以应用为主…...