zl程序教程

您现在的位置是:首页 >  后端

当前栏目

[PHP] PHP服务器接口SAPI中的结构体详解编程语言

2023-06-13 09:20:37 时间

SAPI:在各个服务器抽象层之间遵守着相同的约定,这里我们称之为SAPI接口。例如命令行程序的实现,Apache的mod_php模块实现以及fastcgi的实现等等

1.结构体:
使用结构体(Struct)来存放一组不同类型的数据
struct 结构体名{
结构体所包含的变量或数组
};
struct 结构体名 结构体变量名

2.成员的获取和赋值
结构体变量名.成员名;

3.结构体指针
struct 结构体名 *结构体变量名= 结构体变量名
使用结构体指针 == (*结构体变量名).成员名 ; 结构体变量名- 成员名

PHP源码:

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

 /* 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路径 

 ... 

 ... 

cgi_sapi_module.startup( cgi_sapi_module) // cgi模式 cgi/cgi_main.c文件 

apache2_sapi_module.startup( apache2_sapi_module); 

 // apache2服务器 apache2handler/sapi_apache2.c文件 

static sapi_module_struct apache2_sapi_module = { 

 "apache2handler", 

 "Apache 2.0 Handler", 

 php_apache2_startup, /* startup */ 

 php_module_shutdown_wrapper, /* shutdown */ 

 ... 

}

startup 当SAPI初始化时,首先会调用该函数。如果服务器处理多个请求时,该函数只会调用一次。 比如Apache的SAPI,它是以mod_php5的Apache模块的形式加载到Apache中的, 在这个SAPI中,startup函数只在父进程中创建一次,在其fork的子进程中不会调用。
activate 此函数会在每个请求开始时调用,它会再次初始化每个请求前的数据结构。
deactivate 此函数会在每个请求结束时调用,它用来确保所有的数据都,以及释放在activate中初始化的数据结构。
shutdown 关闭函数,它用来释放所有的SAPI的数据结构、内存等。
ub_write 不缓存的写操作(unbuffered write),它是用来将PHP的数据输出给客户端, 如在CLI模式下,其最终是调用fwrite实现向标准输出输出内容;在Apache模块中,它最终是调用Apache提供的方法rwrite。
sapi_error 报告错误用,大多数的SAPI都是使用的PHP的默认实现php_error。
flush 刷新输出,在CLI模式下通过使用C语言的库函数fflush实现,在php_mode5模式下,使用Apache的提供的函数函数rflush实现。
read_cookie 在SAPI激活时,程序会调用此函数,并且将此函数获取的值赋值给SG(request_info).cookie_data。 在CLI模式下,此函数会返回NULL。
read_post 此函数和read_cookie一样也是在SAPI激活时调用,它与请求的方法相关,当请求的方法是POST时,程序会操作$_POST、$HTTP_RAW_POST_DATA等变量。
send_header 发送头部信息,此方法一般的SAPI都会定制,其所不同的是,有些的会调服务器自带的(如Apache),有些的需要你自己实现(如 FastCGI)。

 

我的练习:

#include stdio.h 

int hello(int a){ 

 return a+100; 

int main(){ 

 //定义结构体 

 struct stu{ 

 char *name; 

 int age; 

 int (*sum)(int); 

 //1.赋值结构体 

 struct stu student; 

 student.age=10; 

 student.name="taoshihan"; 

 student.sum=hello; 

 //使用结构体成员 

 printf("%d /n",student.sum(20)); 

 //2.另一种赋值结构体方式 

 struct stu lstudent={ 

 "taoshihan", 

 10, 

 .sum=hello 

 printf("%s /n",lstudent.name); 

 printf("%d /n",lstudent.sum(30)); 

 //3.结构体指针 

 struct stu *rstudent= student; 

 //使用结构体指针 

 printf("%s /n",(*rstudent).name); 

 printf("%s /n",rstudent- name);