Mais conteúdo relacionado Semelhante a Php internal-release 2011-04-01-v0.5.2 (20) Php internal-release 2011-04-01-v0.5.21. TIPI
TIPI: PHP
www.php-internal.com RELEASE_2011-04-01_V0.5.2
reeze http://reeze.cn
er http://www.zhanger.com
phppan http://www.phppan.com
2. TIPI: PHP RELEASE_2011-04-01_V0.5.2
3. TIPI: PHP RELEASE_2011-04-01_V0.5.2
PHP PHP
PHP PHP
*nix Windows PHP
PHP PHP PHP PHP
PHP PHP PHP PHP
PHP6
PHP , . *nix
PHP . (*nix Unix , Linux ,FreeBSD, OpenSolaris, Mac OS X
)
1. PHP
PHP PHP PHP
http://php.net/downloads.php , svn/git , svn/git
#svn
cd ~
svn co http://svn.php.net/repository/php/php-src/branches/PHP_5_2 php-src-5.2
#php5.2
svn co http://svn.php.net/repository/php/php-src/branches/PHP_5_3 php-src-5.3
#php5.3
#git
cd ~
git clone git://github.com/php/php-src.git php-src
, PHP ,
.( )
2.
*nix gcc . Ubuntu apt ,
.
sudo apt-get install build-essential
4. TIPI: PHP RELEASE_2011-04-01_V0.5.2
Mac OS Xcode Xcode Mac OS X
Apple ID http://developer.apple.com/
3.
apache PHP mysql
google ~/php-src buildconf
Makefile
cd ~/php-src
./buildconf
configure , configure , ,
./configure --help #
, . ./configure .
. configure , PHP , .
. configure. configure .
make
*nix configure make, make install . make
make install . install configure prefix ,
, PHP .
make ~/php-src php .
cd ~/php-src
./sapi/cli/php -v
php . make install $prefix/bin/php
php, prefix $PATH , php .
make make install
( ) php-cli php-src/sapi/cli/php
configure make make && make install
PHP
5. TIPI: PHP RELEASE_2011-04-01_V0.5.2
PHP PHP
:/ , .
README :
/README.PHP4-TO-PHP5-THIN-CHANGES PHP4 PHP5
.
/CODING_STANDARDS, PHP ,
, , ,
, .
build , buildconf
, .
ext PHP array pdo spl
main PHP , PHP , Zend
,Zend .
Zend Zend , , opcode .
pear “PHP ”, PEAR .
sapi apache mod_php,cgi, fastcgi fpm .
TSRM PHP TSRM , PHP *G TSRM ,
TSRM(Thread Safe Resource Manager) .
tests PHP , PHP PHP, php /run-tests.php,
tests phpt .
, php ,
/tests/basic/001.phpt:
--TEST--
Trivial "Hello World" test
--FILE--
<?php echo "Hello World"?>
--EXPECT--
Hello World
, --FILE-- PHP , --EXPECT--
, , Fatal Error, ,
, , , php
: system(), exec() , ,
. php proc_open() , .
win32 Windows , sokcet Windows *Nix
, Windows PHP
PHP
VIM + Ctags
6. TIPI: PHP RELEASE_2011-04-01_V0.5.2
Linux *Nix VIM ,
, , . Emacs ,
Emacs, , .
Linux ctags . ctags ,
, : . ,
UNIX ,
# PHP ( /server/php-src) :
$ cd /server/php-src
$ ctags -R
# tags
# ctags -R /full-path-to-php-src/ ctags
# ~/.vimrc :
set tags+=/server/php-src/tags
/sever/php-src tags , :
{tagname}<Tab>{tagfile}<Tab>{tagaddress}
EG Zend/zend_globals_macros.h /^# define EG(/;" d
, , EG ,
. VIM tags , CTRL+] VIM tags ,
, .
.
Ctrl+] Ctrl+t
.
. VIM , IDE.
Mac OS X, ctags , Mac OS X ctags
, ctags, homebrew .
IDE
VIM , IDE Windows Visual
Studio 2010. Netbeans, Eclipse , ,
,
Eclipse Netbeans , CTRL, ,
.
VS , win32
Win32 Console Application
7. TIPI: PHP RELEASE_2011-04-01_V0.5.2
F12
CTRL + F12
F3:
Shift+F3:
Ctrl+G:
CTRL + -
CTRL + SHIFT + -
editplus
editplus ...
PHP
1. "##" "#"
PHP
(##)
C "##" concatenator (Token)
#define PHP_FUNCTION ZEND_FUNCTION
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
#define ZEND_FN(name) zif_##name
#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval
**return_value_ptr,
zval *this_ptr, int return_value_used TSRMLS_DC
PHP_FUNCTION(count);
// , PHP_FUCNTION(count);
void zif_count(int ht, zval *return_value, zval **return_value_ptr,
zval *this_ptr, int return_value_used TSRMLS_DC)
ZEND_FN(name) "##" zif name
(#)
8. TIPI: PHP RELEASE_2011-04-01_V0.5.2
"#"
(Token) :
#define STR(x) #x
int main(int argc char** argv)
{
printf("%sn", STR(It's a long string)); // It's a long str
return 0;
}
It's a long string STR printf
2. do-while
PHP5.3
#define ALLOC_ZVAL(z)
do {
(z) = (zval*)emalloc(sizeof(zval_gc_info));
GC_ZVAL_INIT(z);
} while (0)
do{ }while(0) PHP
do-while ? do-while
, do{ }while(0) ,
do-while ?
#define TEST(a, b) a++;b++;
if (expr)
TEST(a, b);
else
do_else();
if (expr)
a++;b++;
else
do_else();
if-else : if , , do-while
{} . if , TEST
, , . {} ,
. . do-while(0) .
9. TIPI: PHP RELEASE_2011-04-01_V0.5.2
3. #line
#line 838 "Zend/zend_language_scanner.c"
#line 838,
Zend/zend_language_scanner.c C
4.PHP
PHP PG(), EG() , PHP
$PHP_SRC/main/php_globals.h
, PG PHP
#ifdef ZTS //
# define PG(v) TSRMG(core_globals_id, php_core_globals *, v)
extern PHPAPI int core_globals_id;
#else
# define PG(v) (core_globals.v) //
extern ZEND_API struct _php_core_globals core_globals;
#endif
ZTS
PHP
struct _php_core_globals {
zend_bool magic_quotes_gpc; // GET/POST/Cookie
zend_bool magic_quotes_runtime; //
zend_bool magic_quotes_sybase; // Sybase
zend_bool safe_mode; //
zend_bool allow_call_time_pass_reference; //
zend_bool implicit_flush; // PHP
long output_buffering; // ( )
char *safe_mode_include_dir; //
UID/GID
zend_bool safe_mode_gid; // UID
zend_bool sql_safe_mode;
zend_bool enable_dl; // dl() dl() PHP apache
char *output_handler; //
char *unserialize_callback_func; //
unserialize()
long serialize_precision; // (
10. TIPI: PHP RELEASE_2011-04-01_V0.5.2
)
char *safe_mode_exec_dir; //
long memory_limit; // ( K M
)
long max_input_time; // (POST, GET, upload)
( )
zend_bool track_errors; // $php_errormsg
zend_bool display_errors; //
zend_bool display_startup_errors; // PHP
zend_bool log_errors; //
error_log
long log_errors_max_len; //
zend_bool ignore_repeated_errors; //
zend_bool ignore_repeated_source; //
zend_bool report_memleaks; //
char *error_log; //
char *doc_root; //PHP ” ”
char *user_dir; // php /~username
char *include_path; // require(), include(),
fopen_with_path()
char *open_basedir; // PHP ( )
char *extension_dir; // ( ) PHP
char *upload_tmp_dir; //
long upload_max_filesize; //
char *error_append_string; //
char *error_prepend_string; //
char *auto_prepend_file; //
char *auto_append_file; //
arg_separators arg_separator; //PHP URL
char *variables_order; // PHP Environment, GET, POST, Cookie,
Server
HashTable rfc1867_protected_variables; // RFC1867
main/rfc1867.c
short connection_status; //
short ignore_user_abort; //
unsigned char header_is_being_sent; //
zend_llist tick_functions; // main php_ticks.c
register_tick_function
zval *http_globals[6]; // GET POST SERVER
zend_bool expose_php; // php
zend_bool register_globals; // E, G, P, C, S
11. TIPI: PHP RELEASE_2011-04-01_V0.5.2
zend_bool register_long_arrays; // (HTTP_*_VARS)
zend_bool register_argc_argv; // $argv $argc ( GET
)
zend_bool auto_globals_jit; // $_SERVER $_ENV
( )
zend_bool y2k_compliance; // 2000 ( Y2K
)
char *docref_root; // html_errors PHP
char *docref_ext; // ( ’.')
zend_bool html_errors; // HTML
zend_bool xmlrpc_errors;
long xmlrpc_error_number;
zend_bool activated_auto_globals[8];
zend_bool modules_activated; //
zend_bool file_uploads; // HTTP
zend_bool during_request_startup; //
zend_bool allow_url_fopen; //
zend_bool always_populate_raw_post_data; //
$HTTP_RAW_POST_DATA ( POST )
zend_bool report_zend_debug; // zend debug main/main.c
int last_error_type; //
char *last_error_message; //
char *last_error_file; //
int last_error_lineno; //
char *disable_functions; //
char *disable_classes; //
zend_bool allow_url_include; // include/require
zend_bool exit_on_timeout; //
#ifdef PHP_WIN32
zend_bool com_initialized;
#endif
long max_input_nesting_level; //
zend_bool in_user_include; //
char *user_ini_filename; // ini
long user_ini_cache_ttl; // ini
char *request_order; // variables_order request
zend_bool mail_x_header; // ext/standard/mail.c
char *mail_log;
zend_bool in_error_log;
};
php.ini PHP php.ini
ini_get() ini_set()
PHP PG
12. TIPI: PHP RELEASE_2011-04-01_V0.5.2
G
PHP
PHP
PHP PHP PHP
PHP
13. TIPI: PHP RELEASE_2011-04-01_V0.5.2
PHP PHP PHP
PHP
Zend
: SAPI
PHP Web Apache Nginx Web .
php PHP . ,
. PHP . Web
. . Web , ,
url PHP . , .
SAPI . SAPI .
PHP SAPI . .
, SAPI ( Apache
) (MINIT), . , url
. (RINIT ). PHP PHP , MINIT
MINIT . , ,
.
PHP_MINIT_FUNCTION(myphpextension)
{
//
return SUCCESS;
}
PHP , , PHP
. . PHP RINIT
, , RINIT MINIT
PHP_RINIT_FUNCTION(myphpextension)
{
//
// .
return SUCCESS;
}
, exit() die() ,PHP
14. TIPI: PHP RELEASE_2011-04-01_V0.5.2
. , , (RSHUWDOWN), SAPI
(MSHUTDOWN).
PHP_RSHUTDOWN_FUNCTION(myphpextension)
{
// , .
return SUCCESS;
}
,
SAPI
CLI/CGI PHP SAPI . .
- - - SAPI 2.1
SAPI
PHP apache PHP . Apache , Apache
fork , , ,
fork , . Apache
, -
15. TIPI: PHP RELEASE_2011-04-01_V0.5.2
2.2
SAPI
, -
Zend
Zend PHP , . : PHP ,
, , Zend PHP , PHP PHP (
, facebook hiphop , ,PHP ),
PHP Web (SAPI).
Extending and Embedding PHP
16. TIPI: PHP RELEASE_2011-04-01_V0.5.2
SAPI
PHP , SAPI . SAPI PHP
, Apache mod_php fastcgi .
SAPI
_sapi_module_struct PHP
2.4 SAPI
cgi apache2
cgi_sapi_module.startup(&cgi_sapi_module) // cgi cgi/cgi_main.c
apache2_sapi_module.startup(&apache2_sapi_module);
// apache2 apache2handler/sapi_apache2.c
startup sapi_module_struct
struct _sapi_module_struct {
char *name; //
char *pretty_name; //
int (*startup)(struct _sapi_module_struct *sapi_module); //
int (*shutdown)(struct _sapi_module_struct *sapi_module); //
int (*activate)(TSRMLS_D); //
int (*deactivate)(TSRMLS_D); //
int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC);
// (unbuffered write)
void (*flush)(void *server_context); // flush
struct stat *(*get_stat)(TSRMLS_D); // get uid
char *(*getenv)(char *name, size_t name_len TSRMLS_DC); // getenv
void (*sapi_error)(int type, const char *error_msg, ...); /* error
handler */
int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum
op,
sapi_headers_struct *sapi_headers TSRMLS_DC); /* header handler */
17. TIPI: PHP RELEASE_2011-04-01_V0.5.2
sapi_headers_struct *sapi_headers TSRMLS_DC); /* header handler */
/* send headers handler */
int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);
void (*send_header)(sapi_header_struct *sapi_header,
void *server_context TSRMLS_DC); /* send header handler */
int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC); /* read POST
data */
char *(*read_cookies)(TSRMLS_D); /* read Cookies */
/* register server variables */
void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);
void (*log_message)(char *message); /* Log message */
time_t (*get_request_time)(TSRMLS_D); /* Request Time */
void (*terminate_process)(TSRMLS_D); /* Child Terminate */
char *php_ini_path_override; // ini
...
...
};
apache2
static sapi_module_struct apache2_sapi_module = {
"apache2handler",
"Apache 2.0 Handler",
php_apache2_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
...
}
PHP SAPI 2.5
18. TIPI: PHP RELEASE_2011-04-01_V0.5.2
SAPI SAPI.c SAPI.h
sapi_module
Apache
PHP Apache , Apache PHP
(mod_php5) PHP . PHP PHP
apache2 ap_hook_post_config , Apache mod_php5 PHP .
PHP Apache
Apache
Apache
HUP
AP_SIG_GRACEFUL
Apache mod_so mod_so
Apache Apache
PHP httpd.conf
LoadModule php5_module modules/mod_php5.so
19. TIPI: PHP RELEASE_2011-04-01_V0.5.2
HUP AP_SIG_GRACEFUL
Apache
PHP Apache
Apache Apache
“mod_” php mod_php5.c Apache module
name STANDARD20_MODULE_STUFF __FILE__
mod_php5 Apache
Apache Apache
magic magic STANDARD20_MODULE_STUFF magic
MODULE_MAGIC_COOKIE MODULE_MAGIC_COOKIE
#define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
Apache (ap_add_loaded_module)
(ap_top_modules ap_top_modules Apache
Apache PHP Apache2 mod_php5
Apache2 mod_php5
Apache2 mod_php5 sapi/apache2handler sapi/apache2filter
apache2_handle/mod_php5.c
AP_MODULE_DECLARE_DATA module php5_module = {
STANDARD20_MODULE_STUFF,
/*
__FILE__ */
create_php_config, /* create per-directory config structure */
merge_php_config, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
php_dir_cmds, /* */
php_ap2_register_hook
/* ap_hoo_
*/
};
apache module module
typedef struct module_struct module;
struct module_struct {
int version;
int minor_version;
int module_index;
20. TIPI: PHP RELEASE_2011-04-01_V0.5.2
const char *name;
void *dynamic_load_handle;
struct module_struct *next;
unsigned long magic;
void (*rewrite_args) (process_rec *process);
void *(*create_dir_config) (apr_pool_t *p, char *dir);
void *(*merge_dir_config) (apr_pool_t *p, void *base_conf, void *new_conf);
void *(*create_server_config) (apr_pool_t *p, server_rec *s);
void *(*merge_server_config) (apr_pool_t *p, void *base_conf, void
*new_conf);
const command_rec *cmds;
void (*register_hooks) (apr_pool_t *p);
}
mod_php5.c
STANDARD20_MODULE_STUFF 8
STANDARD20_MODULE_STUFF
/** Use this in all standard modules */
#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR,
MODULE_MAGIC_NUMBER_MINOR,
-1,
__FILE__,
NULL,
NULL,
MODULE_MAGIC_COOKIE,
NULL /* rewrite args spot */
php_dir_cmds
const command_rec php_dir_cmds[] =
{
AP_INIT_TAKE2("php_value", php_apache_value_handler, NULL,
OR_OPTIONS, "PHP Value Modifier"),
AP_INIT_TAKE2("php_flag", php_apache_flag_handler, NULL,
OR_OPTIONS, "PHP Flag Modifier"),
AP_INIT_TAKE2("php_admin_value", php_apache_admin_value_handler,
NULL, ACCESS_CONF|RSRC_CONF, "PHP Value Modifier (Admin)"),
AP_INIT_TAKE2("php_admin_flag", php_apache_admin_flag_handler,
NULL, ACCESS_CONF|RSRC_CONF, "PHP Flag Modifier (Admin)"),
AP_INIT_TAKE1("PHPINIDir", php_apache_phpini_set, NULL,
RSRC_CONF, "Directory containing the php.ini file"),
{NULL}
};
php command_rec Apache
php php_value
5
php_ap2_register_hook
void php_ap2_register_hook(apr_pool_t *p)
{
ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_post_config(php_apache_server_startup, NULL, NULL,
APR_HOOK_MIDDLE);
21. TIPI: PHP RELEASE_2011-04-01_V0.5.2
ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}
pre_config,post_config,handler child_init 4
pre_config,post_config,child_init handler
post_config php php_apache_server_startup
php_apache_server_startup sapi_startup sapi, php_apache2_startup
sapi module struct , php_module_startup PHP,
ZEND , zend_module_struct treat_data (
php_startup_sapi_content_types)
Apache
Apache Apache
root *nix Administrator(Windows )
( http.conf ) (
mod_php,mod_perl)
Apache
Apache Apache
Apache HTTP
11 Post-Read-
Request URI Translation Header Parsing Access Control Authentication Authorization MIME
Type Checking FixUp Response Logging CleanUp
Apache Hook
Apache Hook Apache (
mod_php5.so,mod_perl.so ) Apache
(Hook) Apache mod_php5.so/
php5apache2.dll Hook Apache Apache
php Hook Windows Windows
apache hook apache php5
Apache
Apache httpd.h httpd.h Apache
API
22. TIPI: PHP RELEASE_2011-04-01_V0.5.2
request_rec
Apache request_rec Apache
request_rec request_rec HTTP
Apache
server_rec
server_rec WEB
server_rec server_rec Apache httpd
server_rec request_rec
conn_rec
conn_rec TCP Apache
The Apache Modules Book--Application Development with Apache
PHP PHP PHP CLI,
SAPI SAPI =>
=> => => PHP
PHP
PHP
Extending and Embedding PHP
PHP PHP PHP
#include <sapi/embed/php_embed.h>
#ifdef ZTS
void ***tsrm_ls;
#endif
/* Extension bits */
zend_module_entry php_mymod_module_entry = {
STANDARD_MODULE_HEADER,
"mymod", /* extension name */
NULL, /* function entries */
NULL, /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
"1.0", /* version */
STANDARD_MODULE_PROPERTIES
};
/* Embedded bits */
static void startup_php(void)
{
23. TIPI: PHP RELEASE_2011-04-01_V0.5.2
int argc = 1;
char *argv[2] = { "embed5", NULL };
php_embed_init(argc, argv PTSRMLS_CC);
zend_startup_module(&php_mymod_module_entry);
}
static void execute_php(char *filename)
{
zend_first_try {
char *include_script;
spprintf(&include_script, 0, "include '%s'", filename);
zend_eval_string(include_script, NULL, filename TSRMLS_CC);
efree(include_script);
} zend_end_try();
}
int main(int argc, char *argv[])
{
if (argc <= 1) {
printf("Usage: embed4 scriptfile";);
return -1;
}
startup_php();
execute_php(argv[1]);
php_embed_shutdown(TSRMLS_CC);
return 0;
}
Extending and Embedding PHP 20
PHP
PHP PHP PHP
PHP PHP PHP
#include <sapi/embed/php_embed.h>
sapi embed PHP
php_embed_init php_embed_shutdown
2 4
#ifdef ZTS
void ***tsrm_ls;
#endif
ZTS Zend Thread Safety TSRM
6 17
zend_module_entry php_mymod_module_entry = {
STANDARD_MODULE_HEADER,
"mymod", /* extension name */
NULL, /* function entries */
NULL, /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
24. TIPI: PHP RELEASE_2011-04-01_V0.5.2
NULL, /* MINFO */
"1.0", /* version */
STANDARD_MODULE_PROPERTIES
};
PHP NULL,
sapi/embed/php_embed.c
php_embed_shutdown zend/zend_modules.h
startup_php :
static void startup_php(void)
{
int argc = 1;
char *argv[2] = { "embed5", NULL };
php_embed_init(argc, argv PTSRMLS_CC);
zend_startup_module(&php_mymod_module_entry);
}
php_embed_init zend_startup_module php_embed_init
sapi/embed/php_embed.c PHP
zend_startup_module PHP API mymod
zend_module_entry
execute_php :
static void execute_php(char *filename)
{
zend_first_try {
char *include_script;
spprintf(&include_script, 0, "include '%s'", filename);
zend_eval_string(include_script, NULL, filename TSRMLS_CC);
efree(include_script);
} zend_end_try();
}
PHP sprrintf include
zend_eval_string include zend_eval_string
zend_eval_stringl PHP zend_op_array
opcode php , php
PHP C PHP, PHP
<?php
if($argc < 2) die("Usage: embed4 scriptfile");
include $argv[1];
main
int main(int argc, char *argv[])
{
if (argc <= 1) {
printf("Usage: embed4 scriptfile";);
25. TIPI: PHP RELEASE_2011-04-01_V0.5.2
return -1;
}
startup_php();
execute_php(argv[1]);
php_embed_shutdown(TSRMLS_CC);
return 0;
}
PHP include
php_embed_shutdown sapi/embed/php_embed.c PHP
#define PHP_EMBED_START_BLOCK(x,y) {
php_embed_init(x, y);
zend_first_try {
#endif
#define PHP_EMBED_END_BLOCK()
} zend_catch {
/* int exit_status = EG(exit_status); */
} zend_end_try();
php_embed_shutdown(TSRMLS_C);
}
PHP
php_embed_init zend_first_try zend_end_try php_embed_shutdown PHP
PHP
Extending and Embedding PHP
FastCGI
FastCGI
CGI
CGI “ ”(Common Gateway Interface)
Web CGI CGI
CGI
php,perl,tcl
26. TIPI: PHP RELEASE_2011-04-01_V0.5.2
FastCGI
FastCGI (long-live) CGI
fork ( CGI fork-and-execute ) , FastCGI
FastCGI CGI CGI
CGI CGI CGI
FastCGI Fail- Over
FastCGI
1. Web Server FastCGI IIS ISAPI Apache Module)
2. FastCGI CGI ( php-cgi) Web
Server
3. Web Server FastCGI CGI Web server
CGI FastCGI php-cgi
4. FastCGI Web Server FastCGI
FastCGI FastCGI (
Web Server ) CGI php-cgi
PHP CGI
PHP cgi socket tcp udp tcp/udp
socket sapi
sapi cgi cgi_main.c main
main fastcgi.c main PHP
fastcgi
/* {{{ main
*/
int main(int argc, char *argv[])
{
...
sapi_startup(&cgi_sapi_module);
// 1512 sapi, sapi sapi_globals_struct
... //
27. TIPI: PHP RELEASE_2011-04-01_V0.5.2
if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
// php_cgi_startup
...
}
...
if (bindpath) {
fcgi_fd = fcgi_listen(bindpath, 128); // socket fcgi_init
...
}
if (fastcgi) {
...
/* library is already initialized, now init our request */
fcgi_init_request(&request, fcgi_fd); // request
}
fcgi_listen socket
if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 ||
...
bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
listen(listen_socket, backlog) < 0) {
...
}
while (parent) {
do {
pid = fork(); //
switch (pid) {
case 0: //
parent = 0;
/* don't catch our signals */
sigaction(SIGTERM, &old_term, 0); //
sigaction(SIGQUIT, &old_quit, 0); //
sigaction(SIGINT, &old_int, 0); //
break;
...
default:
/* Fine */
running++;
break;
} while (parent && (running < children));
...
while (!fastcgi || fcgi_accept_request(&request) >= 0) {
SG(server_context) = (void *) &request;
init_request_info(TSRMLS_C);
CG(interactive) = 0;
...
}
28. TIPI: PHP RELEASE_2011-04-01_V0.5.2
fcgi_accept_request fcgi_read_request
fastcgi.c
safe_read [main() -> fcgi_accept_request() -> fcgi_read_request() ->
safe_read()]
static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t
count)
{
size_t n = 0;
do {
... // win32
ret = read(req->fd, ((char*)buf)+n, count-n); // win
... //
} while (n != count);
}
PHP
PHP_MODE_STANDARD php_execute_script PHP
zend_execute_scripts PHP
zend_execute
...
php_request_shutdown((void *) 0); // php
...
fcgi_shutdown(); // fcgi fcgi_mgmt_vars
php_module_shutdown(TSRMLS_C); // sapi, zend
sapi_shutdown(); // sapi sapi
...
http://www.fastcgi.com/drupal/node/2
http://baike.baidu.com/view/641394.htm
PHP
PHP PHP SAPI SAPI PHP
Zend , PHP
29. TIPI: PHP RELEASE_2011-04-01_V0.5.2
:
C/C++, .NET, Java , : ,
.
:PHP, Javascript, Ruby, Python , " ".
, , ,
, , ,
, . ,
, PHP opcode ( APC, xcache, eAccelerator ),
Python pyc/pyo , .
PHP , php , apache mod_php .
PHP SAPI , PHP PHP .
PHP :
<?php
$str = "Hello, Tipi!n";
echo $str;
hello.php , PHP :
$ php ./hello.php
Hello, Tipi!, PHP/Zend ?
php ? .
1. , php , php PHP Zend ,
.
2. ,Zend , . opcode .
apc opcode , opcode .
PHP , PHP lex ,
$PHP_SRC/Zend/zend_language_scanner.l, lex
(token). PHP token_get_all(), ,
. php :
<?php
$code =<<<PHP_CODE
<?php
$str = "Hello, Tipin";
echo $str;
PHP_CODE;
30. TIPI: PHP RELEASE_2011-04-01_V0.5.2
var_dump(token_get_all($code));
array (
0 =>
array (
0 => 368, //
1 => '<?php //
',
2 => 1,
),
1 =>
array (
0 => 371,
1 => ' ',
2 => 2,
),
2 => '=',
3 =>
array (
0 => 371,
1 => ' ',
2 => 2,
),
4 =>
array (
0 => 315,
1 => '"Hello, Tipi
"',
2 => 2,
),
5 => ';',
6 =>
array (
0 => 371,
1 => '
',
2 => 3,
),
7 =>
array (
0 => 316,
1 => 'echo',
2 => 4,
),
8 =>
array (
0 => 371,
1 => ' ',
2 => 4,
),
9 => ';',
Zend , , (PHP bison
, $PHP_SRC/Zend/zend_language_parser.y), bison ,
, Zend , . ,
. ,Zend ,
opcode, ,Zend opcode, opcode - ,
31. TIPI: PHP RELEASE_2011-04-01_V0.5.2
eval,include/require , .
echo ZEND_ECHO , , C
zend_print_variable(zval* z) , . , ,
opcode . .
Opcode php vld :
http://pecl.php.net/package/vld Win dll
PHP , , opcode .
(compiler) (interpreter) :
1. ,
2.
Lex Yacc . :
1. (token).
2. (hierarchical structure).
lex/yacc (flex/bison) , PHP,
Ruby, Python MySQL SQL .
Lex Yacc Unix , , ,
Lex( :A Lexical Analyzer Generator)
Yacc(Yet Another Compiler-Compiler)
Lex/Flex
Lex , . Flex Bison , Flex lex
, Bison Yacc .
.l , flex , %%
%%
%%
, :
%option noyywrap
%{
int chars = 0;
int words = 0;
32. TIPI: PHP RELEASE_2011-04-01_V0.5.2
int words = 0;
int lines = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
n { chars++; lines++; }
. { chars++; }
%%
main(int argc, char **argv)
{
if(argc > 1) {
if(!(yyin = fopen(argv[1], "r"))) {
perror(argv[1]);
return (1);
}
yylex();
printf("%8d%8d%8dn", lines, words, chars);
}
}
, , ,
, , .
.
PHP , PHP flex, PHP re2c,
$PHP_SRC/Zend/zend_language_scanner.l re2c ,
re2c .
Yacc/Bison
PHP Lemon , Lemon SQLite SQLite
SQL . Lemno ,
.
Bison Flex , %% Bison (token) , ,
, Bison (BNF) , php echo ,
, PHP :
echo_expr_list:
echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
| expr { zend_do_echo(&$1 TSRMLS_CC); }
;
echo_expr_list , .
, , echo zend_do_echo ,
, $3 , expr , zend_do_echo
opcode, php , PHP opcode.
Opcode
33. TIPI: PHP RELEASE_2011-04-01_V0.5.2
Opcode wikipedia : opcode , ,
. ,
. , , IO .
opcode : (byte codes). Java (JVM), .NET (CIL:
Common Intermeditate Language) .
PHP opcode
PHP opcode , PHP Zend (Zend VM) . PHP
opcode Zend .
Zend
opcode PHP
struct _zend_op {
opcode_handler_t handler; // opcode
znode result;
znode op1;
znode op2;
ulong extended_value;
uint lineno;
zend_uchar opcode; // opcode
};
CPU , opcode , opcode , PHP
, , extended_value ,
result .
print :
void zend_do_print(znode *result, const znode *arg TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->result.op_type = IS_TMP_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->opcode = ZEND_PRINT;
opline->op1 = *arg;
SET_UNUSED(opline->op2);
*result = opline->result;
}
zend_op, (IS_TMP_VAR),
, opcode ZEND_PRINT, opcode .
echo :
void zend_do_echo(const znode *arg TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
34. TIPI: PHP RELEASE_2011-04-01_V0.5.2
opline->opcode = ZEND_ECHO;
opline->op1 = *arg;
SET_UNUSED(opline->op2);
}
echo opcode , echo op1, opcode result
print echo , print , echo , null
, echo .
PHP opcode op_array , :
struct _zend_op_array {
/* Common elements */
zend_uchar type;
char *function_name; // ,
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
zend_uint num_args;
zend_uint required_num_args;
zend_arg_info *arg_info;
zend_bool pass_rest_by_reference;
unsigned char return_reference;
/* END of common elements */
zend_bool done_pass_two;
zend_uint *refcount;
zend_op *opcodes; // opcode
zend_uint last, size;
zend_compiled_variable *vars;
int last_var, size_var;
// ...
}
, opcodes , execute :
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
{
// ... op_array opcode op_array opcode
}
opcode opcode_handler_t , opcode,
, ? Zend
.
PHP , PHP , SAPI ,
PHP .
35. TIPI: PHP RELEASE_2011-04-01_V0.5.2
: PHP.
36. TIPI: PHP RELEASE_2011-04-01_V0.5.2
PHP
PHP
PHP
PHP
$var1 = 10;
$var2 = 20;
function t() {
global $var1;
$var2 = 0;
$var1++;
}
t();
echo $var1, ' ';
echo $var2;
11 20 PHP
C Pascal PHP PHP
PHP
PHP zval zval
int array string
Zend
zval
.PHP
PHP
PHP C C C
PHP :
37. TIPI: PHP RELEASE_2011-04-01_V0.5.2
1. PHP 8
boolean integer float(double) string
array object
resource NULL
ZE zval zval
Zend/zend.h
typedef struct _zval_struct zval;
...
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
2. :
refcount__gc 1
is_ref__gc 0
value
type
PHP5.3
refcount__gc is_ref__gc refcount is__ref
ZE type IS_NULL, IS_BOOL,
IS_LONG, IS_DOUBLE, IS_STRING, IS_ARRAY, IS_OBJECT, IS_RESOURCE
PHP (
. _zval_value
php zval zvalue_value
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
38. TIPI: PHP RELEASE_2011-04-01_V0.5.2
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
boolean ZVAL_BOOL / (zval).value.lval , IS_*
integer ZVAL_LONG
float ZVAL_DOUBLE Z_TYPE_P(z)=IS_BOOL/LONG; Z_LVAL_P(z)=((b)!=0);
NULL (zval).type IS_NULL
null ZVAL_NULL
Z_TYPE_P(z)=IS_NULL;
resource ZVAL_RESOURCE
Z_TYPE_P(z) = IS_RESOURCE; Z_LVAL_P(z) = l;
Sting
C
PHP _zvalue_value
*val len
struct {
char *val;
int len;
} str;
strlen() str len
Array
PHP
HashTable Bucket
typedef struct _hashtable {
uint nTableSize; // hash Bucket , 8, 2x
uint nTableMask; // nTableSize-1
uint nNumOfElements; // hash Bucket , count()
ulong nNextFreeElement; // hash Bucket
Bucket *pInternalPointer; // foreach for
Bucket *pListHead; //
Bucket *pListTail; //
39. TIPI: PHP RELEASE_2011-04-01_V0.5.2
Bucket **arBuckets; // hash
dtor_func_t pDestructor;
zend_bool persistent;
unsigned char nApplyCount; // hash Bucket
zend_bool bApplyProtection;// hash
3
#if ZEND_DEBUG
int inconsistent;
#endif
} HashTable;
....
typedef struct bucket {
ulong h; // char *key hash ,
uint nKeyLength; //hash , 0
void *pData; // value ,
pDataPtr
void *pDataPtr; // , value, pData
struct bucket *pListNext; // hash
struct bucket *pListLast;
struct bucket *pNext; // hash Bucket
struct bucket *pLast;
char arKey[1];
/* 1 char
*key
*/
} Bucket;
_zval_struct _zvalue_value HashTable Bucket
Object
PHP zend_object_value
typedef struct _zend_object_value {
zend_object_handle handle; // unsigned int
zend_object_handlers *handlers;
} zend_object_value;
handle EG(objects_store).object_buckets
zend_object_handlers
_zend_class_entry
(HashTable)
PHP , PHP .
(HashTable). PHP .
, ,
40. TIPI: PHP RELEASE_2011-04-01_V0.5.2
, (Search), (Insert), (Delete) ,
O(n), , ,
O(1). .
, .
, HashTable .
, , .
(key): , PHP , .
(slot/bucket): , .
(hash function): key (map) slot .
(hash collision): key .
, , (key)
, , ,
key , . , , .
, PHP , ( ) key
:
h(key) -> index
, key , key (
key), key index ,
. hash : .
key , key
. , key ,
O(n). .
PHP HashTable .
: . ,
key , , ,
, , .
41. TIPI: PHP RELEASE_2011-04-01_V0.5.2
, :
1.
2.
3.
, ,
, , .
:
typedef struct _Bucket
{
char *key;
void *value;
struct _Bucket *next;
} Bucket;
typedef struct _HashTable
{
int size;
Bucket* buckets;
} HashTable;
PHP , , , key
, .
Bucket , key , .
key index .
key (slot bucket) ,
: key ,
.
static int hash_str(char *key)
{
int hash = 0;
char *cur = key;
while(*(cur++) != '0') {
42. TIPI: PHP RELEASE_2011-04-01_V0.5.2
hash += *cur;
}
return hash;
}
// key
#define HASH_INDEX(ht, key) (hash_str((key)) % (ht)->size)
, PHP DJBX33A , Mysql, OpenSSL
,
:
int hash_init(HashTable *ht); //
int hash_lookup(HashTable *ht, char *key, void **result); // key
int hash_insert(HashTable *ht, char *key, void *value); //
int hash_remove(HashTable *ht, char *key); // key
int hash_destroy(HashTable *ht);
int hash_insert(HashTable *ht, char *key, void *value)
{
// check if we need to resize the hashtable
resize_hash_table_if_needed(ht); //
// ,
int index = HASH_INDEX(ht, key); // key
Bucket *org_bucket = ht->buckets[index];
Bucket *bucket = (Bucket *)malloc(sizeof(Bucket)); //
bucket->key = strdup(key);
//
bucket->value = value;
LOG_MSG("Insert data p: %pn", value);
ht->elem_num += 1; //
if(org_bucket != NULL) { //
LOG_MSG("Index collision found with org hashtable: %pn", org_bucket);
bucket->next = org_bucket;
}
ht->buckets[index]= bucket;
LOG_MSG("Element inserted at index %i, now we have: %i elementsn",
index, ht->elem_num);
return SUCCESS;
43. TIPI: PHP RELEASE_2011-04-01_V0.5.2
}
key
key key ,
int hash_lookup(HashTable *ht, char *key, void **result)
{
int index = HASH_INDEX(ht, key);
Bucket *bucket = ht->buckets[index];
if(bucket == NULL) return FAILED;
//
//
while(bucket)
{
if(strcmp(bucket->key, key) == 0)
{
LOG_MSG("HashTable found key in index: %i with key: %s value:
%pn",
index, key, bucket->value);
*result = bucket->value;
return SUCCESS;
}
bucket = bucket->next;
}
LOG_MSG("HashTable lookup missed the key: %sn", key);
return FAILED;
}
PHP
PHP Bucket
PHP
$TIPI_ROOT/book/sample/chapt03/03-01-01-hashtable .
PHP
PHP
PHP ( PHP core )
HashTable
44. TIPI: PHP RELEASE_2011-04-01_V0.5.2
Ruby st , Ruby hash
PHP
PHP
zval
PHP
typedef struct _zend_constant {
zval value; /* zval PHP */
int flags; /* CONST_PERSISTENT | CONST_CS */
char *name; /* */
uint name_len;
int module_number; /* */
} zend_constant;
Zend/zend_constants.h 33
zval
PHP
define('TIPI', 'Thinking In PHP Internal');
PHP define TIPI
zval define
define
define PHP Zend/zend_builtin_functions.c
/* {{{ proto bool define(string constant_name, mixed value, boolean
case_insensitive=false)
Define a new constant */
ZEND_FUNCTION(define)
{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name,
&name_len, &val, &non_cs) == FAILURE) {
45. TIPI: PHP RELEASE_2011-04-01_V0.5.2
return;
}
... //
... //
c.value = *val;
zval_copy_ctor(&c.value);
if (val_free) {
zval_ptr_dtor(&val_free);
}
c.flags = case_sensitive; /* non persistent */
c.name = zend_strndup(name, name_len);
c.name_len = name_len+1;
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */
zend_constant
false zend_constant flags
zend_bool non_cs = 0; //
int case_sensitive = CONST_CS; // 1
if(non_cs) { //
case_sensitive = 0;
}
c.flags = case_sensitive; //
define PHP
define('^_^', 'smile');
if (defined('^_^')) {
echo 'yes';
}else{
echo 'no';
}
defined ‘^_^’
defined
46. TIPI: PHP RELEASE_2011-04-01_V0.5.2
define defined Zend/zend_builtin_functions.c
zend_get_constant_ex
zend_get_constant_ex
zend_get_constant zend_get_constant
zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c)
name
define PHP_USER_CONSTANT
E_ALL
cgi
[php_cgi_startup() -> php_module_startup() -> zend_startup() ->
zend_register_standard_constants()]
void zend_register_standard_constants(TSRMLS_D)
{
... // REGISTER_MAIN_LONG_CONSTANT
REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
...
}
REGISTER_MAIN_LONG_CONSTANT zend_register_long_constant
zend_register_long_constant zend_constant
zend_register_constant
[php_cgi_startup() -> php_module_startup() -> zend_startup() ->
zend_register_standard_constants() -> zend_register_constant]
ZEND_API void zend_register_long_constant(const char *name, uint name_len,
long lval, int flags, int module_number TSRMLS_DC)
{
zend_constant c;
c.value.type = IS_LONG;
c.value.value.lval = lval;
c.flags = flags;
c.name = zend_strndup(name, name_len-1);
c.name_len = name_len;
c.module_number = module_number;
zend_register_constant(&c TSRMLS_CC);
}
zend_register_constant c->flags
""
EG(zend_constants) EG(zend_constants) HashTable
47. TIPI: PHP RELEASE_2011-04-01_V0.5.2
HashTable
zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c,
sizeof(zend_constant), NULL)==FAILURE)
php_module_startup zend_startup
REGISTER_MAIN_LONG_CONSTANT PHP_VERSION PHP_OS
PHP ( ) HashTable
(symbol_table) , PHP : $_GET, $_POST,
$_SERVER , , ?
, PHP ? .
$GLOBALS
cgi $GLOBALS cgi_main.c main
[main() -> php_request_startup() -> zend_activate() -> init_executor() ]
... //
zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
{
zval *globals;
ALLOC_ZVAL(globals);
Z_SET_REFCOUNT_P(globals, 1);
Z_SET_ISREF_P(globals);
Z_TYPE_P(globals) = IS_ARRAY;
Z_ARRVAL_P(globals) = &EG(symbol_table);
zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"),
&globals, sizeof(zval *), NULL); // GLOBALS
}
... //
zend_hash_update GLOBALS
EG(symbol_table) EG(symbol_table) HashTable
$_GET
$_GET $_POST
$_GET $_COOKIE $_SERVER $_ENV $_FILES $_REQUEST
[main() -> php_request_startup() -> php_hash_environment() ]
php_hash_environment
48. TIPI: PHP RELEASE_2011-04-01_V0.5.2
php_hash_environment $_POST
/* {{{ php_hash_environment
*/
int php_hash_environment(TSRMLS_D)
{
char *p;
unsigned char _gpc_flags[5] = {0, 0, 0, 0, 0};
zend_bool jit_initialization = (PG(auto_globals_jit) &&
!PG(register_globals) && !PG(register_long_arrays));
struct auto_global_record {
char *name;
uint name_len;
char *long_name;
uint long_name_len;
zend_bool jit_initialization;
} auto_global_records[] = {
{ "_POST", sizeof("_POST"), "HTTP_POST_VARS",
sizeof("HTTP_POST_VARS"), 0 },
{ "_GET", sizeof("_GET"), "HTTP_GET_VARS",
sizeof("HTTP_GET_VARS"), 0 },
{ "_COOKIE", sizeof("_COOKIE"), "HTTP_COOKIE_VARS",
sizeof("HTTP_COOKIE_VARS"), 0 },
{ "_SERVER", sizeof("_SERVER"), "HTTP_SERVER_VARS",
sizeof("HTTP_SERVER_VARS"), 1 },
{ "_ENV", sizeof("_ENV"), "HTTP_ENV_VARS",
sizeof("HTTP_ENV_VARS"), 1 },
{ "_FILES", sizeof("_FILES"), "HTTP_POST_FILES",
sizeof("HTTP_POST_FILES"), 0 },
};
size_t num_track_vars = sizeof(auto_global_records)/sizeof(struct
auto_global_record);
size_t i;
/* jit_initialization = 0; */
for (i=0; i<num_track_vars; i++) {
PG(http_globals)[i] = NULL;
}
for (p=PG(variables_order); p && *p; p++) {
switch(*p) {
case 'p':
case 'P':
if (!_gpc_flags[0] && !SG(headers_sent) &&
SG(request_info).request_method && !strcasecmp(SG(request_info).request_method,
"POST")) {
sapi_module.treat_data(PARSE_POST,
NULL, NULL TSRMLS_CC); /* POST Data */
_gpc_flags[0] = 1;
if (PG(register_globals)) {
php_autoglobal_merge(&EG(symbol_table),
Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC);
}
}
break;
case 'c':
case 'C':
if (!_gpc_flags[1]) {
sapi_module.treat_data(PARSE_COOKIE,
NULL, NULL TSRMLS_CC); /* Cookie Data */
_gpc_flags[1] = 1;
if (PG(register_globals)) {
49. TIPI: PHP RELEASE_2011-04-01_V0.5.2
php_autoglobal_merge(&EG(symbol_table),
Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC);
}
}
break;
case 'g':
case 'G':
if (!_gpc_flags[2]) {
sapi_module.treat_data(PARSE_GET, NULL,
NULL TSRMLS_CC); /* GET Data */
_gpc_flags[2] = 1;
if (PG(register_globals)) {
php_autoglobal_merge(&EG(symbol_table),
Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
}
}
break;
case 'e':
case 'E':
if (!jit_initialization && !_gpc_flags[3]) {
zend_auto_global_disable_jit("_ENV",
sizeof("_ENV")-1 TSRMLS_CC);
php_auto_globals_create_env("_ENV",
sizeof("_ENV")-1 TSRMLS_CC);
_gpc_flags[3] = 1;
if (PG(register_globals)) {
php_autoglobal_merge(&EG(symbol_table),
Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV]) TSRMLS_CC);
}
}
break;
case 's':
case 'S':
if (!jit_initialization && !_gpc_flags[4]) {
zend_auto_global_disable_jit("_SERVER",
sizeof("_SERVER")-1 TSRMLS_CC);
php_register_server_variables(TSRMLS_C);
_gpc_flags[4] = 1;
if (PG(register_globals)) {
php_autoglobal_merge(&EG(symbol_table),
Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]) TSRMLS_CC);
}
}
break;
}
}
/* argv/argc support */
if (PG(register_argc_argv)) {
php_build_argv(SG(request_info).query_string,
PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
}
for (i=0; i<num_track_vars; i++) {
if (jit_initialization &&
auto_global_records[i].jit_initialization) {
continue;
}
if (!PG(http_globals)[i]) {
50. TIPI: PHP RELEASE_2011-04-01_V0.5.2
ALLOC_ZVAL(PG(http_globals)[i]);
array_init(PG(http_globals)[i]);
INIT_PZVAL(PG(http_globals)[i]);
}
Z_ADDREF_P(PG(http_globals)[i]);
zend_hash_update(&EG(symbol_table),
auto_global_records[i].name, auto_global_records[i].name_len,
&PG(http_globals)[i], sizeof(zval *), NULL);
if (PG(register_long_arrays)) {
zend_hash_update(&EG(symbol_table),
auto_global_records[i].long_name, auto_global_records[i].long_name_len,
&PG(http_globals)[i], sizeof(zval *), NULL);
Z_ADDREF_P(PG(http_globals)[i]);
}
}
/* Create _REQUEST */
if (!jit_initialization) {
zend_auto_global_disable_jit("_REQUEST", sizeof("_REQUEST")-1
TSRMLS_CC);
php_auto_globals_create_request("_REQUEST",
sizeof("_REQUEST")-1 TSRMLS_CC);
}
return SUCCESS;
}
$_POST auto_global_record
PG(variables_order) php.ini
sapi_module.treat_data
PHP treat_data SAPI
treat_data PG(register_globals) php_autoglobal_merge
zend_hash_update &EG(symbol_table) $_REQUEST
PHP
Javascript
PHP
51. TIPI: PHP RELEASE_2011-04-01_V0.5.2
static
function t() {
static $i = 0;
$i++;
echo $i, ' ';
}
t();
t();
t();
123 $i
static PHP
1.
Zend/zend_language_scanner.l static
<ST_IN_SCRIPTING>"static" {
return T_STATIC;
}
2.
token token Zend/zend_language_parser.y
| T_STATIC static_var_list ';'
static_var_list:
static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3,
NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
| static_var_list ',' T_VARIABLE '=' static_scalar {
zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
| T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL,
ZEND_FETCH_STATIC TSRMLS_CC); }
| T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3,
ZEND_FETCH_STATIC TSRMLS_CC); }
;
PHP static zend_do_fetch_static_variable
52. TIPI: PHP RELEASE_2011-04-01_V0.5.2
3.
zend_do_fetch_static_variable
void zend_do_fetch_static_variable(znode *varname, const znode
*static_assignment, int fetch_type TSRMLS_DC)
{
zval *tmp;
zend_op *opline;
znode lval;
znode result;
ALLOC_ZVAL(tmp);
if (static_assignment) {
*tmp = static_assignment->u.constant;
} else {
INIT_ZVAL(*tmp);
}
if (!CG(active_op_array)->static_variables) { /*
*/
ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
zend_hash_init(CG(active_op_array)->static_variables, 2, NULL,
ZVAL_PTR_DTOR, 0);
}
//
zend_hash_update(CG(active_op_array)->static_variables, varname-
>u.constant.value.str.val,
varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
...//
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R :
ZEND_FETCH_W; /* fetch_type=ZEND_FETCH_STATIC ZEND_FETCH_W*/
opline->result.op_type = IS_VAR;
opline->result.u.EA.type = 0;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->op1 = *varname;
SET_UNUSED(opline->op2);
opline->op2.u.EA.type = ZEND_FETCH_STATIC; /* */
result = opline->result;
if (varname->op_type == IS_CONST) {
zval_copy_ctor(&varname->u.constant);
}
fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact
that the default fetch is BP_VAR_W */
if (fetch_type == ZEND_FETCH_LEXICAL) {
...//
} else {
zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); //
}
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type
|= EXT_TYPE_UNUSED;
}
53. TIPI: PHP RELEASE_2011-04-01_V0.5.2
CG(active_op_array)-
>static_variables ZEND_FETCH_W ZEND_ASSIGN_REF
ZEND_FETCH_W zend_do_fetch_static_variable ZEND_ASSIGN_REF
zend_do_fetch_static_variable zend_do_assign_ref
4.
ZE
Zend/zend_vm_opcodes.h
#define ZEND_FETCH_W 83
#define ZEND_ASSIGN_REF 39
ZEND_FETCH_W
ZEND_FETCH_W_SPEC_CV_HANDLER
static int ZEND_FASTCALL
ZEND_FETCH_W_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_W,
ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV(int type,
ZEND_OPCODE_HANDLER_ARGS)
{
...//
if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
retval = zend_std_get_static_property(EX_T(opline-
>op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0
TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts),
type, varname TSRMLS_CC); // EG(active_op_array)-
>static_variables
...//
if (zend_hash_find(target_symbol_table, varname->value.str.val,
varname->value.str.len+1, (void **) &retval) == FAILURE) {
switch (type) {
...//
// type = case BP_VAR_W case
BP_VAR_W
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
Z_ADDREF_P(new_zval);
zend_hash_update(target_symbol_table, varname-
>value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **)
&retval);
//
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
54. TIPI: PHP RELEASE_2011-04-01_V0.5.2
switch (opline->op2.u.EA.type) {
...//
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CV == IS_VAR && !free_op1.var) {
PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
}
break;
}
}
...//
}
zend_get_target_symbol_table
static inline HashTable *zend_get_target_symbol_table(const zend_op *opline,
const temp_variable *Ts, int type, const zval *variable TSRMLS_DC)
{
switch (opline->op2.u.EA.type) {
...//
case ZEND_FETCH_STATIC:
if (!EG(active_op_array)->static_variables) {
ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
zend_hash_init(EG(active_op_array)->static_variables, 2, NULL,
ZVAL_PTR_DTOR, 0);
}
return EG(active_op_array)->static_variables;
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
return NULL;
}
zend_do_fetch_static_variable op2.u.EA.type ZEND_FETCH_STATIC
zend_get_target_symbol_table EG(active_op_array)->static_variables
HashTable
static_variables
PHP
PHP is_numeric(),
instanceof instanceof
instanceof PHP 5 is_a()
PHP5
55. TIPI: PHP RELEASE_2011-04-01_V0.5.2
PHP
PHP5.1 PHP
PHP function
function function
function Zend/zend_language_scanner.l function
token T_FUNCTION
Zend/zend_language_parser.y T_FUNCTION
zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, &$2, 0 TSRMLS_CC);
opcode ZEND_RECV opcode
ZEND_RECV_SPEC_HANDLER
static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
...//
if (param == NULL) {
char *space;
char *class_name = get_active_class_name(&space TSRMLS_CC);
zend_execute_data *ptr = EX(prev_execute_data);
if (zend_verify_arg_type((zend_function *) EG(active_op_array),
arg_num, NULL, opline->extended_value TSRMLS_CC)) {
...//
}
...//
} else {
...//
zend_verify_arg_type((zend_function *) EG(active_op_array),
arg_num, *param, opline->extended_value TSRMLS_CC);
...//
}
...//
}
ZEND_RECV_SPEC_HANDLER zend_verify_arg_type
static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num,
zval *arg, ulong fetch_type TSRMLS_DC)
{
...//
if (cur_arg_info->class_name) {
const char *class_name;
if (!arg) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type,
56. TIPI: PHP RELEASE_2011-04-01_V0.5.2
&class_name, &ce TSRMLS_CC);
return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg,
class_name, "none", "" TSRMLS_CC);
}
if (Z_TYPE_P(arg) == IS_OBJECT) { // ,
// ,
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type,
&class_name, &ce TSRMLS_CC);
if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
return zend_verify_arg_error(zf, arg_num, cur_arg_info,
need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
}
} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { //
NULL, ,
//
,
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type,
&class_name, &ce TSRMLS_CC);
return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg,
class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
}
} else if (cur_arg_info->array_type_hint) {
if (!arg) {
return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an
array", "", "none", "" TSRMLS_CC);
}
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL ||
!cur_arg_info->allow_null)) {
return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an
array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
}
}
return 1;
}
zend_verify_arg_type 3.1