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.
A documentação no SDK do Windows para as funções AllocSelector e FreeSelector não Mencione que eles podem alocar e livre seletores vários. Cada função usa o limite (comprimento) do seletor passado para ele para determinar quantos seletores para alocar ou liberar. Este artigo descreve como AllocSelector aloca um ou mais seletores e como FreeSelector libera seletores. Ela também descreve o que você deve saber para usar essas duas funções corretamente. A documentação deve incluir todas as informações fornecidas neste artigo.
AllocSelector(UINT uSelector) aloca um novo seletor ou matriz de seletores lado a lado e copiará o endereço base, limite (comprimento) e direitos de acesso de uSelector selector(s) novo. Se o limite de uSelector é menor ou igual a 64 K, um seletor único é alocado. Se o limite de uSelector for maior que 64 K, uma matriz de seletores lado a lado é alocada de modo que cada seletor aponta para uma parte de 64 K do limite de uSelector.
Se uSelector for NULL, AllocSelector aloca um seletor único e não inicializado completamente. O seletor não pode ser usado até seu endereço base, limite (comprimento) e direitos de acesso foram definidos. Para definir os direitos de acesso de um seletor unitialized, você deve chamar a função de interface de modo protegido DOS (DPMI) definir descritor Access Rights (0x09). Além disso, você deve definir no seletor de bits de tabela e bits de privilégio, usando uma máscara de bit a bit ou de 0x0007 para definir os bits de três mais baixa ordem do seletor.
Você deve copiar um seletor existente em vez de alocar um seletor não inicializado porque é mais fácil permitir que AllocSelector conjunto bits de controle de acesso do seletor de recém-criado. Depois de criar uma cópia de um seletor existente, use SetSelectorLimit e SetSelectorBase para fazer a cópia que aponte para o local desejado.
Seletores alocados pelo AllocSelector devem ser liberadas pelo FreeSelector porque o sistema não controlar ou gerenciá-los automaticamente.
FreeSelector(UINT uSelector) libera um seletor único ou uma matriz de seletores lado a lado dependendo o limite de uSelector. Libera um seletor para cada parte de 64 K o limite de uSelector. A matriz de seletores lado a lado que está sendo liberado ou seletor deve tiverem sido alocado anteriormente pelo AllocSelector. Além disso, o limite de uSelector deve ser o mesmo que o seletor usado como um parâmetro na chamada para AllocSelector.
aviso que o endereço base do seletor de cada sucessivas inicia 64 K de endereço base do seletor de anterior e tem um limite que é 64 K menor do que o seletor anterior. O que realmente faz esses seletores lado a lado é que eles sejam contíguos na tabela de descritor de 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 1 Sel é usado para criar um ponteiro para o bloco grande. Como você incrementa através do bloco, o compilador gera o código correto para alternar do Sel 1 para 2 Sel para Sel 3 a 4 Sel automaticamente. O código listado na seção "Código exemplo dois" deste artigo demonstra isso.
Este exemplo mostra como alocar exatamente um seletor de dados. Segmentos de código no código de 16 bits sempre são menos de 64 K, portanto, você pode garantir que você não alocar seletores vários alocando uma cópia de um seletor de código e convertê-lo em um seletor 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.
Este exemplo mostra como automaticamente alocar uma matriz de seletores lado a lado que aponta para uma região especificada de memória e obter um ponteiro enorme da matriz seletor:
// 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;
}
Tenha em mente o seguinte ao usar as sugestões deste artigo:
Alocar seletores não aloca, na verdade, qualquer memória. Ele simplesmente cria um ponteiro que pode ser usado para acessar a memória existente (memória anteriormente alocado ou fornecido por um dispositivo de hardware de memória mapeada). Não confunda seletores alocar com alocação de memória.
Seletores de alias (aponte para) um bloco de memória alocado pelo Windows não são atualizados se o bloco de memória for movido. Para garantir que o bloco de memória não é movido, chame GlobalFix nele antes de criar um seletor que aliases-lo. No entanto, se o seletor alocado aponta para memória fornecida por um dispositivo de hardware, não é necessário chamar GlobalFix porque a memória do dispositivo não foi alocada pelo Windows.
O Gerenciador de memória do Windows não controlar de quais tarefas alocada seletores com essas funções, portanto, você deve garantir que a tarefa libera-los corretamente. Em particular, verifique se que ele não liberar mais ou menos seletores que alocado. O código de exemplo neste artigo demonstra o modo adequado para alocar e liberar seletores com essas funções.
Não alocar grandes números de seletores é recomendado porque seletores são um recurso limitado.
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 traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes 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/
)
Aviso de Isenção de Responsabilidade sobre Conteúdo do KB Aposentado
Este artigo trata de produtos para os quais a Microsoft não mais oferece suporte. Por esta razão, este artigo é oferecido "como está" e não será mais atualizado.
Quanto esforço foi necessário para seguir os procedimentos deste artigo?
Muito baixo
Baixo
Moderado
Alto
Muito alto
Diga-nos o porque e o que podemos fazer para melhorar esta informação
Obrigado! Seus comentários são usados para nos ajudar a aperfeiçoar o conteúdo de suporte. Para obter mais opções de ajuda, visite a Home Page de Ajuda e Suporte.