Механизм и принцип работы PHP

PHP

PHP прост, но освоить его непросто. В дополнение к его использованию, мы также должны знать его основной принцип работы.
PHP — это динамический язык, подходящий для веб-разработки. В частности, это программная среда, содержащая большое количество компонентов, реализованных на языке C. В более узком смысле вы можете думать об этом как о мощной структуре пользовательского интерфейса.
Какова цель понимания базовой реализации PHP? Чтобы хорошо использовать динамический язык, мы должны сначала понять его.Управление памятью и модели фреймворка стоит изучить.Мы можем создавать все более и более мощные функции за счет расширенной разработки и оптимизации производительности наших программ.

1. Концепция дизайна и характеристики PHP

001. Модель с несколькими процессами. Поскольку PHP является моделью с несколькими процессами, разные запросы не мешают друг другу, что гарантирует, что сбой запроса не повлияет на службу в целом. Конечно, с развитием времени PHP уже давно поддерживает модель многопоточности.

002. Язык со слабой типизацией. В отличие от C/C++, Java, C# и других языков, PHP является языком со слабой типизацией. Тип переменной не определяется в начале, и он будет определен в процессе работы и может происходить неявное или явное преобразование типов.Гибкость этого механизма очень удобна и эффективна в веб-разработке, что будет рассмотрено далее в PHP. Подробно описаны переменные.

003. Режим движок (Zend) + компонент (ext) уменьшает внутреннюю связь.

004 Средний уровень (sapi) изолирует веб-сервер и PHP.

Синтаксис 005 прост и гибок, спецификаций немного. Недостатки приводят к смешению стилей, но даже самые плохие программисты не будут писать программы, которые слишком возмутительны, чтобы навредить общей ситуации.

2. Четырехуровневая система PHP

Базовая архитектура PHP выглядит следующим образом:

Как видно из рисунка, PHP представляет собой 4-х уровневую систему снизу вверх:

Движок Zend: Zend полностью реализован на чистом C, который является основной частью PHP.Он переводит PHP-код (ряд процессов компиляции, таких как лексический и синтаксический анализ) в исполняемый код операции и реализует соответствующие методы обработки для реализации Основные данные Структура (например, хеш-таблица, oo), распределение и управление памятью, а также предоставление соответствующих API-методов для внешних вызовов являются ядром всего, и все периферийные функции реализованы вокруг Zend.

Расширения: вокруг движка Zend расширения предоставляют различные базовые услуги на основе компонентов.Наши общие встроенные функции (такие как ряды массивов), стандартные библиотеки и т. д. реализуются через расширения, и пользователи также могут реализовывать свои собственные в соответствии с их потребностями расширение для достижения цели расширения функций и оптимизации производительности (например, средний уровень PHP и синтаксический анализ форматированного текста, которые использует Tieba, являются типичными приложениями расширения).

Sapi: Полное название Sapi — интерфейс программирования серверных приложений, который представляет собой интерфейс программирования серверных приложений. Sapi позволяет PHP взаимодействовать с периферийными данными с помощью ряда функций-ловушек. Это очень элегантный и успешный дизайн PHP. и изолированы от приложения верхнего уровня, и PHP больше не может рассматривать, как быть совместимым с различными приложениями, и само приложение также может реализовывать различные методы обработки в соответствии со своими особенностями.

Приложение: это программа PHP, которую мы обычно пишем.Различные режимы приложений получаются с помощью различных методов sapi, таких как реализация веб-приложений через веб-сервер, запуск в режиме сценария из командной строки и т. д.

Если PHP — это автомобиль, то каркас автомобиля — это сам PHP, Zend — это двигатель (двигатель) автомобиля, различные компоненты под Ext — это колеса автомобиля, Sapi можно рассматривать как дорогу, а автомобиль может работать на разных типах дорог, а выполнение программы PHP — это машина, движущаяся по дороге. Итак, нам нужно: хороший двигатель + правильные колеса + правильная гусеница.

3. Sapi

Как упоминалось выше, Sapi позволяет внешним приложениям обмениваться данными с PHP через ряд интерфейсов и может реализовывать определенные методы обработки в соответствии с различными характеристиками приложения.Некоторые из наших общих SAPI:

apache2handler: это метод обработки, когда apache используется в качестве веб-сервера и работает в режиме mod_PHP.

cgi: Это еще один метод прямого взаимодействия между веб-сервером и PHP, то есть знаменитый протокол fastcgi.В последние годы fastcgi+PHP используется все больше и больше, и это также единственный метод, поддерживаемый асинхронным веб-сервером.

