手动创建单进程: 下面通过一个实例来分别演示进程的创建函数.

#include <windows.h>
#include <stdio.h> BOOL WinExec(char *pszExePath, UINT uiCmdShow)
{
UINT uiRet = 0;
uiRet = ::WinExec(pszExePath, uiCmdShow);
if (31 < uiRet)
{
return TRUE;
}
return FALSE;
} BOOL ShellExecute(char *pszExePath, UINT uiCmdShow)
{
HINSTANCE hInstance = 0;
hInstance = ::ShellExecute(NULL, NULL, pszExePath, NULL, NULL, uiCmdShow);
if (32 < (DWORD)hInstance)
{
return TRUE;
}
return FALSE;
} BOOL Exec_Run(LPCSTR exe_file)
{
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
si.cb = sizeof(STARTUPINFO); BOOL bRet = CreateProcessA(exe_file,
NULL, NULL, NULL, FALSE,
NULL, NULL, NULL, &si, &pi); if (bRet != FALSE)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return TRUE;
}
return FALSE;
} int main(int argc, char * argv[])
{
int ret = 0;
ret = Exec_Run("c:\\windows\\system32\\notepad.exe");
printf("执行状态: %d \n", ret); system("pause");
return 0;
}

手动创建多线程: 多线程的创建需要使用CreateThread()其内部应该传递进去ThreadProc()线程执行函数,运行结束后恢复.

#include <Windows.h>
#include <iostream> int Global_One = 0;
CRITICAL_SECTION g_cs; // 定义一个线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
// 加锁防止线程数据冲突
EnterCriticalSection(&g_cs);
for (int x = 0; x < 10; x++)
{
Global_One++;
Sleep(1);
}
// 执行完修改以后,需要释放锁
LeaveCriticalSection(&g_cs);
return 0;
} int main()
{
// 初始化锁
InitializeCriticalSection(&g_cs); HANDLE hThread[10] = { 0 }; for (int x = 0; x < 10; x++)
{
// 循环创建线程
hThread[x] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
}
// 等待多个线程执行结束.
WaitForMultipleObjects(10, hThread, TRUE, INFINITE); // 最后循环释放资源
for (int x = 0; x < 10; x++)
{
CloseHandle(hThread[x]);
} printf("Global: %d \n", Global_One);
DeleteCriticalSection(&g_cs); system("pause");
return 0;
}

强制终止一个进程: 在进程正常进行退出时,会调用ExitProcess()正常关闭程序,也可以调用TerminateProcess()强制销毁进程.

#include <windows.h>
#include <stdio.h> int Get_ProcessID(LPCSTR path)
{
HWND hWnd = FindWindow(NULL, path);
if (hWnd != NULL)
{
DWORD dwPid = 0;
GetWindowThreadProcessId(hWnd, &dwPid);
if (dwPid != 0)
return dwPid;
}
return -1;
} int main(int argc,char * argv [])
{
int pid = 0; pid = Get_ProcessID("新建文本文档.txt - 记事本");
printf("进程PID为: %d \n", pid); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess != NULL)
{
TerminateProcess(hProcess, 0); // 终止进程
} system("pause");
return 0;
}

判断进程是否存在: 通过循环遍历所有进程,并对比szExeFile名称是否与pName一致,来实现判断进程是否正在运行中.

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h> int Get_Process_Status(const char *procressName)
{
char pName[MAX_PATH];
strcpy(pName, procressName); // 拷贝数组
CharLowerBuff(pName, MAX_PATH); // 将名称转换为小写 PROCESSENTRY32 currentProcess; // 存放快照进程信息的一个结构体
currentProcess.dwSize = sizeof(currentProcess); // 在使用这个结构之前,先设置它的大小
HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 给系统内的所有进程拍一个快照 if (INVALID_HANDLE_VALUE != hProcess)
{
BOOL bMore = Process32First(hProcess, &currentProcess);
while (bMore)
{
CharLowerBuff(currentProcess.szExeFile, MAX_PATH); // 将进程名转换为小写
if (strcmp(currentProcess.szExeFile, pName) == 0) // 比较是否存在此进程
{
CloseHandle(hProcess);
return 1;
}
bMore = Process32Next(hProcess, &currentProcess);
}
CloseHandle(hProcess);
}
return -1;
} int main(int argc,char * argv [])
{
int ret = Get_Process_Status("qq.exe"); if (ret == 1)
printf("正在运行. \n");
else
printf("没有运行. \n"); system("pause");
return 0;
}

