Linux和windows进程同步与线程同步那些事儿(四):windows 下进程同步

Linux和windows进程同步与线程同步那些事儿(一)
Linux和windows进程同步与线程同步那些事儿(二): windows线程同步详解示例
Linux和windows进程同步与线程同步那些事儿(三): Linux线程同步详解示例
Linux和windows进程同步与线程同步那些事儿(四):windows 下进程同步
Linux和windows进程同步与线程同步那些事儿(五):Linux下进程同步


1. 互斥量(Mutex):

互斥量是最常用的线程同步机制,它可以确保在同一时间只有一个线程可以访问共享资源。
在Windows中,可以使用CreateMutex函数来创建互斥量。

下面是一个使用互斥量实现进程同步的代码示例。该示例展示了两个进程之间如何使用互斥量来保证共享资源的互斥访问。

#include <iostream>
#include <windows.h>int main() {// 创建互斥量对象HANDLE hMutex = CreateMutex(NULL, FALSE, "MyMutex");if (hMutex == NULL) {std::cout << "互斥量创建失败!" << std::endl;return 1;}// 尝试获取互斥量的所有权DWORD dwWaitResult = WaitForSingleObject(hMutex, INFINITE);if (dwWaitResult == WAIT_OBJECT_0) {std::cout << "进程A获得了互斥量的所有权!" << std::endl;// 模拟共享资源的访问std::cout << "进程A正在访问共享资源..." << std::endl;Sleep(5000);// 释放互斥量的所有权ReleaseMutex(hMutex);std::cout << "进程A释放了互斥量的所有权!" << std::endl;}else {std::cout << "进程A无法获取互斥量的所有权!" << std::endl;}// 关闭互斥量句柄CloseHandle(hMutex);return 0;
}
#include <iostream>
#include <windows.h>int main() {// 创建互斥量对象HANDLE hMutex = CreateMutex(NULL, FALSE, "MyMutex");if (hMutex == NULL) {std::cout << "互斥量创建失败!" << std::endl;return 1;}// 尝试获取互斥量的所有权DWORD dwWaitResult = WaitForSingleObject(hMutex, INFINITE);if (dwWaitResult == WAIT_OBJECT_0) {std::cout << "进程B获得了互斥量的所有权!" << std::endl;// 模拟共享资源的访问std::cout << "进程B正在访问共享资源..." << std::endl;Sleep(3000);// 释放互斥量的所有权ReleaseMutex(hMutex);std::cout << "进程B释放了互斥量的所有权!" << std::endl;}else {std::cout << "进程B无法获取互斥量的所有权!" << std::endl;}// 关闭互斥量句柄CloseHandle(hMutex);return 0;
}

在上面的代码示例中,进程A和进程B都通过调用CreateMutex函数来创建了一个名为"MyMutex"的互斥量对象。接着,它们分别调用WaitForSingleObject函数来尝试获取互斥量的所有权。

如果某个进程成功获取了互斥量的所有权(即dwWaitResult的值为WAIT_OBJECT_0),那么它就可以访问共享资源。在示例中,为了模拟共享资源的访问,我们使用了Sleep函数来暂停程序的执行。

完成对共享资源的访问后,进程需要调用ReleaseMutex函数来释放互斥量的所有权,以便其他进程可以获取互斥量的所有权。

最后,进程要调用CloseHandle函数来关闭互斥量句柄,释放系统资源。

请注意,这只是一个简单的示例,实际的应用中可能还需要处理异常情况、错误处理等。


2. 事件(Event):

事件用于线程间的通信和同步,允许线程等待某个特定事件的发生。
在Windows中,可以使用CreateEvent函数来创建事件对象。

下面是一个使用事件(Event)实现进程同步的代码示例。该示例展示了两个进程之间如何使用事件来进行进程同步。

