我正在尝试阅读 - >加密/解密 - >逐个部门编写原始数据。我需要以某种方式优化时间,因为仅仅2GB的音量需要2个多小时(我的音量G:这里)。我尝试使用线程来处理时间问题,但没有显着的结果。该程序需要在日常使用的PC上运行。
每个线程在与其他线程不同的扇区块上运行。
我知道的事情:
- 写作时无法完成阅读(所以我处理了临界区问题)
- 线程中的读/写由于寻道时间等原因而缩短了时间。
- 由于延迟(由读/写磁头来回移动引起)导致太多线程可能无法完成任务。(给出错误DEVICE_NOT_READY))
醇>我想问一下:
- 我是否可以同时利用线程在两个不同的扇区上进行读写或写入(因为我知道磁盘操作是使用已回答here的调度算法来执行的)?
- 为什么程序在一个线程(在一个扇区上)写入时会产生错误,其他线程会尝试读取(在另一个扇区上)?
- 您建议如何缩短时间?
醇>代码:
DWORD WINAPI EncryptSectorBlock(LPVOID lpParam)
{
PTARGS args = (PTARGS)lpParam;
static unsigned char buffer[SECTOR_SIZE];
printf("Thread No:%i start:%i end:%i\n ", args->thread_id, args->sector_start, args->sector_end);
for (int i = args->sector_start; i <= args->sector_end; i++)
{
//Entering critical section of the code. The Other Threads Would be first spin with 65536 loops and then set to
// sleep until the worker threads releases the lock on critical section
if (ReadSector(args->read, buffer, SECTOR_SIZE, i) != 1)
printf("Thread: %i. Error reading sector %i\n",args->thread_id, i);
else
printf("Thread: %i. Read Sector %i Successfully\n", args->thread_id, i);
xts_encrypt_sector(buffer, i, SECTOR_SIZE, &(args->ctx));
//Critical Section starts
EnterCriticalSection(&CriticalSection);
if (WriteSector(args->write, buffer, SECTOR_SIZE, i) != 1)
printf("Thread: %i. Error writing sector %i\n",args->thread_id ,i);
else
printf("Thread: %i. Wrote Sector %i Successfully\n", args->thread_id, i);
//Critical Section Ends
LeaveCriticalSection(&CriticalSection);
//init to zero every time in case a sector is failed to be read or write, so it can recover from fault
//This may break in future.. Not proper mechanism to recover from fault. just a hack.
memset(buffer, 0, SECTOR_SIZE);
}
return 0;
}
INT_RETURN EncryptFullVolume(wchar_t* volume, unsigned char* key)
{
//init variables here
for (int i = 0; i < MAX_Threads; i++)
{
ArgsDataArray[i] = (PTARGS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TARGS));
if (ArgsDataArray[i] == NULL)
{
// If the array allocation fails, the system is out of memory
// so there is no point in trying to print an error message.
// Just terminate execution.
ret = EXIT_FAILURE;
}
else
{
// Generate unique data for each thread to work with here
// Create the thread to begin execution on its own.
hThreadArray[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
EncryptSectorBlock, // thread function name
ArgsDataArray[i], // argument to thread function
0, // use default creation flags
&ThreadIdArray[i]); // returns the thread identifier
if (hThreadArray[i] == NULL)
{
ret = EXIT_FAILURE;
}
sector_offset += sectors_per_thread;
}
} // End of main thread creation loop.
// Wait until all threads have terminated.
DWORD result = WaitForMultipleObjects(MAX_Threads, hThreadArray, TRUE, INFINITE);
// Free all the dynamically allocated structures
}
}
return ret;
}
答案 0 :(得分:4)
你的观点2并非如此。
对于常规磁盘,最佳访问模式是大顺序读取,而不必由于多个线程争用磁盘时间而来回跳过(使其在搜索中浪费时间);此外,顺序读取与操作系统和磁盘本身完成的预读缓存相得益彰。
您可能希望多线程只是处理您从磁盘读取的数据,但鉴于在现代PC上您的处理器比这个任务的磁盘更快,您的任务将是IO绑定。如果我是你,我只需要一个线程在大块中执行异步顺序IO(一次考虑4 MB数据),在等待磁盘执行其操作时加密数据。另一种可能性是使用两个线程(一个执行IO,一个加密)和同步IO执行基本相同的操作。