遍历获取进程PID:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h> DWORD FindProcessID(LPCTSTR szProcessName)
{
DWORD dwPID = 0xFFFFFFFF;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
Process32First(hSnapShot, &pe);
do
{
if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile))
{
dwPID = pe.th32ProcessID;
break;
}
} while (Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
return dwPID;
} int main(int argc,char *argv[])
{
DWORD PID = FindProcessID(L"qq.exe");
printf("该进程PID是: %d \n", PID); system("pause");
return 0;
}

枚举系统中所有进程:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h> int EnumProcess()
{
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32); // 获取全部进程快照
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE != hProcessSnap)
{
// 获取快照中第一条信息
BOOL bRet = Process32First(hProcessSnap, &pe32);
while (bRet)
{
printf("进程ID: %-5d --> 进程名: %s \n", pe32.th32ProcessID, pe32.szExeFile);
// 获取快照中下一条信息
bRet = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
}
return -1;
} int main(int argc,char * argv [])
{
EnumProcess(); system("pause");
return 0; }

枚举指定进程中的DLL模块: 枚举出指定PID进程中所加载的DLL

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h> int EnumProcessModule(DWORD Pid)
{
MODULEENTRY32 me32 = { 0 };
me32.dwSize = sizeof(MODULEENTRY32);
// 获取指定进程全部模块的快照
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Pid); if (INVALID_HANDLE_VALUE != hModuleSnap)
{
// 获取快照中第一条信息
BOOL bRet = Module32First(hModuleSnap, &me32);
while (bRet)
{
printf("模块基址: 0x%p --> 大小: %-8d --> 模块名: %-25s -> 路径: %s \n",
me32.modBaseAddr, me32.modBaseSize, me32.szModule,me32.szExePath); // 获取快照中下一条信息
bRet = Module32Next(hModuleSnap, &me32);
}
CloseHandle(hModuleSnap);
return 0;
}
return -1;
} int main(int argc,char * argv [])
{
EnumProcessModule(1920); system("pause");
return 0;
}

枚举进程中线程ID:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h> int EnumThread(DWORD Pid)
{
THREADENTRY32 te32 = { 0 };
te32.dwSize = sizeof(THREADENTRY32);
int index = 0; // 获取全部线程快照
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (INVALID_HANDLE_VALUE != hThreadSnap)
{
// 获取快照中第一条信息
BOOL bRet = Thread32First(hThreadSnap, &te32);
while (bRet)
{
// 只过滤出 Owner Process ID = pid 的线程ID
if (Pid == te32.th32OwnerProcessID)
{
printf("线程ID: %6d --> 大小: %d \n", te32.th32ThreadID,te32.dwSize);
++index;
} // 获取快照中下一条信息
bRet = Thread32Next(hThreadSnap, &te32);
}
CloseHandle(hThreadSnap);
return index;
}
return -1;
} int main(int argc,char * argv [])
{
int tid_count = EnumThread(9868);
printf("线程数: %d \n", tid_count); system("pause");
return 0;
}

判断进程是否重复运行:

#include <Windows.h>
#include <stdio.h> // 判断是否重复运行
BOOL IsAlreadyRun()
{
HANDLE hMutex = NULL;
hMutex = CreateMutex(NULL, FALSE, "RUN");
if (hMutex)
{
if (ERROR_ALREADY_EXISTS == GetLastError())
return TRUE;
}
return FALSE;
} int main(int argc, const char * argv[])
{
if (IsAlreadyRun() == TRUE)
printf("重复运行 \n");
else
printf("没有重复运行 \n"); system("pause");
return 0;
}