#include <iostream>
#include <windows.h>int main() {// 创建事件对象HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, "MyEvent");if (hEvent == NULL) {std::cout << "事件创建失败!" << std::endl;return 1;}// 等待事件变为有信号状态DWORD dwWaitResult = WaitForSingleObject(hEvent, INFINITE);if (dwWaitResult == WAIT_OBJECT_0) {std::cout << "进程A检测到事件有信号!" << std::endl;// 执行需要同步的操作std::cout << "进程A正在执行同步操作..." << std::endl;Sleep(5000);std::cout << "进程A完成同步操作!" << std::endl;}else {std::cout << "进程A等待事件超时或发生其他错误!" << std::endl;}// 关闭事件句柄CloseHandle(hEvent);return 0;
}
#include <iostream>
#include <windows.h>int main() {// 打开事件对象HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, "MyEvent");if (hEvent == NULL) {std::cout << "事件打开失败!" << std::endl;return 1;}// 设置事件为有信号状态if (SetEvent(hEvent)) {std::cout << "进程B设置了事件的信号!" << std::endl;}else {std::cout << "进程B设置事件的信号失败!" << std::endl;}// 关闭事件句柄CloseHandle(hEvent);return 0;
}

在上面的代码示例中,进程A通过调用CreateEvent函数来创建了一个名为"MyEvent"的事件对象。而进程B则通过调用OpenEvent函数来打开同一个事件对象。

进程A调用WaitForSingleObject函数来等待事件变为有信号状态。一旦事件有信号,进程A就可以执行需要同步的操作。在示例中,我们使用了Sleep函数来模拟同步操作的执行。

进程B在需要进行同步的时候,调用SetEvent函数来设置事件的信号。这样,进程A就会被唤醒,继续执行同步操作。

请注意,事件对象具有自动复位(auto-reset)的特性,即一旦某个等待事件的进程被唤醒,事件会自动重置为无信号状态,其他等待事件的进程将继续等待。

最后,进程要调用CloseHandle函数来关闭事件句柄,释放系统资源。


3. 临界区(Critical Section):

临界区用于保护共享资源,确保在同一时间只有一个线程可以访问。
在Windows中,可以使用InitializeCriticalSection函数来初始化临界区。

下面是一个使用临界区(Critical Section)实现进程同步的代码示例。该示例展示了两个进程之间如何使用临界区来进行进程同步。

#include <iostream>
#include <windows.h>CRITICAL_SECTION g_cs;  // 全局临界区对象int main() {// 初始化临界区InitializeCriticalSection(&g_cs);// 进入临界区EnterCriticalSection(&g_cs);std::cout << "进程A进入临界区,执行同步操作..." << std::endl;Sleep(5000);  // 模拟同步操作std::cout << "进程A完成同步操作,退出临界区!" << std::endl;// 离开临界区LeaveCriticalSection(&g_cs);// 销毁临界区DeleteCriticalSection(&g_cs);return 0;
}
#include <iostream>
#include <windows.h>CRITICAL_SECTION g_cs;  // 全局临界区对象int main() {// 初始化临界区InitializeCriticalSection(&g_cs);// 进入临界区EnterCriticalSection(&g_cs);std::cout << "进程B进入临界区,执行同步操作..." << std::endl;Sleep(5000);  // 模拟同步操作std::cout << "进程B完成同步操作,退出临界区!" << std::endl;// 离开临界区LeaveCriticalSection(&g_cs);// 销毁临界区DeleteCriticalSection(&g_cs);return 0;
}

在上面的代码示例中,我们使用CRITICAL_SECTION类型的全局变量g_cs作为临界区对象。

进程A和进程B都会初始化临界区对象,进入临界区进行同步操作。

在示例中,我们使用了Sleep函数来模拟同步操作的执行。

进程A和进程B在完成同步操作后,都需要离开临界区。

最后,进程要调用DeleteCriticalSection函数来销毁临界区对象,释放系统资源。

请注意,临界区是进程内的同步机制,不适用于跨进程的同步。如果需要跨进程的同步,可以考虑使用互斥量(Mutex)或事件(Event)等其他机制。


4. 信号量(Semaphore):

信号量是一种经典的线程同步机制,它可以用于控制对共享资源的访问。
在Windows中,可以使用CreateSemaphore函数来创建信号量。

下面是一个使用信号量(Semaphore)实现进程同步的代码示例。该示例展示了两个进程之间如何使用信号量来进行进程同步。

