PHP拡張モジュールの動作原理
OSS推進センター 海外浩平 <kaigai@ak.jp.nec.com>
PECL (PHP Extension Community Library)
PHPからSELinuxを
呼び出すための
インターフェース群
PHPからSELinuxを
呼び出すための
インターフェース群
PHPスクリプトの実行
/usr/bin/php -q
<?
:
:
my_function();
:
:
?>
スクリプト
/usr/bin/php
インタープリタ my_module.so
my_function()
pgsql.so
pq...
zend_module_entry 構造体 (1/2)
typedef struct _zend_module_entry zend_module_entry;
struct _zend_module_entry {
:
const char ...
zend_module_entry 構造体 (2/2)
/* SELinux module entry */
zend_module_entry selinux_module_entry = {
STANDARD_MODULE_HEADER,
...
zend_function_entry構造体 (1/2)
#define INTERNAL_FUNCTION_PARAMETERS ¥
int ht, zval *return_value, zval **return_value_ptr, ¥...
zval構造体
zend_function_entry構造体 (2/2)
ZEND_BEGIN_ARG_INFO(arginfo_selinux_setenforce, 0)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()...
PHP関数はどう定義されるか?
PHP_FUNCTION(selinux_setenforce)
{
long mode;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"l", &m...
引数の受け渡し (1/2)
zend_parse_parameters() 関数
可変長引数を持ち、変換仕様に応じて、スタックに積まれた
PHP関数の引数を解釈する
変換仕様の一例
s … 文字列 (string)
l … 整数値 (long)...
引数の受け渡し (2/2)
Thread Safe Resource Manager
#ifdef ZTS
#define TSRMLS_DC , void ***tsrm_ls
#define TSRMLS_CC , tsrm_ls
#els...
配列を返す関数
方針
return_value に配列 (IS_ARRAY) をセットしてリターン
配列オブジェクトを作る方法
array_init(zval *zval, uint size); で初期化
add_assoc_xxx(zval...
参考資料
PHP Manual - A Hacker's Guide to the Zend Engine
http://usphp.com/manual/en/internals2.php
PHP Extension Development
...
Upcoming SlideShare
Loading in …5
×

OSS開発勉強会-03

1,206
-1

Published on

OSS開発勉強会-03
~PHPモジュールの書き方~

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,206
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

OSS開発勉強会-03

  1. 1. PHP拡張モジュールの動作原理 OSS推進センター 海外浩平 <kaigai@ak.jp.nec.com>
  2. 2. PECL (PHP Extension Community Library) PHPからSELinuxを 呼び出すための インターフェース群 PHPからSELinuxを 呼び出すための インターフェース群
  3. 3. PHPスクリプトの実行 /usr/bin/php -q <? : : my_function(); : : ?> スクリプト /usr/bin/php インタープリタ my_module.so my_function() pgsql.so pq_query() 拡張モジュール 拡張モジュール Zend APIZend API ビルトイン 関数
  4. 4. zend_module_entry 構造体 (1/2) typedef struct _zend_module_entry zend_module_entry; struct _zend_module_entry { : const char *name; const struct _zend_function_entry *functions; int (*module_startup_func)(INIT_FUNC_ARGS); int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); int (*request_startup_func)(INIT_FUNC_ARGS); int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS); void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS); const char *version; : };
  5. 5. zend_module_entry 構造体 (2/2) /* SELinux module entry */ zend_module_entry selinux_module_entry = { STANDARD_MODULE_HEADER, "selinux", selinux_functions, NULL, /* module_startup_func */ NULL, /* module_shutdown_func */ NULL, /* request_startup_func */ NULL, /* request_shutdown_func */ NULL, /* info_func */ NO_VERSION_YET, STANDARD_MODULE_PROPERTIES, }; #ifdef COMPILE_DL_SELINUX ZEND_GET_MODULE(selinux) #endif zend_module_entry * get_module(void) { return &name##_module_entry; } zend_module_entry * get_module(void) { return &name##_module_entry; }
  6. 6. zend_function_entry構造体 (1/2) #define INTERNAL_FUNCTION_PARAMETERS ¥ int ht, zval *return_value, zval **return_value_ptr, ¥ zval *this_ptr, int return_value_used TSRMLS_DC typedef struct _zend_function_entry { const char *fname; void (*handler)(INTERNAL_FUNCTION_PARAMETERS); const struct _zend_arg_info *arg_info; zend_uint num_args; zend_uint flags; } zend_function_entry;
  7. 7. zval構造体
  8. 8. zend_function_entry構造体 (2/2) ZEND_BEGIN_ARG_INFO(arginfo_selinux_setenforce, 0) ZEND_ARG_INFO(0, mode) ZEND_END_ARG_INFO() : zend_function_entry selinux_functions[] = { /* global state API */ PHP_FE(selinux_is_enabled, arginfo_selinux_is_enabled) PHP_FE(selinux_getenforce, arginfo_selinux_getenforce) PHP_FE(selinux_setenforce, arginfo_selinux_setenforce) : }; : PHP_FUNCTION(selinux_setenforce) { : }
  9. 9. PHP関数はどう定義されるか? PHP_FUNCTION(selinux_setenforce) { long mode; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &mode) == FAILURE) return; if (!security_setenforce(mode)) RETURN_TRUE; RETURN_FALSE; } void zif_selinux_setenforce(INTERNAL_FUNCTION_PARAMETERS) { return_value->type = IS_BOOL; return_value->value.lval = false; return; } int ht, zval *return_value, zval **return_value_ptr, ¥ zval *this_ptr, int return_value_used TSRMLS_DC
  10. 10. 引数の受け渡し (1/2) zend_parse_parameters() 関数 可変長引数を持ち、変換仕様に応じて、スタックに積まれた PHP関数の引数を解釈する 変換仕様の一例 s … 文字列 (string) l … 整数値 (long) b … 論理値 (bool) d … 浮動小数点型 (double) z … zval | … 次のパラメータは省略可能 (optional) ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) 【使用例】 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sb", &name, &length, &new_value);
  11. 11. 引数の受け渡し (2/2) Thread Safe Resource Manager #ifdef ZTS #define TSRMLS_DC , void ***tsrm_ls #define TSRMLS_CC , tsrm_ls #else #define TSRMLS_DC #define TSRMLS_CC #endif Thread-1: zend_executor_globals->argument_stack Thread-N: zend_executor_globals->argument_stack : マルチスレッドが有効なビルドでは、 PHP関数にTSRMへのポインタが渡される マルチスレッドが有効なビルドでは、 PHP関数にTSRMへのポインタが渡される zval *の配列を内包
  12. 12. 配列を返す関数 方針 return_value に配列 (IS_ARRAY) をセットしてリターン 配列オブジェクトを作る方法 array_init(zval *zval, uint size); で初期化 add_assoc_xxx(zval *zval, const char *key, xxx value); add_index_xxx(zval *zval, ulong idx, xxx value); で、配列要素を追加 (xxxの部分はデータ型) 配列として構築された zval を配列の要素としてセットする ことで、多次元配列を表現する事ができる。 array_init(return_value); for (i=0; contexts[i]; i++) { add_index_string(return_value, i, contexts[i], 1); }
  13. 13. 参考資料 PHP Manual - A Hacker's Guide to the Zend Engine http://usphp.com/manual/en/internals2.php PHP Extension Development http://www.somabo.de/talks/200510_zend_conf_php_e xtension_development.pdf

×