O mecanismo operacional subjacente e o princípio do php

1 A filosofia de design e características do PHP

  • Modelo multiprocessos: Como o PHP é um modelo multiprocessos, diferentes solicitações não interferem entre si, o que garante que uma solicitação não afetará todo o serviço. Claro que, com o desenvolvimento dos tempos, o PHP já suportou o modelo multi-threaded.

  • Linguagem fracamente tipada: Ao contrário de C / C ++, Java, C # e outras linguagens, o PHP é uma linguagem fracamente tipada. O tipo de uma variável não é determinado no início, será determinado durante a operação e poderá ocorrer conversão de tipo implícita ou explícita. A flexibilidade deste mecanismo é muito conveniente e eficiente no desenvolvimento web.

  • O modo engine (Zend) + componente (ext) reduz o acoplamento interno.

  • A camada intermediária (sapi) isola o servidor web e o PHP.

  • A sintaxe é simples e flexível e não há muitas especificações.


2 A arquitetura central do PHP

A arquitetura central do PHP é mostrada na figura abaixo, que pode ser simplesmente dividida em quatro camadas de baixo para cima: 
Escreva a descrição da imagem aqui

  1. Motor Zend: implementação C pura, é a parte central do PHP, traduz o código PHP (uma série de processos de compilação, como análise lexical e gramatical) em processamento de opcode executável e implementa os métodos de processamento correspondentes, e realiza a estrutura de dados básica (como como hashtable, oo), alocação e gerenciamento de memória e métodos de API correspondentes para chamadas externas são o núcleo de tudo.Todas as funções periféricas são implementadas em torno do Zend.

  2. Extensões: Em torno do motor Zend, as extensões fornecem vários serviços básicos de maneira baseada em componentes. Nossas funções internas comuns (como série de array), bibliotecas padrão, etc. são implementadas por meio de extensões.

  3. Sapi: O nome completo é Server Application Programming Interface. Sapi usa uma série de funções de gancho para permitir que o PHP interaja com a periferia. Este é um design de PHP muito elegante e bem-sucedido. Integra com sucesso o próprio PHP e o aplicativo superior por meio do sapi. Com o isolamento de desacoplamento, o PHP não pode mais considerar como ser compatível com diferentes aplicativos, e o próprio aplicativo também pode implementar diferentes métodos de processamento com base em suas próprias características. 
    Alguns
    sapis comuns são:  apache2handler: Este é o método de processamento quando o apache é usado como servidor web e o modo mod_PHP é usado.Também é o mais amplamente usado. 
    cgi: Esta é outra forma de interação direta entre servidor web e PHP, que é o famoso protocolo fastcgi.Nos últimos anos, fastcgi + PHP tem recebido cada vez mais aplicações, sendo também a única forma suportada por servidor web assíncrono. 
    cli: modo de aplicação invocado pela linha de comando

  4. Aplicativo de nível superior: este é o programa PHP que normalmente escrevemos, e obtemos uma variedade de modos de aplicativo por meio de diferentes métodos sapi, como a implementação de aplicativos da web por meio do servidor da web e sua execução em scripts na linha de comando.


3 processo de execução de PHP

Escreva a descrição da imagem aqui

PHP implementa um processo típico de execução de linguagem dinâmica: Depois de obter um trecho de código, após análise lexical, análise gramatical e outras etapas, o programa fonte será traduzido em instruções (opcodes), e então a máquina virtual ZEND executará essas instruções em sequência para concluir a operação. O próprio PHP é implementado em C, então as chamadas finais são todas funções C. Na verdade, o PHP pode ser considerado um software desenvolvido em C.

O núcleo da execução do PHP é a instrução traduzida, que é opcode.

Opcode é a unidade mais básica de execução de um programa PHP. Um opcode consiste em dois parâmetros (op1, op2), valor de retorno e função de processamento. O programa PHP é finalmente traduzido em uma sequência de funções de processamento de opcode.

Várias funções de processamento comuns:

  • ZEND_ASSIGN_SPEC_CV_CV_HANDLER: alocação de variável (a = b)

  • ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER: Chamada de função

  • ZEND_CONCAT_SPEC_CV_CV_HANDLER: concatenação de string ab

  • ZEND_ADD_SPEC_CV_CONST_HANDLER: operação de adição a + 2

  • ZEND_IS_EQUAL_SPEC_CV_CONST: Juiz igual a == 1

  • ZEND_IS_IDENTICAL_SPEC_CV_CONST: Juiz igual a === 1


4 Introdução ao Zend Engine