循环干掉特定进程: 该方式只能干掉普通的检测程序,无法干掉带有自保护的杀软,需要加载驱动。

#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h> int Kill_AV_Process(char *kill_list[],int Count)
{
PROCESSENTRY32 currentProcess;
currentProcess.dwSize = sizeof(currentProcess);
HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE != hProcess)
{
BOOL bMore = Process32First(hProcess, &currentProcess);
while (bMore)
{
CharLowerBuff(currentProcess.szExeFile, MAX_PATH); for (int each = 0; each < Count; each++)
{
if (strcmp(currentProcess.szExeFile, kill_list[each]) == 0)
{
// printf("干掉进程 --> %s \n", kill_list[each]);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, currentProcess.th32ProcessID);
TerminateProcess(hProcess, 0);
}
}
bMore = Process32Next(hProcess, &currentProcess);
}
CloseHandle(hProcess);
}
return -1;
} int main(int argc, char * argv[])
{
// 填写杀毒软件的进程名称,然后循环干掉进程
char *fuck[10] = { "chrome.exe", "360.exe","qqpctray.exe","qqpcrtp.exe","qmdl.exe" };
Kill_AV_Process(fuck,5); system("pause");
return 0;
}

暂停/恢复指定的线程:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h> int Start_Stop_Thread(DWORD Pid,DWORD ThreadID)
{
THREADENTRY32 te32 = { 0 };
te32.dwSize = sizeof(THREADENTRY32); // 获取全部线程快照
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (INVALID_HANDLE_VALUE != hThreadSnap)
{
// 获取快照中第一条信息
BOOL bRet = Thread32First(hThreadSnap, &te32);
while (bRet)
{
// 只过滤出 pid 里面的线程
if (Pid == te32.th32OwnerProcessID)
{
// 判断是否为ThreadID,暂停指定的TID
if (ThreadID == te32.th32ThreadID)
{
// 打开线程
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); SuspendThread(hThread); // 暂停线程
//ResumeThread(hThread); // 恢复线程
CloseHandle(hThreadSnap);
}
}
// 获取快照中下一条信息
bRet = Thread32Next(hThreadSnap, &te32);
}
return 0;
}
return -1;
} int main(int argc, char * argv[])
{
// 暂停或恢复进程ID = 4204 里面的线程ID = 10056
int ret = Start_Stop_Thread(4204,10056);
printf("状态: %d \n", ret); system("pause");
return 0;
}

枚举进程内存权限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h> void ScanMemoryAttribute()
{
DWORD Addres = 0, Size = 0;
MEMORY_BASIC_INFORMATION Basicinfo = {}; // 遍历进程所有分页, 输出内容
while (VirtualQuery((LPCVOID)Addres, &Basicinfo, sizeof(MEMORY_BASIC_INFORMATION)))
{
Size = Basicinfo.RegionSize;
printf("地址: %08p 类型: %7d 大小: %7d 状态: ", Basicinfo.BaseAddress,Basicinfo.Type,Basicinfo.RegionSize);
switch (Basicinfo.State)
{
case MEM_FREE: printf("空闲 \n"); break;
case MEM_RESERVE: printf("保留 \n"); break;
case MEM_COMMIT: printf("提交 \n"); break;
default: printf("未知 \n"); break;
} // 如果是提交状态的内存区域,那么遍历所有块中的信息
if (Basicinfo.State == MEM_COMMIT)
{
// 遍历所有基址是 Address
LPVOID BaseBlockAddress = (LPVOID)Addres;
DWORD BlockAddress = Addres;
DWORD dwBlockSize = 0;
// 遍历大内存块中的小内存块
while (VirtualQuery((LPVOID)BlockAddress, &Basicinfo, sizeof(Basicinfo)))
{
if (BaseBlockAddress != Basicinfo.AllocationBase)
{
break;
}
printf("--> %08X", BlockAddress);
// 查看内存状态,映射方式
switch (Basicinfo.Type)
{
case MEM_PRIVATE: printf("私有 "); break;
case MEM_MAPPED: printf("映射 "); break;
case MEM_IMAGE: printf("镜像 "); break;
default: printf("未知 "); break;
} if (Basicinfo.Protect == 0)
printf("---");
else if (Basicinfo.Protect & PAGE_EXECUTE)
printf("E--");
else if (Basicinfo.Protect & PAGE_EXECUTE_READ)
printf("ER-");
else if (Basicinfo.Protect & PAGE_EXECUTE_READWRITE)
printf("ERW");
else if (Basicinfo.Protect & PAGE_READONLY)
printf("-R-");
else if (Basicinfo.Protect & PAGE_READWRITE)
printf("-RW");
else if (Basicinfo.Protect & PAGE_WRITECOPY)
printf("WCOPY");
else if (Basicinfo.Protect & PAGE_EXECUTE_WRITECOPY)
printf("EWCOPY");
printf("\n"); // 计算所有相同块大小
dwBlockSize += Basicinfo.RegionSize;
// 累加内存块的位置
BlockAddress += Basicinfo.RegionSize;
}
// 内有可能大小位空
Size = dwBlockSize ? dwBlockSize : Basicinfo.RegionSize;
}
// 下一个区域内存信息
Addres += Size;
}
} int main(int argc, char * argv[])
{
ScanMemoryAttribute();
system("pause");
return 0;
}

