查看文章
 
TrueCrypt分析(4)
2010年07月21日 14:46

//如果是加密的话就用到了EncryptionThreadPoolDoWork (EncryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci);
看下这个函数实现,这里写的很精髓
void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo)
{
uint32 fragmentCount;
uint32 unitsPerFragment;
uint32 remainder;

byte *fragmentData;
uint64 fragmentStartUnitNo;

EncryptionThreadPoolWorkItem *workItem;
EncryptionThreadPoolWorkItem *firstFragmentWorkItem;
//加密的长度除512
if (unitCount == 0)
   return;

if (!ThreadPoolRunning || unitCount == 1) //没有启用加密解密线程就直接做加密解密了
{
   switch (type)
   {
   case DecryptDataUnitsWork:
    DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo);
    break;

   case EncryptDataUnitsWork:
    EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo);
    break;

   default:
    TC_THROW_FATAL_EXCEPTION;
   }

   return;
}

if (unitCount <= ThreadCount)
{
   fragmentCount = unitCount;
   unitsPerFragment = 1;
   remainder = 0;
}
else
{
   /* Note that it is not efficient to divide the data into fragments smaller than a few hundred bytes.
   The reason is that the overhead associated with thread handling would in most cases make a multi-threaded
   process actually slower than a single-threaded process. */

   fragmentCount = ThreadCount;
   unitsPerFragment = unitCount / ThreadCount;
   remainder = unitCount % ThreadCount;

   if (remainder > 0)
    ++unitsPerFragment;
}

fragmentData = data;
fragmentStartUnitNo = startUnitNo->Value;

TC_ACQUIRE_MUTEX (&EnqueueMutex); //多线程同步
firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition];

while (GetWorkItemState (firstFragmentWorkItem) != WorkItemFree)
{
   TC_WAIT_EVENT (WorkItemCompletedEvent);
}

firstFragmentWorkItem->OutstandingFragmentCount = fragmentCount;
//这里假设fragmentCount ==1 unitCount== 3 ThreadCount==2 unitsPerFragment==1
while (fragmentCount-- > 0)
{
   workItem = &WorkItemQueue[EnqueuePosition++];
   if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) //大于等于最大线程数的2倍
    EnqueuePosition = 0;

   while (GetWorkItemState (workItem) != WorkItemFree)
   {
    TC_WAIT_EVENT (WorkItemCompletedEvent);
   }

   workItem->Type = type;
   workItem->FirstFragment = firstFragmentWorkItem;

   workItem->Encryption.CryptoInfo = cryptoInfo;
   workItem->Encryption.Data = fragmentData;
   workItem->Encryption.UnitCount = unitsPerFragment;
   workItem->Encryption.StartUnitNo.Value = fragmentStartUnitNo;

    fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE;
   fragmentStartUnitNo += unitsPerFragment;

   if (remainder > 0 && --remainder == 0)
    --unitsPerFragment;

   SetWorkItemState (workItem, WorkItemReady);
   TC_SET_EVENT (WorkItemReadyEvent);
}

TC_RELEASE_MUTEX (&EnqueueMutex);

TC_WAIT_EVENT (firstFragmentWorkItem->ItemCompletedEvent);
SetWorkItemState (firstFragmentWorkItem, WorkItemFree);
TC_SET_EVENT (WorkItemCompletedEvent);
}
这里把加密解密放入队列后之前驱动入口函数根据cpu个数开的EncryptionThreadProc线程就派上用场了
简单看看函数实现
//不断去工作项中取出信息
static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
{
EncryptionThreadPoolWorkItem *workItem;

while (!StopPending)
{
   TC_ACQUIRE_MUTEX (&DequeueMutex); //分配一个快速互斥体。多线程同步

   workItem = &WorkItemQueue[DequeuePosition++];

   if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE)
    DequeuePosition = 0;

   while (!StopPending && GetWorkItemState (workItem) != WorkItemReady)
   {
    TC_WAIT_EVENT (WorkItemReadyEvent);
   }

   SetWorkItemState (workItem, WorkItemBusy);

   TC_RELEASE_MUTEX (&DequeueMutex); //释放这个快速互斥体

   if (StopPending)
    break;

   switch (workItem->Type)
   {
   case DecryptDataUnitsWork:
    DecryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
    break;

   case EncryptDataUnitsWork:
    EncryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
    break;

   case DeriveKeyWork:
    switch (workItem->KeyDerivation.Pkcs5Prf)
    {
    case RIPEMD160:
     derive_key_ripemd160 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

    case SHA512:
     derive_key_sha512 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

    case WHIRLPOOL:
     derive_key_whirlpool (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

    case SHA1:
     derive_key_sha1 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

    default:  
     TC_THROW_FATAL_EXCEPTION;
    }

    InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE);
    TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent);
   
    if (InterlockedDecrement (workItem->KeyDerivation.OutstandingWorkItemCount) == 0)
     TC_SET_EVENT (*workItem->KeyDerivation.NoOutstandingWorkItemEvent);

    SetWorkItemState (workItem, WorkItemFree);
    TC_SET_EVENT (WorkItemCompletedEvent);
    continue;

   default:
    TC_THROW_FATAL_EXCEPTION;
   }

   if (workItem != workItem->FirstFragment)
   {
    SetWorkItemState (workItem, WorkItemFree);
    TC_SET_EVENT (WorkItemCompletedEvent);
   }

   if (InterlockedDecrement (&workItem->FirstFragment->OutstandingFragmentCount) == 0)
    TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent);
}

#ifdef DEVICE_DRIVER
PsTerminateSystemThread (STATUS_SUCCESS);
#else
_endthreadex (0);
    return 0;
#endif
}

整个流程大体就这样了,多线程的处理十分值得学习啊


类别:默认分类||添加到搜藏 |分享到i贴吧|浏览(379)|评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu