Artigo: 132005 - Última revisão: sábado, 6 de Novembro de 1999 - Revisão: 1.0

DOCERR: AllocSelector & FreeSelector documentação incompletos

Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.

Nesta página

Expandir tudo | Reduzir tudo

Sumário

A documentação no Windows SDK para as funções AllocSelector e FreeSelector não mencionar que podem atribuir e libertar selectores vários. Cada função utiliza o limite (comprimento) do selector lhe é transmitido para determinar quantas selectores para atribuir ou libertar. Este artigo descreve como AllocSelector atribui um ou mais selectores e como FreeSelector liberta selectores. Também descreve o que deve saber para utilizar correctamente estas duas funções. A documentação deve incluir todas as informações fornecidas neste artigo.

Mais Informação

AllocSelector (UINT uSelector)

AllocSelector(UINT uSelector) atribui um novo selector ou matriz de selectores em mosaico e copia o endereço base, limite (comprimento) e direitos de acesso de uSelector para selector(s) novo. Se o limite de uSelector for menor ou igual a 64 K, um selector único é atribuído. Se o limite de uSelector for maior do que 64 K, é atribuída uma matriz de selectores em mosaico que cada selector aponta para uma parte de 64 K o limite de uSelector.

Se uSelector for NULL, AllocSelector atribui um selector único, não totalmente inicializado. É possível utilizar o selector até que o endereço base, limite (comprimento) e direitos de acesso foram definidos. Para definir os direitos de acesso de um selector unitialized, tem de chamar a função de direitos de acesso de descritor de conjunto DOS protegido modo de interface (DPMI) (0 x 09). Para além disso, tem de definir no selector de tabela bit e privilégios bits utilizando uma máscara de bits ou de 0x0007 para definir os bits de três ordem mais baixa do selector.

Deve copiar uma selecção existente em vez de atribuir um selector não inicializado porque é mais fácil de permitir AllocSelector definir bits de controlo de acesso no selector recém-criado. Depois de criar uma cópia de um selector existente, utilize SetSelectorLimit e SetSelectorBase para efectuar a cópia apontar para a localização pretendida.

Selectores atribuídos pelo AllocSelector tem ser libertadas pelo FreeSelector porque o sistema não controlar ou geri-las automaticamente.

FreeSelector (UINT uSelector)

FreeSelector(UINT uSelector) liberta um selector único ou uma matriz de selectores em mosaico consoante o limite de uSelector. Liberta um selector de cada parte de 64 K o limite de uSelector. O selector ou matriz de selectores em mosaico a ser libertada tem tiverem sido atribuído anteriormente por AllocSelector. Para além disso, o limite de uSelector tem de ser a mesma que o selector utilizado como um parâmetro na chamada para AllocSelector.

Matriz de exemplo de selectores em mosaico

Uma matriz de exemplo de selectores em mosaico é semelhante a este (partindo do princípio que o selector passado para AllocSelector tem um limite de 256 K):
  Sel 1     Sel 2      Sel 3      Sel 4

   0         64K       128K       192K       256K
   +----------+----------+----------+----------+
   |          |          |          |          |
   +----------+----------+----------+----------+
   |          |          |          |--------->| (Limit = 64K)
   |          |          |-------------------->| (Limit = 128K)
   |          |------------------------------->| (Limit = 192K)
   |------------------------------------------>| (Limit = 256K)
				
aviso de que endereço base cada selector sucessivas inicia 64 K do endereço base o selector anterior e tem um limite que é 64 K menor que o selector anterior. O que faz realmente estes selectores em mosaico é que eles são contíguos na tabela descritor local (LDT). Por exemplo, se Sel 1 tem um valor de 0x97, em seguida, Sel 2 será 0x9F, Sel 3 será 0xA7 e Sel 4 será 0xAF.

Apenas Sel 1 é utilizado para criar um ponteiro para o bloco grande. Como aumentar através do bloco, o compilador gera o código correcto para alternar entre Sel 1 e 2 Sel para 3 Sel para 4 Sel automaticamente. O código listado na secção "Exemplo de código dois" deste artigo demonstra este.

Código de exemplo um

Este exemplo mostra como atribuir exactamente um selector de dados. Segmentos de código no código de 16 bits são sempre menos de 64 K, pelo que pode garantir que não a atribuir múltiplos selectores por atribuindo uma cópia de um selector de código e convertê-la para um selector de dados:
     UINT codeSelector, dataSelector;

   _asm {
        mov ax, cs
        mov codeSelector, ax
        }

   dataSelector = AllocSelector(codeSelector);
   if (!dataSelector)
      return NULL;

   // Change dataSelector from a code selector into a data selector
   if (PrestoChangoSelector(codeSelector, dataSelector))
      {
      // Set the desired base address and limit
      SetSelectorBase(dataSelector, dwLinearBase);
      DPMISetSelectorLimit(dataSelector, dwLimit);
      }
   else
      {
      // If you get here, you couldn't change dataSelector so you need
      // to free it because you can't use it as a code selector
      FreeSelector(dataSelector);
      return NULL;
      }

   // You now have a single data selector. Use it, and then free it by
   // calling FreeSelector.
				

Exemplo de código Two

Este exemplo mostra como automaticamente atribuir uma matriz de selectores em mosaico que aponta para uma região especificada de memória e obter um ponteiro de grandes dimensões da matriz selector:
    // The application creates, uses, and frees a huge pointer here
   char __huge * hpMem;

   hpMem = CreateHugePointer (dwBaseAddress, dwLength);

   // hpMem now points to a region of pre-allocated memory, such
   // as a memory-mapped hardware device's buffer. Use it as you
   // would any pointer.

   FreeHugePointer (hpMem);

// The following three functions show how to allocate an array
// of tiled selectors that point to a specified region of memory.

/*--------------------------------------------------------------
  This function creates a huge pointer with the proper number
  of selectors to access physical memory. The huge pointer may be
  used by C or C++ code. dwLinearBase is a 32-bit linear address,
  and dwLength is the number of bytes that the huge pointer will
  be able to access. This function returns the huge pointer if it
  succeeds, or it returns NULL if it fails.
--------------------------------------------------------------*/ 

void __huge * CreateHugePointer (DWORD dwLinearBase,
                                 DWORD dwLength)
   {
   WORD tempSelector = NULL;
   WORD codeSelector = NULL;
   WORD dataSelector = NULL;
   DWORD dwLimit;

   /*
     A segment's limit is defined as the last accessible offset in
     the segment. Because the limit is the last accessible offset, it
     is the desired length of the segment minus 1. For example, if
     you want a 64K segment, then you need a limit of 0xFFFF, not
     0x10000, because the segment contains byte offsets 0 to 0xFFFF.
     Note that a segment with a limit of 0 is actually a single byte
     in length. Thus, this function considers a length of zero
     invalid.
   */ 
   if (dwLength == 0)
      return NULL;

   dwLimit = dwLength - 1;
   /*
     Allocate a single temporary selector by making a copy of the
     code segment selector and converting the copy to a data
     selector. Code segments are always less than or equal to
     64K in length, so you are guaranteed to get a single temporary
     selector and be sure to free a single selector.

     Once you have the temporary selector, set its base address and
     limit to the desired values, which may be larger than 64K.
     Because the memory must be accessed by 16-bit code, you must
     allocate an array of tiled selectors. The temporary selector is
     used to force AllocSelector to allocate an array of the proper
     number of tiled selectors, each with the proper base and limit.
     Then you can free the single temporary selector.

     If you fail anywhere along the way, clean up whatever has been
     done, and return NULL.
   */ 

   _asm {
        mov ax, cs
        mov codeSelector, ax
        }

   tempSelector = AllocSelector (codeSelector);
   if (!tempSelector)
      return NULL;

   /*
     If you can successfully change the tempSelector into a
     data selector, set its base address and limit to the
     desired base and limit, and then allocate the real selector
     array. Otherwise, prepare to return NULL.

     SetSelectorLimit does not handle the granularity bit of
     selectors properly, which limits its usefulness only to ranges
     of addresses less than 1MB in length. This function calls
     DPMISetSelectorLimit, a function defined below, to overcome
     this limitation and allow you to create arrays of tiled
     selectors that can access more than 1MB.
   */ 
   if (PrestoChangoSelector (codeSelector, tempSelector))
      {
      SetSelectorBase(tempSelector, dwLinearBase);
      DPMISetSelectorLimit(tempSelector, dwLimit);
      dataSelector = AllocSelector(tempSelector);
      }
   else
      dataSelector = NULL;

   // Clean up temp selector
   DPMISetSelectorLimit(tempSelector, 0L);
   FreeSelector(tempSelector);

   // dataSelector will be NULL if it could not be allocated
   // successfully, making this function return NULL.
   return (void __huge *)MAKELONG(0, dataSelector);
   }

