Pergunta

Gostaria de mapear um arquivo na memória usando a função MMAP e gostaria de saber se a quantidade de memória virtual na plataforma atual é suficiente para mapear um arquivo enorme. Para um sistema 32, não posso mapear o arquivo maior que 4 GB.
Gostaria std::numeric_limits<size_t>::max() Dê -me a quantidade de memória endereçável ou existe algum outro tipo que eu devo testar (OFF_T ou outra coisa)?

Como Lie Ryan apontou em seu comentário, a "memória virtual" aqui é mal utilizada. A questão, no entanto, é mantida: existe um tipo associado a um ponteiro e possui o valor máximo que define o limite superior do que você pode se vestir no seu sistema. O que é esse tipo? É tamanho_t ou talvez ptrdiff_t?

Foi útil?

Solução

size_t é necessário apenas ser grande o suficiente para armazenar o maior objeto contíguo possível. Este poderia não ser o mesmo que o tamanho do espaço de endereço (em sistemas com um modelo de memória segmentada, por exemplo)

No entanto, em plataformas comuns com um espaço de memória plana, os dois são iguais e, assim, você pode se safar usando o uso size_t Na prática, se você conhece a CPU alvo.

De qualquer forma, isso realmente não diz nada útil. Claro, uma CPU de 32 bits tem um espaço de memória de 4 GB e, portanto, size_t é um número inteiro não assinado de 32 bits. Mas isso não diz nada sobre o quanto você pode alocar. Alguma parte do espaço de memória é usada pelo sistema operacional. E algumas peças já são usadas por seu próprio aplicativo: para mapear o executável na memória (bem como quaisquer bibliotecas dinâmicas que ele possa usar), para a pilha de cada thread, alocou a memória na pilha e assim por diante.

Então não, truques como pegar o tamanho de size_t diz um pouco sobre o espaço de endereço que você está executando, mas nada muito utilizável. Você pode perguntar ao sistema operacional quanta memória está em uso por seu processo e outras métricas, mas, novamente, isso realmente não ajuda muito. É possível que um processo use apenas alguns megabytes, mas isso se espalhe por tantas pequenas alocações que é impossível encontrar um bloco contíguo de memória maior que 100 MB, digamos. E assim, em uma máquina de 32 bits, com um processo que usa quase nenhuma memória, é improvável que você faça essa alocação. (E mesmo se o sistema operacional tivesse um mágico WhatIsTheLargestPossibleMemoryAllocationICanMake() API, isso ainda não te ajudaria. Isso te diria o que você precisava de um momento atrás. Você não tem garantia de que a resposta ainda seja válida quando você tentou mapear o arquivo.

Então, realmente, o melhor que você pode fazer é tentar Para mapear o arquivo e ver se ele falha.

Outras dicas

Olá, você pode usar o GlobalMemoryStatusex e o VirtualQueryEx se você codificar no Win32

O problema é que o tamanho de um ponteiro não diz nada sobre quanto desse "espaço de endereço" está realmente disponível para você, ou seja, pode ser mapeado como um único pedaço contíguo.

É limitado por:

  • o sistema operacional. Ele pode optar por disponibilizar apenas um subconjunto do intervalo de endereços teoricamente possíveis, porque a memória mapeável é necessária para fins de propriedade do OS (como, digamos, tornando visível o quadro de quadros da placa gráfica e, é claro, para uso pelo OS em si próprio ).
  • limites configuráveis. No Linux / Unix, o comando "ulimit" resp. A chamada Setrlimit () permite restringir o tamanho máximo do espaço de endereço de um aplicativo de várias maneiras, e o Windows possui opções semelhantes através dos parâmetros do registro.
  • a história do aplicativo. Se o aplicativo usar amplamente o mapeamento da memória, o espaço de endereço poderá fragmentar o tamanho máximo de endereços virtuais contíguos "disponíveis".
  • a plataforma de hardware. Algumas CPUs têm espaços de endereço com "buracos"; an example of that is 64bit x86 where pointers are only valid if they're between 0x0..0x7fffffffffff or 0xffff000000000000 and 0xffffffffffffffff. Ou seja, você tem 2x128tb em vez do 16Eb completo. Pense nisso como ponteiros "assinados" de 48 bits ...

Por fim, não confunda "memória disponível" e "espaço de endereço disponível". Há uma diferença entre fazer um malloc (algum bigsize) e um mmap (..., alguma coisa, ...) porque o primeiro pode exigir a disponibilidade de memória física para acomodar a solicitação, enquanto este geralmente requer apenas a disponibilidade de uma grande quantidade suficiente intervalo de endereços.

Para plataformas UNIX, parte da resposta é usar getrlimit (rlimit_as), pois isso fornece o limite superior para a invocação atual do seu aplicativo - como dito, o usuário e/ou o administrador podem configurar isso. Você está garantido que qualquer tentativa de MMAP maior do que isso falhará.

A sua pergunta reformulada "Limite superior do que você pode se divertir no seu sistema" é um pouco enganador; É a arquitetura de hardware específica. Existem arquiteturas de 64 bits por aí (x64, SPARC) cujo MMU alegremente permite (uintptr_t) (-1) como endereço válido, ou seja, você pode mapear algo na última página de um espaço de endereço de 64 bits. Se o sistema operacional permite que um aplicativo faça isso ou não seja novamente uma pergunta totalmente diferente ...

Para aplicativos de usuário, a "alta marca" não é (sempre) a-priori fixada. É sintonizável em EG Solaris ou Linux. É aí que entra o getrlimit (rlimit_as).

Observe que, novamente, por especificação, não haveria nada para impedir um design (estranho) do sistema operacional para escolher, por exemplo, colocando pilhas de aplicativos e pilhas em endereços "baixos" ao colocar código em endereços "altos", em uma plataforma com orifícios de espaço de endereço . Você precisaria de ponteiros completos de 64 bits lá, não podem torná -los menores, mas pode haver um número arbitrário de intervalos "inacessíveis / inválidos" que nunca são disponibilizados ao seu aplicativo.

Podes tentar sizeof(int*). Isso lhe dará o comprimento (em bytes) de um ponteiro na plataforma de destino. Assim, você pode descobrir o tamanho do espaço endereçável.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top