TIPI:深入理解PHP内核

344 63 2MB

Chinese Pages [181] Year 2017

Report DMCA / Copyright

DOWNLOAD FILE

TIPI:深入理解PHP内核

Citation preview

TIPI TIPI:

PHP

www.php-internal.com

RELEASE_2011-07-29_V0.6.7

reeze http://reeze.cn er http://www.zhangabc.com phppan http://www.phppan.com

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

PHP

PHP

PHP *nix

PHP 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 #5.2 svn co http://svn.php.net/repository/php/php-src/branches/PHP_5_3 php-src-5.3 #5.3 #git cd ~ git clone git://github.com/php/php-src.git php-src PHP (

)

PHP svn

SVN git

git (DVCS)

Python

DVCS

git

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

2. *nix

Ubuntu

apt

sudo apt-get install build-essential Mac OS

Xcode

Apple ID

Xcode

Mac OS X

http://developer.apple.com/

3. Apache

PHP

Mysql

svn/git buildconf cd ~/php-src ./buildconf configure

configure

./configure --help # PHP

./configure --disable-all

configure

PHP configure

configure

./configure --disable-all make *nix

configure make

make install

install

make install

configure

PHP

make

prefix

make

sapi/cli

php

. ./sapi/cli/php -n -v -n

php.ini

-v

make install prefix make

$PATH make install

php $prefix/bin/php php

php

TIPI:

make

RELEASE_2011-07-29_V0.6.7

php-src/sapi/cli/php

php-cli

configure make

linuxsir.org

PHP

make install

make

make && make install

http://www.linuxsir.org/main/doc/gnumake/GNUmake_v3.80-

zh_CN_html/index.html Autotools A Practioner's Guide

PHP PHP

PHP

:/ README /README.PHP4-TO-PHP5-THIN-CHANGES

PHP4

/CODING_STANDARDS

PHP5

PHP

build

buildconf

ext

PHP

main

array

PHP

pdo

PHP

spl

Zend

Zend Zend Zend

opcode

pear “PHP



PEAR

sapi

apache

TSRM PHP

TSRM

mod_php

PHP

cgi fastcgi *G

fpm TSRM

TSRM(Thread Safe Resource Manager) tests PHP

PHP

win32

Windows Windows

PHP tests

PHP phpt

/tests/basic/001

sokcet PHP PHP php

phpt

Windows

php

/run-tests php

*Nix

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

--TEST-Trivial "Hello World" test --FILE- --EXPECT-Hello World --FILE--

PHP

--EXPECT-Fatal Error php

system()

exec() php

proc_open()

PHP

VIM + Ctags Linux

*Nix

VIM Emacs

Emacs

Linux

ctags

ctags

: VIM

EMACS

UNIX

# PHP ( /server/php-src) $ cd /server/php-src $ ctags -R # #

:

tags ctags -R /server/

ctags

# ~/.vimrc : set tags+=/server/php-src/tags # vim : :set tags+=/server/php-src/tags /sever/php-src

tags

{tagname}{tagfile}{tagaddress} EG

Zend/zend_globals_macros.h

/^# define EG(/;"

d EG

VIM VIM

tags

tags

CTRL+]

TIPI:

Ctrl+] “

PHP

RELEASE_2011-07-29_V0.6.7

Ctrl+t

” VIM IDE Mac OS X

ctags

Mac OS X

ctags

ctags

homebrew

IDE VIM

IDE

Studio 2010 Express

Eclipse

Windows

Netbeans Eclipse

Netbeans

VS

Visual

CTRL

win32 Win32 Console Application

F12 CTRL + F12 F3: Shift+F3: Ctrl+G: CTRL + CTRL + SHIFT + Editplus Editplus

...

PHP PHP

1. "##"

"#" C/C++ PHP

"##"

"#"

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