Como o núcleo do PHP, o motor Zend tem muitos mecanismos de design clássicos, principalmente o seguinte:

4.1 Implementação da organização de dados HashTable:

HashTable é a estrutura de dados central do Zend. Quase todas as funções comuns são implementadas em PHP. O array PHP que conhecemos é sua aplicação típica. Além disso, no zend, como a tabela de símbolos de função e variáveis ​​globais também são implementados com base na tabela hash. 
A tabela de hash Zend implementa uma estrutura hash de tabela de hash típica e, ao mesmo tempo, fornece a função de percorrer matrizes para frente e para trás anexando uma lista duplamente vinculada. Sua estrutura
Escreva a descrição da imagem aqui 
pode ser vista na figura a seguir:  Na tabela hash, há uma forma de chave-> valor da estrutura hash e um modo de lista duplamente vinculado, tornando-o muito conveniente para oferecer suporte a pesquisa rápida e percurso linear. 
Estrutura de hash: a estrutura de hash de Zend é um modelo de tabela de hash típico, que resolve conflitos por meio de listas vinculadas. Deve-se observar que a tabela hash do zend é uma estrutura de dados de crescimento automático. Quando o número de tabelas hash estiver cheio, ela será expandida dinamicamente em 2 vezes e reposicionará os elementos. O tamanho inicial é 8. Além disso, ao realizar a busca rápida chave-> valor, o próprio zend fez algumas otimizações para acelerar a velocidade, alterando o espaço para o tempo. Por exemplo, em cada elemento, uma variável nKeyLength é usada para identificar o comprimento da chave para determinação rápida. 
Lista duplamente vinculada: a tabela hash Zend realiza a travessia linear de elementos por meio de uma estrutura de lista vinculada. Em teoria, é suficiente usar uma lista vinculada individualmente para o percurso. O principal objetivo de usar uma lista duplamente vinculada é excluir e evitar o percurso rapidamente. A tabela de hash Zend é uma estrutura composta. Quando usada como um array, ela suporta arrays associativos comuns e também pode ser usada como números de índice sequenciais, e até permite uma mistura dos dois. 
Matriz associativa do PHP: a matriz associativa é uma aplicação típica de hash_table. Um processo de consulta passa pelas seguintes etapas (como pode ser visto no código, este é um processo de consulta hash comum e adiciona algumas decisões rápidas para acelerar a pesquisa):

01 getKeyHashValue h; 02 index = n & nTableMask; 03 Bucket * p = arBucket [index]; 04 while (p) {05 if ((p-> h == h) && (p-> nKeyLength == nKeyLength)) {06 RETORNAR p-> dados; 07} 08 p = p-> próximo; 09} 10 FALTURA DE RETORNO;
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Matriz de índice PHP: A matriz de índice é nossa matriz comum, acessada por subscrito. Por exemplo, arr [0], Zend HashTable é normalizado internamente, e o valor hash e nKeyLength (0) também são atribuídos à chave do tipo de índice. A variável de membro interno nNextFreeElement é o maior id atualmente alocado, que é automaticamente incrementado em um após cada push. É esse tipo de normalização que o PHP pode alcançar uma mistura de associativo e não associativo. Devido à particularidade da operação de push, a ordem da chave do índice no array PHP não é determinada pelo tamanho do subscrito, mas pela ordem do push. Por exemplo, arr [1] = 2; arr [2] = 3; Para uma chave de tipo duplo, Zend HashTable a trata como uma chave de índice

4.2 Princípios de implementação de variáveis ​​PHP:

PHP é uma linguagem fracamente tipada e não distingue estritamente os tipos de variáveis. O PHP não precisa especificar o tipo quando uma variável é declarada. O PHP pode realizar a conversão implícita de tipos de variáveis ​​durante a execução do programa. Como outras linguagens fortemente tipadas, a conversão do tipo de exibição também pode ser realizada no programa. As variáveis ​​do PHP podem ser divididas em tipos simples (int, string, bool), tipos de coleção (array, recurso, objeto) e constantes (const). Todas as variáveis ​​acima têm a mesma estrutura zval na parte inferior.

Zval é outra estrutura de dados muito importante no zend, usada para identificar e implementar variáveis ​​PHP. Sua estrutura de dados é a seguinte: 
Escreva a descrição da imagem aqui 
A estrutura Zval é composta principalmente de três partes: 
tipo: especifica o tipo da variável (inteiro, string, array) Etc .) 
refcount & is_ref: usado para implementar a contagem de referência (descrito mais tarde) 
valor: a parte central, os dados reais da variável são armazenados, 
Zvalue é usado para armazenar os dados reais de uma variável. Como há vários tipos a serem armazenados, zvalue é uma união e, portanto, tipos fracos são realizados.

