none
DLL única vez na memória, tem como? RRS feed

  • Pergunta

  • Preciso de uma ajuda para construir uma DLL que seja única na memória!
    bem deixa eu explicar:
    Preciso fazer uma DLL que dois programas diferentes possam instanciar a mesma, mas que os Objetos sejam os mesmos!
    ex:
     
    Programa1 ---->>>  DLL (obj)  <<<---- Programa2
     
    O que quero é que o programa 1 e o 2 usam o mesmo obj, se o programa 1 fizer obj.nome = "rafael" o Programa 2 vai fazer obj.ImprimeNome(); e tem que sair Rafael.
     
    Não consigo fazer isso! :( toda vez que eu vou usar a DLL ele reserva um novo espaço de memória para cada programa!
     
    Alguém pode me ajudar???
     
    Obrigado,
    Rafael
    quarta-feira, 21 de junho de 2006 14:00

Respostas

  • Olá Rafael,

    Para isolar as aplicações, os sistemas operacionais modernos utilizam memória virtual de forma que cada processo possue seu próprio espaço de endereçamento, que lhe parece dar controle total sobre a memória da máquina, mas que é traduzido em endereços físicos pelo próprio hardware, contando com uma certa ajuda do SO para a configuração desse esquema. Portanto cada processo tem sua prórpria memória.

    Uma DLL existe como uma entidade diferente no disco, mas depois de carregada por um processo, ela perde quase toda sua identidade como uma entidade diferente. É apenas mais um conjunto de páginas de código e dados naquele espaço de endereçamento. Assim uma .lib perde sua identidade dentro do .exe, uma .dll sofre o mesmo efeito depois de linkada. A única difereça é que no último caso a linkedição ocorre em runtime, por isso é chamada dinâmica (DLL = dynamic-link libraries).

    Ora, se os processos são isolados e a dll é apenas mais páginas de código e dados em um processo, com quase nada em especial, então esses também são isolados! Isso pode parecer ruim no seu cenário, mas é essencial para o conceito de reutilização. Por exemplo, você pode ter um cenário semelhante ao seu em que os processos A, B, C e D usam a mesma DLL, mas você quer que A e B conversem entre si e que C e D mantenham a sua comunicação isolada do outro par. Portanto, compartilhar os dados de uma DLL não teria sido um bom design genérico para um sistema operacional.

    O que você precisa é usar funcionalidades de InterProcess Communication (IPC). Você pode escolher entre vários, por exemplo named pipes, memory mapped files, sockets, etc.

    Apenas para complementar: Repare que esse comportamento de DLLs não é nada diferente do que você já está acostumado como EXEs. Se você iniciar duas instância de um executável, cada um terá sua própria cópia das variáveis estáticas, por exemplo.

    Também como complemento, é interessante notar que há muitas otimizações de performance de espaço e tempo em todo esse processo de carga da mesma DLL por diferentes processos. Por exemplo, se as DLLs não forem reposicionadas na memória porque colidem com algo diferente naquele processo, todas as páginas readonly podem ser compartilhadas fisicamente; isto é, aquela tradução entre memória virtual e física resulta na mesma posição de memória. O código estará em páginas que são readonly, portanto o código será compartilhado entre todos os processos, isto é, depois do primeiro gasta-se menos tempo com a carga, e não se perde memória para cada "cópia" da dll carregada!

    Outra otimização é com relação às páginas de dados em si. Todas as páginas que podem ser escritas podem se beneficiar da feature copy-on-write. Isto é, só ahverá duplicação desses dados se um processo tentar realmente escrever, enquanto ele estiver apenas lendo também há compartilhamento.

    Repare também que para compartilhar dados entre dois processos com segurança é necessário estar usando mecanismos de sincronismo. Não seria possível fazer com que DLLs compartilhassem dados entre processos sem conhecimento do programador por causa disso. Por exemplo, suponha que sua dll possua duas váriaveis estáticas:

    static int s_valor;
    static bool s_valorMaiorQueZero;

    E uma funcao:

    void AtualizarValor(int valor)
    {
        s_valor = valor;
        s_valorMaiorQueZero = valor > 0;
    }

    Com os processos chamando essa função simultaneamente e sem cuidado com múltiplas threads, o seguinte poderia acontecer:

    Instante 0: Processo A: AtualizarValor(1)
    Instante 1: Processo A: s_valor = 1
    Instante 2: Processo B: AtualizarValor(-1)
    Instante 3: Processo B: s_valor = -1
    Instante 4: Processo B: s_maiorQueZero = false
    Instante 5: Processo A: s_maiorQueZero = true

    No final, teríamos s_valor = -1 e s_maiorQueZero = true, o que seria inconsistente!

    Espero que essas informações ajudem.

    quarta-feira, 21 de junho de 2006 23:25

Todas as Respostas

  • Olá Rafael,

    Para isolar as aplicações, os sistemas operacionais modernos utilizam memória virtual de forma que cada processo possue seu próprio espaço de endereçamento, que lhe parece dar controle total sobre a memória da máquina, mas que é traduzido em endereços físicos pelo próprio hardware, contando com uma certa ajuda do SO para a configuração desse esquema. Portanto cada processo tem sua prórpria memória.

    Uma DLL existe como uma entidade diferente no disco, mas depois de carregada por um processo, ela perde quase toda sua identidade como uma entidade diferente. É apenas mais um conjunto de páginas de código e dados naquele espaço de endereçamento. Assim uma .lib perde sua identidade dentro do .exe, uma .dll sofre o mesmo efeito depois de linkada. A única difereça é que no último caso a linkedição ocorre em runtime, por isso é chamada dinâmica (DLL = dynamic-link libraries).

    Ora, se os processos são isolados e a dll é apenas mais páginas de código e dados em um processo, com quase nada em especial, então esses também são isolados! Isso pode parecer ruim no seu cenário, mas é essencial para o conceito de reutilização. Por exemplo, você pode ter um cenário semelhante ao seu em que os processos A, B, C e D usam a mesma DLL, mas você quer que A e B conversem entre si e que C e D mantenham a sua comunicação isolada do outro par. Portanto, compartilhar os dados de uma DLL não teria sido um bom design genérico para um sistema operacional.

    O que você precisa é usar funcionalidades de InterProcess Communication (IPC). Você pode escolher entre vários, por exemplo named pipes, memory mapped files, sockets, etc.

    Apenas para complementar: Repare que esse comportamento de DLLs não é nada diferente do que você já está acostumado como EXEs. Se você iniciar duas instância de um executável, cada um terá sua própria cópia das variáveis estáticas, por exemplo.

    Também como complemento, é interessante notar que há muitas otimizações de performance de espaço e tempo em todo esse processo de carga da mesma DLL por diferentes processos. Por exemplo, se as DLLs não forem reposicionadas na memória porque colidem com algo diferente naquele processo, todas as páginas readonly podem ser compartilhadas fisicamente; isto é, aquela tradução entre memória virtual e física resulta na mesma posição de memória. O código estará em páginas que são readonly, portanto o código será compartilhado entre todos os processos, isto é, depois do primeiro gasta-se menos tempo com a carga, e não se perde memória para cada "cópia" da dll carregada!

    Outra otimização é com relação às páginas de dados em si. Todas as páginas que podem ser escritas podem se beneficiar da feature copy-on-write. Isto é, só ahverá duplicação desses dados se um processo tentar realmente escrever, enquanto ele estiver apenas lendo também há compartilhamento.

    Repare também que para compartilhar dados entre dois processos com segurança é necessário estar usando mecanismos de sincronismo. Não seria possível fazer com que DLLs compartilhassem dados entre processos sem conhecimento do programador por causa disso. Por exemplo, suponha que sua dll possua duas váriaveis estáticas:

    static int s_valor;
    static bool s_valorMaiorQueZero;

    E uma funcao:

    void AtualizarValor(int valor)
    {
        s_valor = valor;
        s_valorMaiorQueZero = valor > 0;
    }

    Com os processos chamando essa função simultaneamente e sem cuidado com múltiplas threads, o seguinte poderia acontecer:

    Instante 0: Processo A: AtualizarValor(1)
    Instante 1: Processo A: s_valor = 1
    Instante 2: Processo B: AtualizarValor(-1)
    Instante 3: Processo B: s_valor = -1
    Instante 4: Processo B: s_maiorQueZero = false
    Instante 5: Processo A: s_maiorQueZero = true

    No final, teríamos s_valor = -1 e s_maiorQueZero = true, o que seria inconsistente!

    Espero que essas informações ajudem.

    quarta-feira, 21 de junho de 2006 23:25
  • Falando unicamente em termos práticos há várias formas de resolver isso dependendo do seu cenário.

    Você pode por exemplo implementar um objeto como componente COM de instância única, usando um ActiveX EXE, e o padrão singleton.

    Pode usar sharedMemory, ou outro mecanismo IPC se a idéia é apenas compartilhar dados.

    { }s

    Guima

     

    sexta-feira, 30 de junho de 2006 12:40
  • Tem algum exemplo de como posso fazer isso! ??

    Eu ja fiz o que precisava em sock! mas queria usar a memoria mesmo! esse de usar o Componete COM de instancia unica eu gostei :)

    Vc tem algum exemplo???

    pode mandar em rfl_souza@hotmail.com

    Obrigado,

    Rafael

    sexta-feira, 30 de junho de 2006 12:55
  •  Roberto Adlich dos Santos - MSFT wrote:

    Olá Rafael,

    Para isolar as aplicações, os sistemas operacionais modernos utilizam memória virtual de forma que cada processo possue seu próprio espaço de endereçamento, que lhe parece dar controle total sobre a memória da máquina, mas que é traduzido em endereços físicos pelo próprio hardware, contando com uma certa ajuda do SO para a configuração desse esquema. Portanto cada processo tem sua prórpria memória.

    Uma DLL existe como uma entidade diferente no disco, mas depois de carregada por um processo, ela perde quase toda sua identidade como uma entidade diferente. É apenas mais um conjunto de páginas de código e dados naquele espaço de endereçamento. Assim uma .lib perde sua identidade dentro do .exe, uma .dll sofre o mesmo efeito depois de linkada. A única difereça é que no último caso a linkedição ocorre em runtime, por isso é chamada dinâmica (DLL = dynamic-link libraries).

    Ora, se os processos são isolados e a dll é apenas mais páginas de código e dados em um processo, com quase nada em especial, então esses também são isolados! Isso pode parecer ruim no seu cenário, mas é essencial para o conceito de reutilização. Por exemplo, você pode ter um cenário semelhante ao seu em que os processos A, B, C e D usam a mesma DLL, mas você quer que A e B conversem entre si e que C e D mantenham a sua comunicação isolada do outro par. Portanto, compartilhar os dados de uma DLL não teria sido um bom design genérico para um sistema operacional.

    O que você precisa é usar funcionalidades de InterProcess Communication (IPC). Você pode escolher entre vários, por exemplo named pipes, memory mapped files, sockets, etc.

    Apenas para complementar: Repare que esse comportamento de DLLs não é nada diferente do que você já está acostumado como EXEs. Se você iniciar duas instância de um executável, cada um terá sua própria cópia das variáveis estáticas, por exemplo.

    Também como complemento, é interessante notar que há muitas otimizações de performance de espaço e tempo em todo esse processo de carga da mesma DLL por diferentes processos. Por exemplo, se as DLLs não forem reposicionadas na memória porque colidem com algo diferente naquele processo, todas as páginas readonly podem ser compartilhadas fisicamente; isto é, aquela tradução entre memória virtual e física resulta na mesma posição de memória. O código estará em páginas que são readonly, portanto o código será compartilhado entre todos os processos, isto é, depois do primeiro gasta-se menos tempo com a carga, e não se perde memória para cada "cópia" da dll carregada!

    Outra otimização é com relação às páginas de dados em si. Todas as páginas que podem ser escritas podem se beneficiar da feature copy-on-write. Isto é, só ahverá duplicação desses dados se um processo tentar realmente escrever, enquanto ele estiver apenas lendo também há compartilhamento.

    Repare também que para compartilhar dados entre dois processos com segurança é necessário estar usando mecanismos de sincronismo. Não seria possível fazer com que DLLs compartilhassem dados entre processos sem conhecimento do programador por causa disso. Por exemplo, suponha que sua dll possua duas váriaveis estáticas:

    static int s_valor;
    static bool s_valorMaiorQueZero;

    E uma funcao:

    void AtualizarValor(int valor)
    {
        s_valor = valor;
        s_valorMaiorQueZero = valor > 0;
    }

    Com os processos chamando essa função simultaneamente e sem cuidado com múltiplas threads, o seguinte poderia acontecer:

    Instante 0: Processo A: AtualizarValor(1)
    Instante 1: Processo A: s_valor = 1
    Instante 2: Processo B: AtualizarValor(-1)
    Instante 3: Processo B: s_valor = -1
    Instante 4: Processo B: s_maiorQueZero = false
    Instante 5: Processo A: s_maiorQueZero = true

    No final, teríamos s_valor = -1 e s_maiorQueZero = true, o que seria inconsistente!

    Espero que essas informações ajudem.

    sexta-feira, 14 de julho de 2006 05:24
  • O mais fácil neste caso é usar memory mapped files. O código abaixo é um rascunho de como isto seria feito:

    #define MFILE "DQ_Mem" // area compartilhada de memoria

    // Estrutura da area compartilhada de memoria
    typedef struct
    {
     int     cmd;     // comando
     int     status;     // status
        // etc
    } DQ_MEM;

    HANDLE hMap = NULL;
    DQ_MEM *pMem = NULL;

    hMap = OpenFileMapping (FILE_MAP_ALL_ACCESS, FALSE, DQ_MFILE);
    pMem = NULL;
    if (hMap == NULL)
    {
        // Somos os primeiros, criar
        hMap = CreateFileMapping ((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,
                0, sizeof(DQ_MEM), DQ_MFILE);
    }
    if (hMap != NULL)
        pMem = (DQ_MEM *) MapViewOfFile (hMap, FILE_MAP_ALL_ACCESS,
                                0, 0, sizeof(DQ_MEM));
    else
        Ferrou ("Nao conseguiu acessar memoria compartilhada");

    // A partir daqui pMem aponta para a mesma estrutura para
    // todas as instancias da dll

     

    quarta-feira, 2 de agosto de 2006 14:32