#include <iostream>
#include <windows.h>HANDLE g_semaphore;  // 全局信号量句柄int main() {// 创建一个信号量,初始值为0,用于进程同步g_semaphore = CreateSemaphore(NULL, 0, 1, L"ProcessSync");std::cout << "进程A执行同步操作..." << std::endl;Sleep(5000);  // 模拟同步操作std::cout << "进程A完成同步操作,释放信号量!" << std::endl;ReleaseSemaphore(g_semaphore, 1, NULL);  // 释放信号量,允许进程B执行// 关闭信号量句柄CloseHandle(g_semaphore);return 0;
}
#include <iostream>
#include <windows.h>HANDLE g_semaphore;  // 全局信号量句柄int main() {// 创建一个信号量,初始值为0,用于进程同步g_semaphore = CreateSemaphore(NULL, 0, 1, L"ProcessSync");// 进程B等待信号量,直到进程A释放信号量WaitForSingleObject(g_semaphore, INFINITE);std::cout << "进程B执行同步操作..." << std::endl;Sleep(5000);  // 模拟同步操作std::cout << "进程B完成同步操作,释放信号量!" << std::endl;ReleaseSemaphore(g_semaphore, 1, NULL);  // 释放信号量,允许其他进程执行// 关闭信号量句柄CloseHandle(g_semaphore);return 0;
}

在上面的示例代码中,我们使用了HANDLE类型的全局变量g_semaphore作为信号量句柄。
进程A创建了一个名为"ProcessSync"的信号量,并执行同步操作之后,调用ReleaseSemaphore函数释放信号量。

进程B在等待信号量状态下,调用WaitForSingleObject函数等待进程A释放信号量,然后执行同步操作。
最后,进程要调用CloseHandle函数来关闭信号量句柄,释放系统资源。

请注意,信号量是一种用于进程间同步的机制,可以在不同进程之间实现同步。在示例中,我们使用了一个简单的二进制信号量,它的初始值为0,进程A通过ReleaseSemaphore函数将其值设置为1,使进程B可以继续执行。


5. 命名管道(Named Pipe):

命名管道是一种进程间通信的机制,可以用于实现进程间的数据交换和同步。
在Windows中,可以使用CreateNamedPipe函数来创建命名管道。

在 Windows 下,可以使用命名管道(Named Pipe)实现多进程间的同步。命名管道是一种特殊的文件,用于在不同进程间进行通信。下面是一个使用命名管道实现多进程同步的 C++ 代码示例:

进程A:写入数据

#include <iostream>
#include <windows.h>int main()
{HANDLE hPipe;// 创建命名管道LPCWSTR pipeName = TEXT("\\\\.\\pipe\\my_pipe");hPipe = CreateNamedPipe(pipeName,PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | PIPE_WAIT,1,              // 最大实例数65536,          // 输出缓冲区大小65536,          // 输入缓冲区大小0,              // 默认超时时间NULL            // 安全属性);// 等待进程B连接ConnectNamedPipe(hPipe, NULL);// 向管道写入数据const char* data = "Hello, World!";DWORD bytesWritten;WriteFile(hPipe, data, strlen(data) + 1, &bytesWritten, NULL);// 关闭管道DisconnectNamedPipe(hPipe);CloseHandle(hPipe);return 0;
}

进程B:读取数据

#include <iostream>
#include <windows.h>int main()
{HANDLE hPipe;// 连接到命名管道LPCWSTR pipeName = TEXT("\\\\.\\pipe\\my_pipe");hPipe = CreateFile(pipeName,GENERIC_READ,0,              // 共享模式NULL,           // 安全属性OPEN_EXISTING,0,              // 属性和标志NULL            // 模板文件);// 从管道读取数据char buffer[65536];DWORD bytesRead;ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL);// 打印数据std::cout << buffer << std::endl;// 关闭管道CloseHandle(hPipe);return 0;
}

上述代码中,进程A创建了一个命名管道,并等待进程B连接。然后,它向管道写入数据。进程B连接到同一个命名管道,并读取进程A写入的数据。

让我们更详细地解释一下代码:

  1. 在进程A中,CreateNamedPipe 函数用于创建命名管道。参数 pipeName 指定了命名管道的名称,格式为 \\.\pipe\pipeName。其他参数设置了管道的访问权限、缓冲区大小等。

  2. 进程A调用 ConnectNamedPipe 函数等待进程B连接。

  3. 进程A使用 WriteFile 函数向管道写入数据。

  4. 进程B使用 CreateFile 函数连接到命名管道。

  5. 进程B调用 ReadFile 函数从管道中读取数据。

  6. 最后,进程B关闭了管道。

在实际使用中,可以根据需要对代码进行修改和扩展,以满足你的具体需求。例如,你可以使用多线程创建多个进程,或者通过命名管道进行双向通信。