A correspondência entre os tipos de variáveis ​​PHP e seu armazenamento real é a seguinte:

1 IS_LONG -> lvalue2 IS_DOUBLE -> dvalue3 IS_ARRAY -> ht4 IS_STRING -> str5 IS_RESOURCE -> lvalue
  • 1

  • 2

  • 3

  • 4

  • 5

4.2.1 Variáveis 
inteiras e de ponto flutuante.Os inteiros e de ponto flutuante são um dos tipos básicos em PHP e também são variáveis ​​simples. Para números inteiros e de ponto flutuante, armazene o valor correspondente diretamente no zvalue. Os tipos são longos e duplos, respectivamente. 
Pode-se ver a partir da estrutura zvalue que para tipos inteiros, ao contrário de linguagens fortemente tipadas como c, o PHP não distingue entre tipos como int, unsigned int, long e long long. Para isso, há apenas um tipo de inteiro, que é longo. A partir disso, pode-se ver que no PHP, o intervalo de valores inteiros é determinado pelo número de bits do compilador ao invés de fixo. 
Para números de ponto flutuante, semelhantes aos inteiros, não faz distinção entre float e double, mas tem apenas um tipo de double.

No PHP, e se o intervalo inteiro estiver fora do intervalo? Nesse caso, ele será convertido automaticamente para o tipo duplo. Cuidado com isso. Muitos truques são causados ​​por isso.

4.2.2 Variável de Caráter

Como os inteiros, as variáveis ​​de caracteres também são variáveis ​​básicas e simples em PHP. Pode-se ver na estrutura zvalue que no PHP, uma string é composta de um ponteiro para os dados reais e uma estrutura de comprimento, que é semelhante à string em C ++. Uma vez que o comprimento é expresso por uma variável real, ao contrário de c, sua string pode ser dados binários (incluindo \ 0). Ao mesmo tempo, em PHP, o comprimento da string strlen é uma operação O (1).

Ao adicionar, modificar e anexar strings, o PHP irá realocar a memória para gerar novas strings. Finalmente, por razões de segurança, o PHP ainda adicionará \ 0 no final ao gerar uma string

Métodos comuns de emenda de strings e comparação de velocidade:

Suponha que existam as seguintes 4 variáveis: strA = '123'; strB = '456'; intA = 123; intB = 456; 
Agora iremos comparar e explicar os seguintes métodos de emenda de string: 
1 res = strA.strB e res = " strAstrB " 
Neste caso, zend irá realocar um pedaço de memória e realizar o processamento correspondente, e sua velocidade é média. 
2 strA = strA.strB 
é o mais rápido, zend irá realocar diretamente com base no strA atual para evitar cópias repetidas 
3 res = intA.intB 
é mais lento, porque precisa fazer a conversão implícita do formato e realmente escrever O programa também deve prestar atenção a evitando 
4 strA = sprintf ("% s% s", strA, strB); 
Esta será a maneira mais lenta, porque sprintf não é uma estrutura de linguagem em PHP e é para reconhecimento de formato e o processamento leva muito tempo, e o próprio mecanismo também é malloc. No entanto, o método sprintf é o mais legível e pode ser selecionado de forma flexível de acordo com a situação real.

4.2.3 Variáveis ​​de matriz

Os arrays PHP são implementados naturalmente por meio do Zend HashTable.

Como realizar a operação foreach? O foreach de uma matriz é feito percorrendo a lista duplamente vinculada na tabela de hash. Para matrizes indexadas, a eficiência de percorrer foreach é muito maior do que para, eliminando a necessidade de pesquisa de chave-> valor. A operação de contagem chama diretamente a operação HashTable-> NumOfElements, O (1). Para uma string como '123', o zend irá convertê-la em sua forma inteira. arr ['123'] e arr [123] são equivalentes

4.2.4 Variáveis ​​de recursos

A variável de tipo de recurso é a variável mais complexa em PHP e também é uma estrutura composta.

O zval do PHP pode representar uma ampla variedade de tipos de dados, mas é difícil descrever totalmente os tipos de dados personalizados. Visto que não há uma maneira eficaz de descrever essas estruturas compostas, não há como usar operadores tradicionais nelas. Para resolver esse problema, você só precisa se referir ao ponteiro por meio de um rótulo (rótulo) essencialmente arbitrário, que é chamado de recurso.