/*--------------------------------------------------------------
  This function frees pointers allocated by CreateHugePointer.
  It correctly frees all tiled selectors created to access the
  block of physical memory. It is very important that you call
  this on all pointers created by CreateHugePointer and that you
  do not call this function on pointers allocated by any way
  other than using CreateHugePointer.
--------------------------------------------------------------*/ 

void FreeHugePointer (void __huge * hPtr)
   {
   if (hPtr)
      FreeSelector (HIWORD(hPtr));
   }

/*--------------------------------------------------------------
  This function sets the limit of a selector using DPMI Function
  0008h (Set Segment Limit). This function is necessary if the
  segment size is greater than 1 MB because the Windows
  SetSelectorLimit() API function does not correctly set selector
  limits greater than 1 MB.

  Segments that are larger than 1MB are actually page granular,
  meaning that in the descriptor, the limit field is actually
  stored as the number of 4K pages rather than bytes. When you
  specify a limit greater than 1MB, this function rounds it up
  to the nearest page boundary.

  No matter the size of the segment, this function always accepts
  selector limits in number of bytes, never pages. The conversion
  between bytes and pages is handled internally.

  Note that this function takes a segment limit, which is one less
  than the number of bytes in the segment.
--------------------------------------------------------------*/ 

   BOOL DPMISetSelectorLimit (UINT selector, DWORD dwLimit)
   {
      BOOL bRetVal=TRUE;

   // If the limit is >= 1MB, we need to make the limit a mulitple
   // of the page size or DPMISetSelectorLimit will fail.

      if( dwLimit >= 0x100000 )
         dwLimit |= 0x0FFF;

      __asm
      {
         mov  ax, 0008h
         mov  bx, selector
         mov  cx, word ptr [dwLimit+2]
         mov  dx, word ptr [dwLimit]
         int  31h
         jnc  success
         mov  bRetVal, FALSE
       success:
      }
      return bRetVal;
   }
				

Quatro avisos para manter em Mind

Tenha em atenção o seguinte quando utilizar as sugestões deste artigo:

  • Atribuir selectores não atribui, de facto, qualquer memória. Apenas cria um apontador que pode ser utilizado para aceder a memória existente (memória anteriormente atribuídos ou fornecidos por um dispositivo de hardware mapeados pela memória). Não confunda selectores ao atribuir com a atribuição de memória.
  • Selectores esse alias (aponte para) um bloco de memória atribuído pelo Windows não são actualizadas se o bloco de memória for movido. Para garantir que o bloco de memória não for movido, chamar GlobalFix nele antes de criar um selector que aliases-lo. No entanto, se o selector atribuído apontar para memória fornecida por um dispositivo de hardware, não é necessário chamar GlobalFix uma vez que de memória o dispositivo não foi atribuída pelo Windows.
  • O Gestor de memória do Windows não manter um registo de qual a tarefa atribuída selectores com estas funções, pelo que deve certificar-se de que o da tarefa liberta-o correctamente. Em particular, certifique-se não libertar selectores de mais ou menos do que atribuir. O código de exemplo neste artigo demonstra a forma correcta de atribuir e libertar selectores com estas funções.
  • Não atribuir um número elevado de selectores é aconselhada porque selectores são um recurso limitado.

A informação contida neste artigo aplica-se a:
  • Microsoft Windows Software Development Kit 3.1
Palavras-chave: 
kbmt kb16bitonly kbdocerr KB132005 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 132005  (http://support.microsoft.com/kb/132005/en-us/ )
Retired KB ArticleExclusão de Responsabilidade para Conteúdo sem Suporte na KB
Este artigo foi escrito sobre produtos para os quais a Microsoft já não fornece suporte. Por conseguinte, este artigo é oferecido "tal como está" e deixará de ser actualizado.