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

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



PHP 8.4 membawa beberapa ciri baharu, peningkatan keselamatan dan peningkatan prestasi dengan jumlah penamatan dan penyingkiran ciri yang sihat. Panduan ini menerangkan cara memasang PHP 8.4 atau naik taraf kepada PHP 8.4 pada Ubuntu, Debian, atau terbitan mereka

Kod Visual Studio, juga dikenali sebagai Kod VS, ialah editor kod sumber percuma — atau persekitaran pembangunan bersepadu (IDE) — tersedia untuk semua sistem pengendalian utama. Dengan koleksi sambungan yang besar untuk banyak bahasa pengaturcaraan, Kod VS boleh menjadi c

Jika anda seorang pembangun PHP yang berpengalaman, anda mungkin merasakan bahawa anda telah berada di sana dan telah melakukannya. Anda telah membangunkan sejumlah besar aplikasi, menyahpenyahpepijat berjuta-juta baris kod dan mengubah suai sekumpulan skrip untuk mencapai op

Tutorial ini menunjukkan cara memproses dokumen XML dengan cekap menggunakan PHP. XML (bahasa markup extensible) adalah bahasa markup berasaskan teks yang serba boleh yang direka untuk pembacaan manusia dan parsing mesin. Ia biasanya digunakan untuk penyimpanan data

JWT adalah standard terbuka berdasarkan JSON, yang digunakan untuk menghantar maklumat secara selamat antara pihak, terutamanya untuk pengesahan identiti dan pertukaran maklumat. 1. JWT terdiri daripada tiga bahagian: header, muatan dan tandatangan. 2. Prinsip kerja JWT termasuk tiga langkah: menjana JWT, mengesahkan JWT dan muatan parsing. 3. Apabila menggunakan JWT untuk pengesahan di PHP, JWT boleh dijana dan disahkan, dan peranan pengguna dan maklumat kebenaran boleh dimasukkan dalam penggunaan lanjutan. 4. Kesilapan umum termasuk kegagalan pengesahan tandatangan, tamat tempoh, dan muatan besar. Kemahiran penyahpepijatan termasuk menggunakan alat debugging dan pembalakan. 5. Pengoptimuman prestasi dan amalan terbaik termasuk menggunakan algoritma tandatangan yang sesuai, menetapkan tempoh kesahihan dengan munasabah,

Rentetan adalah urutan aksara, termasuk huruf, nombor, dan simbol. Tutorial ini akan mempelajari cara mengira bilangan vokal dalam rentetan yang diberikan dalam PHP menggunakan kaedah yang berbeza. Vokal dalam bahasa Inggeris adalah a, e, i, o, u, dan mereka boleh menjadi huruf besar atau huruf kecil. Apa itu vokal? Vokal adalah watak abjad yang mewakili sebutan tertentu. Terdapat lima vokal dalam bahasa Inggeris, termasuk huruf besar dan huruf kecil: a, e, i, o, u Contoh 1 Input: String = "TutorialSpoint" Output: 6 menjelaskan Vokal dalam rentetan "TutorialSpoint" adalah u, o, i, a, o, i. Terdapat 6 yuan sebanyak 6

Mengikat statik (statik: :) Melaksanakan pengikatan statik lewat (LSB) dalam PHP, yang membolehkan kelas panggilan dirujuk dalam konteks statik dan bukannya menentukan kelas. 1) Proses parsing dilakukan pada masa runtime, 2) Cari kelas panggilan dalam hubungan warisan, 3) ia boleh membawa overhead prestasi.

Apakah kaedah sihir PHP? Kaedah sihir PHP termasuk: 1. \ _ \ _ Membina, digunakan untuk memulakan objek; 2. \ _ \ _ Destruct, digunakan untuk membersihkan sumber; 3. \ _ \ _ Call, mengendalikan panggilan kaedah yang tidak wujud; 4. \ _ \ _ Mendapatkan, melaksanakan akses atribut dinamik; 5. \ _ \ _ Set, melaksanakan tetapan atribut dinamik. Kaedah ini secara automatik dipanggil dalam situasi tertentu, meningkatkan fleksibiliti dan kecekapan kod.