(##) 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

(#) "#" (Token) : #define STR(x) #x int main(int argc char** argv) { printf("%s\n", STR(It's a long string)); // return 0; } It's a long string

2.

STR

do-while PHP

PHP5.3

It's a long str

printf

TIPI:

#define ALLOC_ZVAL(z) do { (z) = (zval*)emalloc(sizeof(zval_gc_info)); GC_ZVAL_INIT(z); } while (0)

PHP

RELEASE_2011-07-29_V0.6.7

\ \ \ \

do{ }while(0)

PHP

C/C++ do-while

?

do-while

do{ }while(0) do-while

#define TEST(a, b)

false ?

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)

do-while

"

"

PHP sapi\thttpd\thttpd.c

VEC_FREE(): #ifdef SERIALIZE_HEADERS # define VEC_FREE() smart_str_free(&vec_str) #else # define VEC_FREE() do {} while (0) #endif SERIALIZE_HEADERS

VEC_FREE()

VEC_FREE()



#ifdef DEBUG



Debug

TIPI:

PHP

# define LOG_MSG printf #else # define LOG_MSG(...) #endif DEBUG

LOG_MSG

printf

LOG_MSG()

3. #line #line 838 "Zend/zend_language_scanner.c" #line

__LINE__

838

__FILE__

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; zend_bool safe_mode;

//

Sybase

//

zend_bool allow_call_time_pass_reference; zend_bool implicit_flush; long output_buffering;

//

//

//

PHP (

)

RELEASE_2011-07-29_V0.6.7

TIPI:

char *safe_mode_include_dir; UID/GID zend_bool safe_mode_gid; // zend_bool sql_safe_mode; zend_bool enable_dl; // char *output_handler;

PHP

RELEASE_2011-07-29_V0.6.7

// UID dl()

dl()

PHP

apache

//

char *unserialize_callback_func;

// unserialize()

long serialize_precision;

//

char *safe_mode_exec_dir;

//

(

)

long memory_limit;

//

(

K M

) long max_input_time; ( )

//

(POST, GET, upload)

zend_bool track_errors; // zend_bool zend_bool zend_bool error_log long

$php_errormsg

display_errors; // display_startup_errors; log_errors; // log_errors_max_len;

//

//

zend_bool ignore_repeated_errors;

//

zend_bool ignore_repeated_source;

//

zend_bool report_memleaks; char *error_log; //

PHP

//

char *doc_root; //PHP ” ” char *user_dir; // php /~username char *include_path; // require(), include(), fopen_with_path() char *open_basedir; // PHP ( ) char *extension_dir;

//

char *upload_tmp_dir; // long upload_max_filesize;

(

)

PHP

//

char *error_append_string; // char *error_prepend_string; // char *auto_prepend_file; char *auto_append_file; //

//

arg_separators arg_separator; char *variables_order;

// PHP

//PHP

URL

Environment, GET, POST, Cookie,

Server HashTable rfc1867_protected_variables; main/rfc1867.c

//

RFC1867

TIPI:

short connection_status; short ignore_user_abort;

PHP

RELEASE_2011-07-29_V0.6.7

// //

unsigned char header_is_being_sent; // zend_llist tick_functions; // register_tick_function zval *http_globals[6];

//

zend_bool expose_php;

//

zend_bool zend_bool zend_bool ) zend_bool (

main

php_ticks.c

GET POST SERVER php

register_globals; // register_long_arrays; // register_argc_argv; //

E, G, P, C, S

auto_globals_jit; // )

zend_bool y2k_compliance; ) char *docref_root;

//

char *docref_ext;

//