6. 共享内存(Shared Memory):

共享内存允许多个进程访问同一块内存区域,从而实现进程间的数据共享和通信。
在Windows中,可以使用CreateFileMappingMapViewOfFile等函数来创建和访问共享内存区域。

下面是一个使用共享内存在Windows下实现多个进程同步的代码示例:

#include <iostream>
#include <Windows.h>// 共享内存结构体
struct SharedData {HANDLE mutex;         // 互斥量HANDLE event;         // 事件CONDITION_VARIABLE conditionVariable; // 条件变量int counter;          // 共享计数器
};int main() {// 创建共享内存HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,nullptr,PAGE_READWRITE,0,sizeof(SharedData),L"MySharedMemory");if (hMapFile == NULL) {std::cerr << "Failed to create shared memory" << std::endl;return 1;}// 获取共享内存指针SharedData* sharedData = (SharedData*)MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(SharedData));if (sharedData == NULL) {std::cerr << "Failed to map shared memory" << std::endl;CloseHandle(hMapFile);return 1;}// 初始化互斥量、事件和条件变量sharedData->mutex = CreateMutex(nullptr, FALSE, nullptr);sharedData->event = CreateEvent(nullptr, FALSE, FALSE, nullptr);InitializeConditionVariable(&sharedData->conditionVariable);sharedData->counter = 0;// 创建多个进程进行同步操作for (int i = 0; i < 5; i++) {STARTUPINFO si = {};PROCESS_INFORMATION pi = {};wchar_t cmdLine[] = L"ChildProcess.exe"; // 子进程程序名// 启动子进程if (!CreateProcess(nullptr,cmdLine,nullptr,nullptr,FALSE,0,nullptr,nullptr,&si,&pi)) {std::cerr << "Failed to create child process" << std::endl;CloseHandle(hMapFile);return 1;}// 关闭子进程句柄CloseHandle(pi.hThread);CloseHandle(pi.hProcess);}// 等待所有子进程执行完毕WaitForMultipleObjects(5, sharedData->processHandles, TRUE, INFINITE);// 输出计数器值std::cout << "Counter = " << sharedData->counter << std::endl;// 释放资源UnmapViewOfFile(sharedData);CloseHandle(sharedData->mutex);CloseHandle(sharedData->event);CloseHandle(hMapFile);return 0;
}

这个示例中,首先创建了一个共享内存来存储互斥量、事件和条件变量等同步对象以及一个共享计数器。然后创建了多个子进程,在子进程中进行同步操作。

子进程代码示例(ChildProcess.exe):

#include <iostream>
#include <Windows.h>struct SharedData {HANDLE mutex;HANDLE event;CONDITION_VARIABLE conditionVariable;int counter;
};int main() {HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"MySharedMemory");if (hMapFile == NULL) {std::cerr << "Failed to open shared memory" << std::endl;return 1;}SharedData* sharedData = (SharedData*)MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(SharedData));if (sharedData == NULL) {std::cerr << "Failed to map shared memory" << std::endl;CloseHandle(hMapFile);return 1;}// 等待主进程通知WaitForSingleObject(sharedData->event, INFINITE);// 互斥量保护临界区WaitForSingleObject(sharedData->mutex, INFINITE);// 执行同步操作sharedData->counter++;std::cout << "Child process counter = " << sharedData->counter << std::endl;// 离开临界区ReleaseMutex(sharedData->mutex);// 通知主进程完成WakeConditionVariable(&sharedData->conditionVariable);// 释放资源UnmapViewOfFile(sharedData);CloseHandle(hMapFile);return 0;
}

在子进程中,首先打开共享内存,并获取共享内存指针。然后等待主进程通知,获取互斥量保护临界区,执行同步操作,离开临界区,通知主进程完成,并释放资源。


总结

互斥量(mutex):
适用场景:多个进程需要争夺同一个资源时,只能有一个进程访问资源。
优点:简单易用,能够实现多个进程间的互斥访问。
缺点:性能较低,需要进行系统调用,可能引起上下文切换开销。

事件(event):
适用场景:多个进程需要等待某个特定事件的发生后才能继续执行。
优点:可以在多个进程之间进行高效的同步。
缺点:只能用于单个事件的同步,不能用于争夺资源的同步。