cli: режим приложения для вызова командной строки

4. Процесс выполнения PHP и код операции

Давайте сначала посмотрим на процесс, посредством которого выполняется код PHP.

Как видно из рисунка, PHP реализует типичный динамический процесс исполнения языка: после получения куска кода, после лексического разбора, разбора синтаксиса и других этапов исходная программа будет транслироваться в инструкции (опкоды), а затем виртуальный ZEND Машина последовательно выполняет эти инструкции, чтобы завершить операцию. Сам PHP реализован на C, поэтому конечные вызовы также являются функциями C. Фактически, мы можем рассматривать PHP как программное обеспечение, разработанное на C.

Ядром выполнения PHP являются переведенные инструкции одна за другой, то есть код операции.

Код операции — это самая основная единица выполнения программы PHP. Код операции состоит из двух параметров (op1, op2), возвращаемого значения и функции-обработчика. Программа PHP в конечном итоге транслируется в набор обработчиков кода операции для последовательного выполнения.

Несколько общих функций обработки:

ZEND_ASSIGN_SPEC_CV_CV_HANDLER : 变量分配 ($a=$b)
ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:函数调用
ZEND_CONCAT_SPEC_CV_CV_HANDLER:字符串拼接 $a.$b
ZEND_ADD_SPEC_CV_CONST_HANDLER: 加法运算 $a+2
ZEND_IS_EQUAL_SPEC_CV_CONST:判断相等 $a==1
ZEND_IS_IDENTICAL_SPEC_CV_CONST:判断相等 $a===1

5. HashTable — основная структура данных

HashTable является основной структурой данных Zend. Она используется для реализации почти всех распространенных функций в PHP. Известный массив PHP является ее типичным применением. Кроме того, в Zend такие функции, как таблица символов функций и глобальные переменные, также основаны на хэш-таблица.
Хэш-таблица PHP имеет следующие характеристики:

001. Поддержка типового запроса ключ->значение

002. Можно использовать как массив

003. Добавление и удаление узлов сложности O(1)

004.key поддерживает смешанные типы: есть также массив ассоциативных чисел с комбинированным индексом

005.Value поддерживает смешанные типы: массив ("строка", 2332)

006. Поддержка линейного обхода: например, foreach

Zend hash table реализует типичную хеш-структуру хеш-таблицы, и в то же время, за счет присоединения двусвязного списка, обеспечивает функцию прямого и обратного обхода массива. Его структура выглядит следующим образом:

Видно, что в хеш-таблице присутствуют как хеш-структуры ключ->значение, так и режимы двусвязного списка, что делает очень удобной поддержку быстрого поиска и линейного обхода.

001. Структура хэша. Структура хэша Zend представляет собой типичную модель хеш-таблицы, которая разрешает конфликты с помощью связанных списков. Следует отметить, что хэш-таблица zend является саморастущей структурой данных, когда количество хеш-таблиц заполняется, она будет динамически расширяться в 2 раза и перемещать элементы. Начальный размер равен всем 8. Кроме того, при выполнении быстрого поиска по ключу->значению сам zend также сделал некоторые оптимизации для увеличения скорости за счет замены пространства на время. Например, в каждом элементе будет использоваться переменная nKeyLength для определения длины ключа для быстрого определения.

002. Двусвязный список: хеш-таблица Zend реализует линейный обход элементов через структуру связанного списка. Теоретически для обхода достаточно использовать односвязный список, основная цель использования двусвязного списка — быстро удалить и избежать обхода. Хэш-таблица Zend представляет собой составную структуру. При использовании в качестве массива она поддерживает как обычные ассоциативные массивы, так и последовательные индексы, и даже допускает их сочетание.

Ассоциативный массив 003.PHP: Ассоциативный массив — это типичное приложение для хэш-таблицы. Процесс запроса проходит следующие этапы (как видно из кода, это обычный процесс хэш-запроса, и для ускорения поиска добавлены некоторые быстрые суждения):

getKeyHashValue h;
index = n & nTableMask;
Bucket *p = arBucket[index];                                         
while (p) {    
    if ((p->h == h) & (p->nKeyLength == nKeyLength)) {   
        RETURN p->data;   
    }
    p=p->next;
}RETURN FALTURE;