(HTTP_*_VARS) ( GET

$argv $argc

$_SERVER $_ENV

//

2000 html_errors (

(

Y2K

PHP ’.')

zend_bool html_errors; // zend_bool xmlrpc_errors;

HTML

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; // int last_error_type; // char *last_error_message; char *last_error_file; // int last_error_lineno; // char *disable_functions; char *disable_classes;

zend debug

main/main.c

//

//

//

zend_bool allow_url_include; 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; long user_ini_cache_ttl; char *request_order;

//

//

// //

//

include/require

// ini ini variables_order

request

TIPI:

zend_bool mail_x_header; char *mail_log;

//

PHP

ext/standard/mail.c

zend_bool in_error_log; }; php.ini ini_get()

PHP

php.ini

ini_set()

PHP

PG G

PHP PHP

PHP

PHP

PHP PHP

PHP

RELEASE_2011-07-29_V0.6.7

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

PHP

Web PHP

PHP

PHP

PHP

PHP

Zend : SAPI SAPI(Server Application Programming Interface) PC

PHP

PC

PC

PHP

Web Apache

Nginx

Web

PHP

PHP

Web

PHP

Web PHP

SAPI Apache Apache

url

SAPI

mod_php SAPI

Apache

SAPI SAPI

PHP MINIT

SAPI

(

Apache

) RINIT RINIT

url PHP

PHP_MINIT_FUNCTION(myphpextension)

MINIT

MINIT

PHP

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

{ // return SUCCESS; } PHP

PHP PHP

RINIT

RINIT

MINIT

PHP_RINIT_FUNCTION(myphpextension) { // // return SUCCESS; } exit()

die()

PHP

(RSHUWDOWN RINIT)

SAPI

(MSHUTDOWN

Web

MINIT)

PHP_RSHUTDOWN_FUNCTION(myphpextension) { // return SUCCESS; }

SAPI CLI/CGI

PHP -

SAPI -

-

SAPI

2.1

TIPI:

2.1

PHP

RELEASE_2011-07-29_V0.6.7

SAPI

SAPI PHP

apache

PHP

Apache

Apache

fork fork

Apache -

2.2

2.2

SAPI

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

SAPI -

2.3

SAPI

Zend Zend

PHP

PHP PHP

facebook

hiphop

Web PHP Zend API

PHP

PHP

( )

PHP

(SAPI) Zend

Zend Zend API

PHP

PHP

PHP PHP

Zend

PHP

PHP

Zend

PHP PHP Java JVM

JVM PHP

IBM

Project Zero

.NET HipHop

PHP C

Ruby PHP

PHP ZendAPI

Pear

HipHop

PHP

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

Extending and Embedding PHP

SAPI PHP

SAPI PHP Apache

SAPI

PHP

mod_php

fastcgi SAPI

_sapi_module_struct

SAPI

SAPI

PHP

SAPI

2.4

SAPI

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 cgi_sapi_module

sapi_module_struct

php_cgi_startup

startup

startup

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

TIPI:

struct stat *(*get_stat)(TSRMLS_D); // get uid char *(*getenv)(char *name, size_t name_len TSRMLS_DC); // void (*sapi_error)(int type, const char *error_msg, ...); handler */

PHP

RELEASE_2011-07-29_V0.6.7

getenv /* error

int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, 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); time_t (*get_request_time)(TSRMLS_D); void (*terminate_process)(TSRMLS_D); char *php_ini_path_override;

//

/* Log message */ /* Request Time */ /* Child Terminate */ ini

... ... }; Apache2 static sapi_module_struct apache2_sapi_module = { "apache2handler", "Apache 2.0 Handler", php_apache2_startup, php_module_shutdown_wrapper,

/* startup */ /* shutdown */

... } PHP 2.5

IIS

Web

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

2.5 SAPI PHP

SAPI

PHP

SAPI PECL

APC

SAPI

SAPI.c

SAPI.h

sapi_module PHP zend_module_entry

PHP sapi_module_struct

PHP

zend_module_entry

request_startup_func VLD

PHP_RINIT

request_startup_func

PHP_RINIT(vld),

PHP_RINIT_FUNCTION(vld) { }

SAPI

Apache Apache

Apache

Web Web

Apache

TIPI:

mod_auth mod_rewrite

URL

Perl Python

Tcl

PHP

mod_ssl SSL

RELEASE_2011-07-29_V0.6.7

TLS

Apache

Apache

PHP

Apache

mod_php5

mod_php5

Apache

Apache apache2

PHP

PHP

Apache

PHP

ap_hook_post_config

mod_php5

Apache

PHP

PHP

Apache HUP

AP_SIG_GRACEFUL Apache

mod_so

mod_so

Apache

Apache Apache

mod_php5

Apache

httpd.conf LoadModule php5_module modules/mod_php5.so LoadModule HUP AP_SIG_GRACEFUL

Apache

Apache Apache

“mod_”

Apache

PHP mod_php5.c

Apache

name

module

STANDARD20_MODULE_STUFF

module

__FILE__

mod_php5 Apache

Apache module

magic magic

Apache magic

MODULE_MAGIC_COOKIE

STANDARD20_MODULE_STUFF MODULE_MAGIC_COOKIE

#define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */ Apache

(ap_add_loaded_module)

(ap_top_modules

Apache

PHP

ap_top_modules

Apache

Apache2

mod_php5

TIPI:

Apache2

PHP

RELEASE_2011-07-29_V0.6.7

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; 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 */ php5_module

php_dir_cmds

const command_rec php_dir_cmds[] =

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

{ 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} }; mod_php5

command_rec

Apache mod_php5

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); 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 pre_config

post_config

post_config

handler

child_init

handler

post_config php_apache_server_startup php_apache2_startup php_module_startup treat_data

(

php

php_apache_server_startup

sapi_startup

sapi

sapi module struct PHP

ZEND

zend_module_struct

php_startup_sapi_content_types) Apache

mod_php5

child_init 4

mod_php5

Apache

SAPI

sapi_module_struct

:

static sapi_module_struct apache2_sapi_module = { "apache2handler", "Apache 2.0 Handler", php_apache2_startup, php_module_shutdown_wrapper, NULL, NULL, php_apache_sapi_ub_write, php_apache_sapi_flush, php_apache_sapi_get_stat, php_apache_sapi_getenv,

/* startup */ /* shutdown */

/* activate */ /* deactivate */ /* /* /* /*

unbuffered write */ flush */ get uid */ getenv */

TIPI:

php_error,

PHP

RELEASE_2011-07-29_V0.6.7

/* error handler */

php_apache_sapi_header_handler, /* header handler */ php_apache_sapi_send_headers, /* send headers handler */ NULL, /* send header handler */ php_apache_sapi_read_post, php_apache_sapi_read_cookies,

/* read POST data */ /* read Cookies */

php_apache_sapi_register_variables, php_apache_sapi_log_message, /* Log message */ php_apache_sapi_get_request_time, /* Request Time */ NULL, /* Child Terminate */ STANDARD_SAPI_MODULE_PROPERTIES }; Apache

cookie

Cookie

Apache

SAPI

PHP read_cookies

SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C); sapi_module apache2_sapi_module

read_cookies

Apache

sapi_module

php_apache_sapi_read_cookies

SAPI

Apache Apache

Apache root

mod_php

*nix

Administrator(Windows

)

(

)

http.conf

(

mod_perl)

Apache

Apache

Apache Apache 11

Request

URI Translation

Type Checking

FixUp

Header Parsing

Response

Logging

HTTP

Post-Read-

Access Control Authentication

Authorization

MIME

CleanUp

Apache Hook Apache

Hook

mod_php5.so

Apache

mod_perl.so

(

)

Apache

(Hook)

Apache

php5apache2.dll php

Hook Hook

Windows

Apache

mod_php5.so/ Apache Windows

TIPI:

apache

hook

apache

PHP

RELEASE_2011-07-29_V0.6.7

php5

Apache Apache

httpd.h

httpd.h

Apache

API request_rec

Apache request_rec

request_rec

Apache

request_rec

HTTP

Apache server_rec

server_rec

server_rec

WEB

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 Lua

Javascript PHP

PHP

PHP

#include #ifdef ZTS void ***tsrm_ls; #endif /* Extension bits */ zend_module_entry php_mymod_module_entry = {

PHP

Web

PHP

TIPI:

PHP

RELEASE_2011-07-29_V0.6.7

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) { 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