查询进程所具备的权限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h> BOOL QueryPrivileges()
{
// 1. 获得本进程的令牌
HANDLE hToken = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return false; // 2. 获取提升类型
TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeDefault;
BOOL bIsAdmin = false;
DWORD dwSize = 0; if (GetTokenInformation(hToken, TokenElevationType, &ElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize))
{
// 2.1 创建管理员组的对应SID
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &dwSize); // 2.2 判断当前进程运行用户角色是否为管理员
if (ElevationType == TokenElevationTypeLimited)
{
// a. 获取连接令牌的句柄
HANDLE hUnfilteredToken = NULL;
GetTokenInformation(hToken, TokenLinkedToken, (PVOID)&hUnfilteredToken, sizeof(HANDLE), &dwSize);
// b. 检查这个原始的令牌是否包含管理员的SID
if (!CheckTokenMembership(hUnfilteredToken, &adminSID, &bIsAdmin))
return false;
CloseHandle(hUnfilteredToken);
}
else
{
bIsAdmin = IsUserAnAdmin();
}
} // 3. 判断具体的权限状况
BOOL bFullToken = false;
switch (ElevationType)
{
case TokenElevationTypeDefault: /* 默认的用户或UAC被禁用 */
if (IsUserAnAdmin())
bFullToken = true; // 默认用户有管理员权限
else
bFullToken = false; // 默认用户不是管理员组
break; case TokenElevationTypeFull: /* 已经成功提高进程权限 */
if (IsUserAnAdmin())
bFullToken = true; // 当前以管理员权限运行
else
bFullToken = false; // 当前未以管理员权限运行
break; case TokenElevationTypeLimited: /* 进程在以有限的权限运行 */
if (bIsAdmin)
bFullToken = false; // 用户有管理员权限,但进程权限有限
else
bFullToken = false; // 用户不是管理员组,且进程权限有限
break;
}
return bFullToken;
} int main(int argc, char * argv[])
{
BOOL ret = QueryPrivileges();
printf("具备权限: %d \n", ret); system("pause");
return 0;
}