临界区(critical section):
适用场景:多个进程需要访问共享资源时,只能有一个进程访问资源。
优点:具有较高的性能,适用于保护共享资源的场景。
缺点:只能用于同一个进程内的进程同步,不能用于跨进程同步。

信号量(semaphore):
适用场景:多个进程需要访问有限数量的资源时,控制同时访问的进程数量。
优点:可以用于控制同时访问资源的进程数量。
缺点:较复杂,容易引发死锁问题。

命名管道(named pipe):
适用场景:多个进程之间进行双向通信和同步。
优点:提供了进程间的可靠通信和同步机制。
缺点:性能较低,只能用于进程之间的通信和同步。

共享内存(shared memory):
适用场景:多个进程需要共享大块数据时。
优点:高效的进程间通信,能够实现数据共享。
缺点:需要进行同步,容易引发数据不一致或竞态条件。

综合比较:

  • 互斥量 : 适用于争夺单个资源的情况,使用简单,但性能较低。
  • 事件 : 适用于等待特定事件发生后才能继续执行的场景,同步效率高。
  • 临界区: 适用于保护共享资源的场景,性能较高。
  • 信号量: 适用于控制同时访问资源的进程数量,但使用较复杂,容易产生死锁。
  • 命名管道: 适用于进程间的通信和同步,但性能较低。
  • 共享内存: 适用于共享大块数据的场景,需要进行同步操作,可能引发竞态条件。

根据具体的场景和需求,可以选择合适的进程同步机制来实现进程间的同步和通信。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612783.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tensorflow Lite从入门到精通

TensorFlow Lite 是 TensorFlow 在移动和 IoT 等边缘设备端的解决方案&#xff0c;提供了 Java、Python 和 C API 库&#xff0c;可以运行在 Android、iOS 和 Raspberry Pi 等设备上。目前 TFLite 只提供了推理功能&#xff0c;在服务器端进行训练后&#xff0c;经过如下简单处…

IC设计的前端和后端是如何区分的?

一、工作着重点不同 **1、IC前端&#xff1a;**根据芯片规格书完成SOC的设计和集成&#xff0c; 使用仿真验证工具完成SOC的设计验证。 **2、IC后端&#xff1a;**将前端设计产生的门级网表通过EDA设计工具进行布局布线和进行物理验证并最终产生供制造用的GDSII数据 二、工作…

【开源】基于JAVA+Vue+SpringBoot的超市账单管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统设计3.1 总体设计3.2 前端设计3.3 后端设计在这里插入图片描述 四、系统展示五、核心代码5.1 查询供应商5.2 查询商品5.3 新增超市账单5.4 编辑超市账单5.5 查询超市账单 六、免责说明 一、摘要 1.1 项目介绍 基于…

使用pygame.draw绘制基本图形

import pygame# 初始化pygame pygame.init()# 创建显示窗口 screen pygame.display.set_mode((640, 480)) pygame.display.set_caption("绘制基本图形")# 定义颜色 BLACK (0, 0, 0) WHITE (255, 255, 255) RED (255, 0, 0) GREEN (0, 255, 0) BLUE (0, 0, 255)…

用java实现Client和Server之间的互相通信

概要&#xff1a;看过我之前文章的人都知道&#xff0c;client和server之间的通信必不可少的就是socket。而java已经帮我们做了很多事情。 创建Server端 第一步&#xff0c;创建ServerSocket 这个从名字上就可以看出来&#xff0c;服务器上的socket 0.0 ServerSocket ser…

算法篇:动态规划II

35、647. 回文子串 ①状态表示&#xff1a;dp[i][j]表示&#xff1a;s字符串[i&#xff0c;j]的子串&#xff0c;是否是回文串。(i<j) ②状态转移方程&#xff1a; if(s[i]!s[j]) dp[i][j]false; else if(s[i]s[j]) { if(ij||i1j)dp[i][j]true; else dp[i1][j-1]; }…

SpringMVC-04

RESTful是一种针对Web服务的软件架构风格&#xff0c;它基于HTTP协议和其他标准&#xff0c;用于构建可扩展、可维护和可拓展的网络应用程序。 RESTful风格的设计原则包括以下几点&#xff1a; 资源&#xff1a;将应用程序的所有内容都视为资源&#xff0c;每个资源都有唯一的…

