Ubah suai konfigurasi ini secara dinamik dalam asas php_php
1, tukar konfigurasi semasa masa jalan
Seperti yang dinyatakan dalam artikel sebelumnya, fungsi ini_set boleh mengubah suai secara dinamik beberapa konfigurasi PHP semasa pelaksanaan PHP. Ambil perhatian bahawa tidak semua konfigurasi boleh diubah suai secara dinamik. Mengenai konfigurasi ini yang boleh diubah suai, lihat: http://php.net/manual/zh/configuration.changes.modes.php
Kami pergi terus ke pelaksanaan ini_set Walaupun fungsinya agak panjang, logiknya sangat jelas:
PHP_FUNCTION(set_ini)
{
char *varname, *new_value;
int varname_len, new_value_len;
char *nilai_lama;
jika (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &varname, &varname_len, &new_value, &new_value_len) == GAGAL) {
kembali;
}
// Dapatkan nilai yang dikonfigurasikan daripada EG (ini_directives)
Nilai_lama = zend_ini_string(varname, varname_len + 1, 0);
/* salin untuk kembali ke sini, kerana alter mungkin membebaskannya */
Jika (nilai_lama) {
RETVAL_STRING(nilai_lama, 1);
} lain {
RETVAL_FALSE;
}
// Jika mod selamat dihidupkan, konfigurasi ini berikut mungkin melibatkan operasi fail dan anda perlu menyemak uid
#define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini))
/* safe_mode & basedir check */
Jika (PG(safe_mode) || PG(open_basedir)) {
Jika (_CHECK_PATH(varname, varname_len, "error_log") ||
_CHECK_PATH(varname, varname_len, "java.class.path") ||
_CHECK_PATH(varname, varname_len, "java.home") ||
_CHECK_PATH(varname, varname_len, "mail.log") ||
_CHECK_PATH(varname, varname_len, "java.library.path") ||
_CHECK_PATH(varname, varname_len, "vpopmail.directory")) {
Jika (PG(safe_mode) && (!php_checkuid(new_value, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
zval_dtor(return_value);
PULANGAN_SALAH;
}
Jika (php_check_open_basedir(new_value TSRMLS_CC)) {
zval_dtor(return_value);
PULANGAN_SALAH;
}
}
}
// Dalam mod selamat, ini berikut dilindungi dan tidak akan diubah suai secara dinamik
Jika (PG(safe_mode)) {
Jika (!strncmp("max_execution_time", varname, sizeof("max_execution_time")) ||
!strncmp("memory_limit", varname, sizeof("memory_limit")) ||
!strncmp("child_terminate", varname, sizeof("child_terminate"))
) {
zval_dtor(return_value);
PULANGAN_SALAH;
}
}
// Panggil zend_alter_ini_entry_ex untuk mengubah suai konfigurasi ini secara dinamik
Jika (zend_alter_ini_entry_ex(varname, varname_len + 1, new_value, new_value_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC) == FAILURE) {
zval_dtor(return_value);
PULANGAN_SALAH;
}
}
Seperti yang anda lihat, sebagai tambahan kepada beberapa kerja pengesahan yang diperlukan, perkara utama ialah menghubungi zend_alter_ini_entry_ex.
Kami terus membuat susulan dalam fungsi zend_alter_ini_entry_ex:
ZEND_API int zend_alter_ini_entry_ex(char *nama, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */
{
zend_ini_entry *ini_entry;
char *pendua;
zend_bool boleh diubah suai;
zend_bool diubah suai;
// Cari ini_entry
yang sepadan dalam EG (ini_directives)
Jika (zend_hash_find(EG(ini_directives), nama, nama_panjang, (kosong **) &ini_entry) == GAGAL) {
kembali GAGAL;
}
// Sama ada ia telah diubah suai dan sama ada ia boleh diubah suai
Boleh diubah suai = ini_entry->modifiable;
Diubah suai = ini_entry->diubah suai;
jika (peringkat == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
ini_entry->modifiable = ZEND_INI_SYSTEM;
}
// Sama ada hendak memaksa pengubahsuaian
Jika (!paksa_ubah) {
Jika (!(ini_entry->boleh diubah suai & modify_type)) {
kembali GAGAL;
}
}
// EG (modified_ini_directives) digunakan untuk menyimpan ini_entry yang diubah suai
// Terutamanya digunakan untuk pemulihan
Jika (!EG(modified_ini_directives)) {
ALLOC_HASHTABLE(EG(modified_ini_directives));
zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
}
//Tempah nilai dalam ini_entry, panjang nilai dan julat yang boleh diubah suai ke dalam orig_xxx
// Supaya ini_entry boleh dipulihkan apabila permintaan tamat
Jika (!diubah suai) {
ini_entry->orig_value = ini_entry->value;
ini_entry->orig_value_length = ini_entry->value_length;
ini_entry->orig_modifiable = boleh diubah suai;
ini_entry->diubah suai = 1;
zend_hash_add(EG(modified_ini_directives), nama, name_length, &ini_entry, sizeof(zend_ini_entry*), NULL);
}
pendua = estrnup(nilai_baru, panjang_nilai_baru);
// Ubah suai panggilan untuk mengemas kini konfigurasi ini yang sepadan dalam XXX_G
jika (!ini_entry->on_modify || ini_entry->on_modify(ini_entry, duplikat, new_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_argESS_3,) == TS_arg3,) == >
// Sama seperti di atas, jika diubah suai beberapa kali, nilai yang diubah suai sebelum ini perlu dikeluarkan
Jika (ubah suai && ini_entry->orig_value != ini_entry->value) {
percuma(ini_entry->value);
}
ini_entry->value = pendua;
ini_entry->value_length = new_value_length;
} lain {
percuma(pendua);
kembali GAGAL;
}
}
1) Medan yang diubah suai dalam ini_entry digunakan untuk menunjukkan sama ada konfigurasi telah diubah suai secara dinamik. Setelah konfigurasi ini diubah suai, diubah suai akan ditetapkan kepada 1. Terdapat bahagian penting dalam kod di atas:
// Jika ini_set dipanggil beberapa kali, orig_value, dsb. sentiasa mengekalkan nilai asal
jika (!diubah suai) {
ini_entry->orig_value = ini_entry->value;
ini_entry->orig_value_length = ini_entry->value_length;
ini_entry->orig_modifiable = boleh diubah suai;
ini_entry->diubah suai = 1;
zend_hash_add(EG(modified_ini_directives), nama, name_length, &ini_entry, sizeof(zend_ini_entry*), NULL);
}
Kod ini bermakna tidak kira berapa kali kita memanggil ini_set dalam kod php, hanya set ini pertama akan memasukkan logik ini dan menetapkan nilai_orig. Bermula dari panggilan kedua ke ini_set, cawangan ini tidak akan dilaksanakan lagi, kerana diubah suai pada masa ini telah ditetapkan kepada 1. Oleh itu, ini_entry->orig_value sentiasa menyimpan nilai konfigurasi sebelum pengubahsuaian pertama (iaitu konfigurasi paling asli).
2) Untuk menjadikan konfigurasi yang diubah suai oleh ini_set berkuat kuasa serta-merta, fungsi panggil balik on_modify diperlukan.
Seperti yang dinyatakan dalam artikel sebelumnya, on_modify dipanggil untuk dapat mengemas kini pembolehubah global modul. Ingat sekali lagi, pertama sekali, konfigurasi dalam pembolehubah global modul bukan lagi daripada jenis rentetan Gunakan bool apabila ia harus menggunakan bool, dan int apabila ia harus menggunakan int. Kedua, setiap ini_entry menyimpan alamat pembolehubah global modul dan offset yang sepadan, supaya on_modify boleh mengubah suai memori dengan cepat. Selain itu, jangan lupa bahawa selepas on_modify dipanggil, ini_entry->value masih perlu dikemas kini dengan lebih lanjut supaya nilai konfigurasi dalam EG (ini_directives) adalah yang terkini.
3) Jadual cincang baharu muncul di sini, Cth (modified_ini_directives).
EG (modified_ini_directives) hanya digunakan untuk menyimpan konfigurasi ini yang diubah suai secara dinamik Jika konfigurasi ini diubah suai secara dinamik, maka ia wujud dalam kedua-dua EG (ini_directives) dan EG (modified_ini_directives). Memandangkan setiap ini_entry ditandakan dengan medan yang diubah suai, bukankah mungkin untuk melintasi EG (ini_directives) untuk mendapatkan semua konfigurasi yang diubah suai?
Jawapannya ya. Secara peribadi, saya merasakan bahawa EG (modified_ini_directives) di sini adalah untuk meningkatkan prestasi secara langsung. Selain itu, dengan menangguhkan permulaan EG (modified_ini_directives) kepada zend_alter_ini_entry_ex, anda juga boleh melihat titik pengoptimuman prestasi PHP secara terperinci.
2, pulihkan konfigurasi
Masa tindakan ini_set adalah berbeza daripada fail php.ini Sebaik sahaja pelaksanaan permintaan tamat, ini_set akan menjadi tidak sah. Selain itu, apabila fungsi ini_restore dipanggil dalam kod kami, konfigurasi yang ditetapkan sebelum ini melalui ini_set juga akan menjadi tidak sah.
Selepas setiap permintaan php dilaksanakan, php_request_shutdown akan dicetuskan dan php_request_startup adalah dua proses yang sepadan. Jika php disambungkan di bawah apache/nginx, php_request_shutdown akan dipanggil setiap kali permintaan http diproses; jika php dijalankan dalam mod CLI, php_request_shutdown juga akan dipanggil selepas skrip dilaksanakan.
Dalam php_request_shutdown, kita dapat melihat pemprosesan pemulihan untuk ini:
/* 7. Matikan pengimbas/pelaksana/penyusun dan pulihkan entri ini */
zend_deactivate(TSRMLS_C);
Masukkan zend_deactivate, anda boleh melihat lagi bahawa fungsi zend_ini_deactivate dipanggil, dan zend_ini_deactivate bertanggungjawab untuk memulihkan konfigurasi php.
zend_try {
zend_ini_deactivate(TSRMLS_C);
} zend_end_try();
Mari kita lihat dengan lebih dekat pelaksanaan zend_ini_deactivate:
ZEND_API int zend_ini_deactivate(TSRMLS_D) /* {{{ */
{
Jika (EG(modified_ini_directives)) {
// Lintas jadual ini dalam EG (modified_ini_directives)
// Panggil zend_restore_ini_entry_wrapper
untuk setiap ini_entry zend_hash_apply(EG(modified_ini_directives), (apply_func_t) zend_restore_ini_entry_wrapper TSRMLS_CC);
// Operasi kitar semula
zend_hash_destroy(EG(modified_ini_directives));
FREE_HASHTABLE(EG(modified_ini_directives));
Cth(modified_ini_directives) = NULL;
}
Kembali BERJAYA;
}
Daripada zend_hash_apply, tugas sebenar untuk memulihkan ini akhirnya jatuh kepada fungsi panggil balik zend_restore_ini_entry_wrapper.
int statik zend_restore_ini_entry_wrapper(zend_ini_entry **ini_entry TSRMLS_DC)
{
// zend_restore_ini_entry_wrapper ialah enkapsulasi zend_restore_ini_entry_cb
zend_restore_ini_entry_cb(*ini_entry, ZEND_INI_STAGE_DEACTIVATE TSRMLS_CC);
Pulangan 1;
}
int statik zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS_DC)
{
int result = GAGAL;
// Hanya lihat item ini yang diubah suai
Jika (ini_entry->diubah suai) {
Jika (ini_entry->on_modify) {
//Gunakan orig_value untuk menetapkan semula medan yang berkaitan dalam XXX_G
zend_try {
hasil = ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->asal_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->_LS,🎉);
} zend_end_try();
}
Jika (peringkat == ZEND_INI_STAGE_RUNTIME && keputusan == GAGAL) {
/* kegagalan masa jalan adalah OK */
kembali 1;
}
Jika (ini_entry->value != ini_entry->orig_value) {
percuma(ini_entry->value);
}
// ini_entry sendiri dipulihkan kepada nilai asalnya
ini_entry->value = ini_entry->orig_value;
ini_entry->value_length = ini_entry->orig_value_length;
ini_entry->modifiable = ini_entry->orig_modifiable;
ini_entry->diubah suai = 0;
ini_entry->orig_value = NULL;
ini_entry->orig_value_length = 0;
ini_entry->orig_modifiable = 0;
}
Pulangan 0;
}
3. Pemusnahan konfigurasi
Pada penghujung kitaran hayat sapi, sebagai contoh, apache dimatikan, program cli dilaksanakan, dsb. Sebaik sahaja memasuki peringkat ini, konfigurasi_hash yang disebutkan sebelum ini, EG (ini_directives), dll. perlu dimusnahkan, dan ruang memori yang digunakan oleh mereka perlu dilepaskan.
1. PHP akan menamatkan semua modul dalam urutan dan memanggil UNREGISTER_INI_ENTRIES dalam PHP_MSHUTDOWN_FUNCTION setiap modul. UNREGISTER_INI_ENTRIES sepadan dengan REGISTER_INI_ENTRIES, tetapi UNREGISTER_INI_ENTRIES tidak bertanggungjawab untuk melepaskan ruang global modul Memori XXX_globals diletakkan dalam kawasan data statik dan tidak perlu dikitar semula secara manual.
Perkara utama UNREGISTER_INI_ENTRIES lakukan ialah memadamkan konfigurasi ini_entry modul tertentu daripada jadual EG (ini_directives). Selepas pemadaman, ruang ini_entry itu sendiri akan dituntut semula, tetapi ini_entry->value tidak boleh dituntut semula.
Selepas PHP_MSHUTDOWN_FUNCTION semua modul memanggil UNREGISTER_INI_ENTRIES sekali, hanya konfigurasi ini bagi modul Teras yang tinggal dalam EG (ini_directives). Pada masa ini, anda perlu memanggil UNREGISTER_INI_ENTRIES secara manual untuk menyelesaikan pemadaman konfigurasi modul Teras.
batalkan php_module_shutdown(TSRMLS_D)
{
...
// zend_shutdown akan menutup semua modul php kecuali Teras dalam urutan
// PHP_MSHUTDOWN_FUNCTION
setiap modul akan dipanggil apabila ditutup zend_shutdown(TSRMLS_C);
...
// Pada ketika ini, hanya konfigurasi modul Teras yang tinggal dalam EG (ini_directives)
// Bersihkan secara manual di sini
NYAHDAFTAR_INI_ENTRIES();
// Recycle configuration_hash
php_shutdown_config();
// Kitar Semula EG(ini_directives)
zend_ini_shutdown(TSRMLS_C);
...
}
Selepas panggilan manual ke UNREGISTER_INI_ENTRIES selesai, EG (ini_directives) tidak lagi mengandungi sebarang elemen Secara teorinya, EG (ini_directives) pada masa ini ialah jadual cincang kosong.
2. Kitar semula konfigurasi_hash berlaku selepas EG (ini_directives). php_shutdown_config bertanggungjawab terutamanya untuk mengitar semula configuration_hash.
int php_shutdown_config(void)
{
// Kitar semula configuration_hash
zend_hash_destroy(&configuration_hash);
...
Kembali BERJAYA;
}
Perhatikan bahawa zend_hash_destroy tidak melepaskan ruang configuration_hash itu sendiri Seperti ruang global modul yang diakses oleh XXX_G, configuration_hash juga merupakan pembolehubah global dan tidak perlu dikitar semula secara manual.
3. Apabila php_shutdown_config selesai, hanya ruang EG sendiri (ini_directives) belum dikeluarkan. Jadi langkah terakhir memanggil zend_ini_shutdown. zend_ini_shutdown digunakan untuk melepaskan EG (ini_directives). Seperti yang dinyatakan di atas, EG (ini_directives) pada masa ini secara teorinya adalah jadual hash kosong, jadi ruang yang diduduki oleh HashTable itu sendiri perlu dikeluarkan.
ZEND_API int zend_ini_shutdown(TSRMLS_D)
{
// EG (ini_directives) adalah ruang yang diperuntukkan secara dinamik dan perlu dikitar semula
zend_hash_destroy(EG(ini_directives));
percuma(EG(ini_directives));
Kembali BERJAYA;
}
4, Ringkasan
Gunakan gambar untuk menerangkan secara kasar proses yang berkaitan dengan konfigurasi ini:

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

MinGW - GNU Minimalis untuk Windows
Projek ini dalam proses untuk dipindahkan ke osdn.net/projects/mingw, anda boleh terus mengikuti kami di sana. MinGW: Port Windows asli bagi GNU Compiler Collection (GCC), perpustakaan import yang boleh diedarkan secara bebas dan fail pengepala untuk membina aplikasi Windows asli termasuk sambungan kepada masa jalan MSVC untuk menyokong fungsi C99. Semua perisian MinGW boleh dijalankan pada platform Windows 64-bit.

Penyesuai Pelayan SAP NetWeaver untuk Eclipse
Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.

Dreamweaver Mac版
Alat pembangunan web visual

EditPlus versi Cina retak
Saiz kecil, penyerlahan sintaks, tidak menyokong fungsi gesaan kod

Pelayar Peperiksaan Selamat
Pelayar Peperiksaan Selamat ialah persekitaran pelayar selamat untuk mengambil peperiksaan dalam talian dengan selamat. Perisian ini menukar mana-mana komputer menjadi stesen kerja yang selamat. Ia mengawal akses kepada mana-mana utiliti dan menghalang pelajar daripada menggunakan sumber yang tidak dibenarkan.