Em zval, para recurso, lval é usado como um ponteiro e aponta diretamente para o endereço onde o recurso está localizado. O recurso pode ser qualquer estrutura composta. Os familiares mysqli, fsock, memcached, etc. são todos recursos.

Como usar os recursos:

1 Registro: Para um tipo de dado personalizado, você deseja usá-lo como um recurso. Você precisa se registrar primeiro, e o zend atribuirá um identificador globalmente exclusivo a ele. 
2 Obtenha uma variável de recurso: Para recursos, zend mantém um hash_tale de id-> dados reais. Para um recurso, apenas seu id é registrado no zval. Ao buscar, encontre um valor específico em hash_table por id e retorne-o. 
3 Destruição de recursos: Os tipos de dados de recursos são diversos. O próprio Zend não tem como destruí-lo. Portanto, os usuários são obrigados a fornecer uma função de destruição ao registrar recursos. Quando o recurso não está definido, o zend chama a função correspondente para completar a destruição. Exclua-o também da tabela de recursos globais. 
Os recursos podem permanecer por um longo tempo, não apenas depois que todas as variáveis ​​que fazem referência a eles fora do escopo, mas mesmo depois que uma solicitação termina e uma nova é gerada. Esses recursos são chamados de recursos persistentes, porque eles continuam a existir ao longo de todo o ciclo de vida do SAPI, a menos que sejam especificamente destruídos. Em muitos casos, os recursos persistentes podem melhorar o desempenho até certo ponto. Por exemplo, nosso mysql_pconnect comum, recursos persistentes alocam memória por meio de pemalloc, de modo que eles não sejam liberados quando a solicitação terminar. Para zend, não há distinção entre os dois.

4-3. Contagem de referência de gerenciamento de variável PHP e cópia na gravação:

A contagem de referência é amplamente usada na recuperação de memória e manipulação de strings. A contagem de referência de Zval é realizada através das variáveis ​​membro is_ref e ref_count.Através da contagem de referência, múltiplas variáveis ​​podem compartilhar os mesmos dados. Evite o consumo pesado causado por cópias frequentes. Na operação de atribuição, zend aponta a variável para o mesmo zval e ref_count ++ ao mesmo tempo.Na operação unset, o ref_count-1 correspondente. Somente quando ref_count for reduzido a 0 a operação de destruição será realmente executada. Se for uma atribuição de referência, o zend modificará is_ref para 1.

Variáveis ​​PHP compartilham dados por meio de contagem de referência. E se uma das variáveis ​​for alterada? Ao tentar escrever uma variável, se Zend descobrir que o zval apontado pela variável é compartilhado por várias variáveis, ele copia um zval com ref_count de 1 e diminui o refcount do zval original. Este processo é chamado de "separação zval" . Pode-se ver que o zend só executa operações de cópia quando ocorre uma operação de gravação, por isso também é chamada de cópia na gravação (cópia na gravação)

Para as variáveis ​​de referência, os requisitos são opostos aos das variáveis ​​sem referência. As variáveis ​​atribuídas por referência devem ser limitadas. Modificar uma variável modifica todas as variáveis ​​associadas.

4-4. A realização de variáveis ​​locais e globais do PHP:

Como as variáveis ​​locais e globais são implementadas no PHP? Para uma solicitação, o PHP pode ver duas tabelas de símbolos (symbol_table e active_symbol_table) a qualquer momento. A primeira é usada para manter variáveis ​​globais. O último é um ponteiro para a tabela de símbolos de variável atualmente ativa.Quando o programa entra em uma função, zend irá alocar uma tabela de símbolos x para ela e apontar active_symbol_table para a. Desta forma, a distinção entre variáveis ​​globais e locais é realizada.

Obtendo valores de variáveis: a tabela de símbolos do PHP é implementada através de hash_table.Cada variável recebe um identificador único. Ao adquirir, ela encontrará o zval correspondente na tabela e o retornará com base no identificador.

Use variáveis ​​globais em funções: Em funções, podemos usar variáveis ​​globais declarando explicitamente global. Crie uma referência para a variável com o mesmo nome em symbol_table na active_symbol_table (o valor da variável referenciada precisa ser atualizado, todos irão atualizá-la juntos), se não houver nenhuma variável com o mesmo nome na symbol_table, será criado primeiro.


5 gerenciamento de memória PHP

Consulte o endereço de referência 2.

Acho que você gosta

Origin blog.csdn.net/zy17822307856/article/details/112691167
Recomendado
Clasificación