枚举指定进程权限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h> void ShowPrviliges(HANDLE process)
{
// 通过进程句柄获取到进程令牌
HANDLE hToken;
OpenProcessToken(process, TOKEN_QUERY, &hToken); // 获取查询道德令牌信息
DWORD dwSize;
GetTokenInformation(hToken,TokenPrivileges, NULL, NULL, &dwSize); // 根据令牌中的大小分配空间
char *pBuf = new char[dwSize] {};
GetTokenInformation(hToken,TokenPrivileges, pBuf, dwSize, &dwSize); // 将内存中的内容用要查询数据结构体解析
TOKEN_PRIVILEGES* pTp = (TOKEN_PRIVILEGES*)pBuf;
DWORD dwCount = pTp->PrivilegeCount; // 解析出权限个数
LUID_AND_ATTRIBUTES* pluid = pTp->Privileges; // 具备的权限类型 for (int i = 0; i < dwCount; i++, pluid++)
{
char szName[100] = {};
DWORD dwLen = sizeof(szName);
LookupPrivilegeNameA(0, &pluid->Luid, szName, &dwLen);
switch (pluid->Attributes)
{
case 0:
printf("[ID: %3d] ---> [关闭] ---> %s \n", i,szName); break;
case 1:
printf("[ID: %3d] ---> [默认] ---> %s \n", i,szName); break;
case 2:
printf("[ID: %3d] ---> [开启] ---> %s \n", i,szName); break;
case 3:
printf("[ID: %3d] ---> [默认开启] ---> %s \n", i,szName); break;
}
}
delete pBuf;
} int main(int argc ,char *argv[])
{
// 拿到PID为9656程序的句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 9656);
ShowPrviliges(hProcess); // 拿到自身程序的句柄
HANDLE LocalProcess = GetCurrentProcess();
ShowPrviliges(LocalProcess); system("pause");
return 0;
}

提升指定进程权限:

#include <windows.h>
#include <stdio.h> int EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName)
{
HANDLE hToken = NULL;
LUID luidValue = { 0 };
TOKEN_PRIVILEGES tokenPrivileges = { 0 };
BOOL bRet = FALSE;
DWORD dwRet = 0; // 打开进程令牌并获取具有 TOKEN_ADJUST_PRIVILEGES 权限的进程令牌句柄
bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
if (bRet != FALSE)
{
// 获取本地系统的 pszPrivilegesName 特权的LUID值
bRet = LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);
if (bRet == FALSE)
return -1;
} // 设置提升权限信息
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luidValue;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 提升进程令牌访问权限
bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);
if (bRet != FALSE)
{
// 根据错误码判断是否特权都设置成功
dwRet = GetLastError();
if (ERROR_SUCCESS == dwRet)
{
return 1;
}
}
return -1;
} int main(int argc,char * argv [])
{
// 获取当前自身进程句柄
HANDLE Local_Pid = GetCurrentProcess(); // 修改当前进程令牌访问权限
if (FALSE != EnbalePrivileges(Local_Pid, SE_DEBUG_NAME))
printf("提权成功 \n"); system("pause");
return 0;
}