004. Массив индексов PHP: Массив индексов — это наш общий массив, доступ к которому осуществляется через индексы. Например, $arr[0], Zend HashTable нормализуется внутри, а хеш-значение и nKeyLength (0) также присваиваются ключу типа индекса. Внутренняя переменная-член nNextFreeElement — это текущий назначенный максимальный идентификатор, который автоматически увеличивается на единицу после каждого нажатия. Именно эта нормализация позволяет PHP добиться сочетания ассоциативности и неассоциативности. Из-за специфики операции push порядок индексных ключей в массиве PHP определяется не размером нижнего индекса, а порядком нажатия. Например, $обр[1] = 2; $arr[2] = 3; Для ключа типа double Zend HashTable будет рассматривать его как индексный ключ

6. PHP-переменные

PHP является слабо типизированным языком и строго не различает типы переменных. PHP не нужно указывать тип при объявлении переменной. Неявные преобразования типов переменных могут выполняться PHP во время выполнения программы. Как и в других строго типизированных языках, в программах можно выполнять явное преобразование типов. Переменные PHP можно разделить на простые типы (int, string, bool), типы коллекций (объект ресурса массива) и константы (const). Все вышеперечисленные переменные имеют под капотом одну и ту же структуру zval.
Zval — еще одна очень важная структура данных в Zend, используемая для идентификации и реализации переменных PHP.Его структура данных выглядит следующим образом:

Звал в основном состоит из трех частей:

тип: указывает тип, описываемый переменной (целое число, строка, массив и т. д.)

refcount&is_ref: используется для реализации подсчета ссылок (описано позже)

значение: основная часть, в которой хранятся фактические данные переменной

Zvalue используется для хранения фактических данных переменной. Поскольку необходимо хранить несколько типов, zvalue представляет собой объединение, которое также реализует слабую типизацию.

Соответствие между типами переменных PHP и их реальным хранилищем следующее:

IS_LONG   -> lvalue
IS_DOUBLE -> dvalue
IS_ARRAY  -> ht
IS_STRING -> str
IS_RESOURCE -> lvalue

подсчет ссылок

Подсчет ссылок широко используется при освобождении памяти, манипулировании строками и т. д. Переменные в PHP — типичное применение подсчета ссылок. Счетчик ссылок Zval реализуется переменными-членами is_ref и ref_count.Благодаря подсчету ссылок несколько переменных могут совместно использовать одни и те же данные. Избегайте большого потребления, вызванного частыми копиями.
При выполнении операции присваивания zend указывает переменной на тот же zval и ref_count++, а при выполнении операции сброса — соответствующий ref_count-1. Уничтожение будет выполнено только тогда, когда ref_count уменьшится до 0. Если это присваивание ссылки, zend изменит is_ref на 1.
Переменные PHP реализуют совместное использование данных через подсчет ссылок Что делать, если значение одной из переменных изменилось? Если при попытке записать переменную Zend обнаруживает, что zval, на который указывает переменная, совместно используется несколькими переменными, он копирует zval с ref_count, равным 1, и уменьшает refcount исходного zval.Этот процесс называется "разделением zval". . Видно, что zend выполняет операцию копирования только тогда, когда происходит операция записи, поэтому его еще называют копированием при записи (copy-on-write)
Для ссылочных переменных требования противоположны требованиям к не ссылочным переменным.Переменные, назначенные по ссылке, должны быть связаны.Изменение одной переменной изменит все связанные переменные.

Целые числа и числа с плавающей запятой

Целое число с плавающей запятой — один из основных типов в PHP, а также простая переменная. Для целых чисел и чисел с плавающей запятой сохраните соответствующее значение непосредственно в zvalue. Его виды длинные и двойные соответственно.
Из структуры zvalue видно, что для целочисленных типов, в отличие от строго типизированных языков, таких как с, PHP не различает типы int, unsigned int, long, long long и др. Для него существует только один тип целое, длинное. Отсюда видно, что в PHP диапазон целочисленных значений определяется количеством битов компилятора, а не фиксированным.
Для чисел с плавающей запятой, подобных целым числам, он не делает различий между float и double, а имеет только один тип double.
Что делать в PHP, если диапазон целых чисел выходит за пределы? В этом случае он будет автоматически преобразован в тип double.Будьте осторожны, из-за этого генерируется много трюков.

символы и строки

Как и целые числа, символьные переменные являются примитивными и простыми переменными в PHP. Из структуры zvalue видно, что в PHP строки состоят из указателей на фактические данные и структур длины, которые аналогичны строкам в C++. Поскольку длина представлена ​​фактической переменной, в отличие от c, ее строка может быть двоичными данными (включая \0), а в PHP определение длины строки strlen выполняется за O(1).
При добавлении, изменении и добавлении строковых операций PHP перераспределяет память для создания новых строк. Наконец, из соображений безопасности PHP по-прежнему добавляет \0 в конец при создании строки.
Общие методы сращивания строк и сравнения скорости:

Предположим, что есть 4 переменные следующим образом:

$strA = '123';
$strB = '456';
$intA = 123;
$intB = 456;

Теперь сделайте сравнение и описание следующих нескольких методов конкатенации строк:

// 下面两张情况,zend会重新malloc一块内存并进行相应处理,其速度一般
$res = $strA . $strB
$res = "$strA$strB"
// 这种是速度最快的,zend会在当前strA基础上直接relloc,避免重复拷贝
$strA = $strA . $strB
// 这种速度较慢,因为需要做隐式的格式转换,实际编写程序中也应该注意尽量避免
$res = $intA . $intB
 
// 这会是最慢的一种方式,因为sprintf在PHP中并不是一个语言结构,
// 本身对于格式识别和处理就需要耗费比较多时间,另外本身机制也是malloc。
// 不过sprintf的方式最具可读性,实际中可以根据具体情况灵活选择。
$strA = sprintf ("%s%s", $strA . $strB);

множество

Массивы PHP естественным образом реализованы через Zend HashTable.
Как реализована операция foreach? Foreach для массива выполняется путем обхода двусвязного списка в хеш-таблице. Для индексированных массивов обход по foreach намного эффективнее, чем по for, что устраняет необходимость в поиске по ключу->значению. Операция count напрямую вызывает HashTable->NumOfElements, операцию O(1). Для таких строк, как «123», zend преобразует их в целочисленную форму. $arr['123'] и $arr[123] эквивалентны.

ресурс

Переменная типа ресурса — самая сложная переменная в PHP, а также составная структура.
Zval в PHP может представлять широкий спектр типов данных, но сложно адекватно описать пользовательские типы данных. Поскольку нет эффективного способа описать эти составные структуры, то и использовать для них традиционные операторы невозможно. Чтобы решить эту проблему, просто обратитесь к указателю по произвольной метке, называемой ресурсом.
В zval для ресурса lval используется как указатель, указывающий непосредственно на адрес, где находится ресурс. Ресурсом может быть любая составная структура, знакомые mysqli, fsock, memcached и т. д. — все это ресурсы.

Как использовать ресурсы:

Регистрация: для пользовательского типа данных, чтобы использовать его в качестве ресурса. Сначала вам нужно зарегистрироваться, zend присвоит ему глобально уникальный идентификатор.

Получить переменную ресурса: Для ресурсов zend поддерживает хеш_сказку id->фактических данных. Для ресурса в zval записывается только его id. При выборке найдите конкретное значение в hash_table по идентификатору и верните его.

Уничтожение ресурсов: Типы данных ресурсов различны. Зенд сам по себе не может его уничтожить. Поэтому пользователи должны предоставлять функцию уничтожения при регистрации ресурсов. Когда ресурс не задан, zend вызывает соответствующую функцию для завершения деструктора. Также удалите его из глобальной таблицы ресурсов.

Ресурс может сохраняться в течение длительного времени не только после того, как все переменные, ссылающиеся на него, выходят из области видимости, но даже после завершения запроса и создания нового запроса. Эти ресурсы называются постоянными ресурсами, поскольку они сохраняются на протяжении всего жизненного цикла SAPI, если только они не уничтожаются преднамеренно. Во многих случаях постоянные ресурсы могут в некоторой степени повысить производительность. Например, в нашем обычном mysql_pconnect постоянные ресурсы выделяются памятью через pemalloc, чтобы они не освобождались при завершении запроса. Для зенда между ними нет различия.

переменная область видимости

Как локальные и глобальные переменные реализованы в PHP? Для запроса PHP может видеть две таблицы символов (symbol_table и active_symbol_table) в любое время, первая из которых используется для обслуживания глобальных переменных. Последний является указателем на текущую активную таблицу переменных символов.Когда программа входит в функцию, zend выделит для нее таблицу символов x и укажет active_symbol_table на a. Таким образом реализуется различие между глобальными и локальными переменными.

Получение значений переменных: Таблица символов PHP реализована через hash_table, и каждой переменной присваивается уникальный идентификатор, при получении находим соответствующий zval из таблицы и возвращаем его по идентификатору.

Использование глобальных переменных в функциях. В функциях мы можем использовать глобальные переменные, явно объявив global. Создайте ссылку на переменную с таким же именем в таблице символов в таблице символов, если в таблице символов нет переменной с таким именем, она будет создана первой.

Для перепечатки указать:Код жизни » Механизм и принцип работы PHP

нравится (0)