(详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models

Haoran Wei1∗, Lingyu Kong2∗, Jinyue Chen2, Liang Zhao1, Zheng Ge1†, Jinrong Yang3, Jianjian Sun1, Chunrui Han1, Xiangyu Zhang1 1MEGVII Technology 2University of Chinese Academy of Sciences 3Huazhong University of Science and Technology arXiv 2023.12.11 …

通过dockerfile基于centosdocker镜像和postgresql12的离线安装包制作单机版的Docker镜像

可以按照以下步骤来制作一个基于CentOS Docker镜像和PostgreSQL 12离线安装包的单机版Docker镜像&#xff1a; 首先&#xff0c;创建一个空文件夹作为工作目录。 将CentOS Docker镜像保存到本地文件系统中&#xff0c;命名为centos.tar。你可以从Docker Hub下载CentOS Docker镜…

Docker部署Homepage个人引导页

个人名片&#xff1a; 对人间的热爱与歌颂&#xff0c;可抵岁月冗长&#x1f31e; 个人主页&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff1a;念舒_C.ying 个人博客&#x1f30f; &#xff1a;念舒_C.ying Homepage | 主页 1. 安装环境2. Docker部署 原作者&#xff1a;無…

flutter release包使用adb查看日志排查错误实践

release包给出去后发现出现无法启动的情况&#xff0c;需要flutter开发排查 &#xff0c;直接将release包安装到模拟器 使用adb 去连接模拟器 我这边是MuMu模拟器 adb connect 127.0.0.1:7555 然后查看设备列表 adb devices 直接输入0 即选择第一个设备 然后使用 adb logcat …

Python爬虫---Scrapy项目的创建及运行

Scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架。 可以应用在包括数据挖 掘&#xff0c;信息处理或存储历史数据等一系列的程序中。 1. 安装scrapy&#xff1a; pip install scrapy 注意&#xff1a;需要安装在python解释器相同的位置,例如&#xf…

Spring原理-7.切点与切面

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

静态网页设计实践(HTML+CSS)

一、前端程序员必会三大编程语言 &#xff08;一&#xff09;HTML&#xff08;.html/.htm&#xff09; 超文本标记语言&#xff08;HyperText Markup Language&#xff0c;简称:HTML&#xff09;是一种用于创建网页的标准标记语言。HTML是一种基础技术&#xff0c;常与CSS、Ja…

高通rb5的fastboot设备识别不了及驱动安装问题

Android fastboot驱动无法安装和识别问题-CSDN博客 以上为转载出处。

批量求和(文件)

请编写函数&#xff0c;从一个文件中读取实数求和&#xff0c;并将结果写入另一个文件。 函数原型 void BatchAdd(FILE *in, FILE *out); 说明&#xff1a;参数 in 和 out 为指示两个文件的指针。函数从 in 所指文件中的读出数据&#xff0c;将结果写入 out 所指的文件中。 …

C语言中socket模块、线程

socket编程 windows下TCP协议 测试环境基于Win10 x64&#xff0c;Visual Studio 服务端代码1. 初始化Winsock库&#xff1b;2. 创建套接字&#xff1b;3. 配置服务端地址&#xff1b;4. 绑定套接字&#xff1b;5. 监听连接&#xff1b;6. 接收连接&#xff1b;7. 发送数据给客…

使用global mapper将分块DSM/DOM合并导出

使用global mapper将分块DSM/DOM合并导出 使用context capture生产dom/dsm时通常因为内存问题而选择分块生产&#xff0c;那么得到的dsm/dom则是一块一块的&#xff0c;如下&#xff1a; 那么为了合并成一张影像&#xff0c;可以使用强大的地图软件 Global Mapper&#xff0c…

番外篇-区块链基础知识入门

今天聊聊番外篇之Web3、区块链的基础知识~ 1. 区块链是如何工作的&#xff1f; Hash算法 将输入的数据映射为一个固定长度的字符串字符串是64长度&#xff0c;16进制&#xff08;2^4&#xff09;&#xff0c;4 * 64 256【SHA256】hash演示&#xff1a;https://andersbrownwo…

android 9 reboot流程

机器出现开机 自动进入fastboot模式。可能是init 那个进程挂了 然后调用了 RebootSystem(ANDROID_RB_RESTART2, “bootloader”); 函数进入重启流程&#xff0c;然后重启后进入fastboot 浅读一下reboot流程和怎么进入的fastboot 比如说是那个进程挂了调用了这个函数&#xff0c…