C/C++ 进程线程操作技术的更多相关文章

  1. python学习笔记-进程线程

    1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...

  2. 获取系统中所有进程&线程信息

    读书笔记--[计算机病毒解密与对抗] 目录: 遍历进程&线程程序 终止进程 获取进程信息 获取进程内模块信息 获取进程命令行参数 代码运行环境:Win7 x64 VS2012 Update3 ...

  3. [skill] 进程 线程

    在业务逻辑上: 进程线程没有区别. 在系统资源上: 进程拥有自己的地址空间.线程拥有自己的堆栈和临时变量,与其他线程共享地址空间. 在通信代价上: 线程间通信代价更低,实现更方便.进程通信相对开销比较 ...

  4. pyhon——进程线程、与协程基础概述

    一直以来写博客都是实用主义者,只写用法,没信心写原理,但是每一次写作业的过程都有一种掘地三尺的感觉,终于,写博客困难症重症患者经历了漫长的思想斗争,还是决定把从网上淘到的各种杂货和自己的总结放在一起, ...

  5. android 进程/线程管理(一)----消息机制的框架

    一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统, ...

  6. android 进程/线程管理(二)----关于线程的迷思

    一:进程和线程的由来 进程是计算机科技发展的过程的产物. 最早计算机发明出来,是为了解决数学计算而发明的.每解决一个问题,就要打纸带,也就是打点. 后来人们发现可以批量的设置命令,由计算机读取这些命令 ...

  7. android 进程/线程管理(三)----Thread,Looper / HandlerThread / IntentService

    Thread,Looper的组合是非常常见的组合方式. Looper可以是和线程绑定的,或者是main looper的一个引用. 下面看看具体app层的使用. 首先定义thread: package ...

  8. android 进程/线程管理(四)续----消息机制的思考(自定义消息机制)

    继续分析handler 和looper 先看看handler的 public void dispatchMessage(Message msg) { if (msg.callback != null) ...

  9. android 进程/线程管理(四)----消息机制的思考(自定义消息机制)

    关于android消息机制 已经写了3篇文章了,想要结束这个系列,总觉得少了点什么? 于是我就在想,android为什么要这个设计消息机制,使用消息机制是现在操作系统基本都会有的特点. 可是andro ...

  10. windows进程/线程创建过程 --- windows操作系统学习

    有了之前的对进程和线程对象的学习的铺垫后,我们现在可以开始学习windows下的进程创建过程了,我将尝试着从源代码的层次来分析在windows下创建一个进程都要涉及到哪些步骤,都要涉及到哪些数据结构. ...

随机推荐

  1. 深入了解浮点运算——CPU 和 GPU 算力是如何计算的

    随着国家大力发展数字经济,算力的提升和普惠变得越来越重要.在数字化时代,算力已成为推动科技发展和创新的关键要素.它不仅仅是衡量计算机处理速度的标准,还涉及计算机系统或设备执行计算任务的能力.数据处理能 ...

  2. LiveData的用法

    一.实时数据LiveData 在上一节中,我们学习了ViewModel,了解到ViewModel的主要作用是存放页面所需要的各种数据.我们在示例代码中定义了接口,当数据发生变化的时候,采用接口的方式实 ...

  3. Navigation的用法

    一.Navigation的诞生 单个Activity嵌套多个Fragment的UI架构模式,已经被大多数的Android工程师所接受和采用.但是,对Fragment的管理一直是一件比较麻烦的事情.我们 ...

  4. Codeforces Round #717 (Div. 2) 个人题解 A~C (A思維,B位運算,C背包DP)

    1516A. Tit for Tat 題意: 給定大小為 \(n\) 的數組和可操作次數 \(k\) , 每次操作都選定兩個數(如果 \(1 \le a_i\) ),使第一個數 - \(1\) ,另一 ...

  5. AtCoder Beginner Contest 178 个人题解(C组合问题 + 快速幂,D规律,E数学公式变形)

    补题链接:Here A - Not Editorial 给出 \(x = 1\) 则输出 0:给出 \(x = 0\) 则输出 1 利用 x ^ 1 可以快速实现 \(x\) 的转换 B - Prod ...

  6. Java 8 Stream原理解析

    说起 Java 8,我们知道 Java 8 大改动之一就是增加函数式编程,而 Stream API 便是函数编程的主角,Stream API 是一种流式的处理数据风格,也就是将要处理的数据当作流,在管 ...

  7. element-china-area-data

    https://blog.csdn.net/xiejnpeng/article/details/111400199

  8. 使用 Sealos 一键部署 Kubernetes 集群

    Sealos 是一款以 Kubernetes 为内核的云操作系统发行版,使用户能够像使用个人电脑一样简单地使用云. 与此同时,Sealos 还提供一套强大的工具,可以便利地管理整个 Kubernete ...

  9. docker目录迁移流程

    概述 在安装测试最新版本的HOMER7的过程中,docker作为基础工具碰到一些问题,针对问题进行总结. docker的默认工作目录在/var目录,而在我们的环境中,/var目录空间预留不足,随着do ...

  10. Mysql 查询优化及索引优化总结

    本文为博主原创,转载请注明出处: 一.Mysql 索引的优缺点: 优点:加快数据的检索速度,这是应用索引的主要用途: 使用唯一索引可以保证数据的唯一性 缺点: 索引也需要占用物理空间,并不是索引越多越 ...