zoukankan      html  css  js  c++  java
  • [PHP] PHP服务器接口SAPI中的结构体

    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 
    ",student.sum(20));
    
            //2.另一种赋值结构体方式
            struct stu lstudent={
                    "taoshihan",
                    10,
                    .sum=hello
            };
            printf("%s 
    ",lstudent.name);
            printf("%d 
    ",lstudent.sum(30));
    
            //3.结构体指针
            struct stu *rstudent=&student;
            //使用结构体指针
            printf("%s 
    ",(*rstudent).name);
            printf("%s 
    ",rstudent->name);
    
    
            //定义函数指针
            int (*h)(int)=hello;
            //使用函数指针
            printf("%d 
    ",(*h)(20));
    }
  • 相关阅读:
    安装SQLServer2000提示“无法验证产品密钥”的解决方法
    【转】SQL Server数据库开发的二十一条军规
    Asp.Net实现FORM认证的一些使用技巧
    记住window.open的用法
    VS2005的关于母版页嵌套的一个小技巧
    一种写法的区别
    问个关于VS使用上的问题
    Server.MapPath方法的应用方法
    一个关于重定向的问题研究,应该具有实用性
    象WORD一样,双击.doc的文件就自动打开WORD并编辑该文件(转)
  • 原文地址:https://www.cnblogs.com/taoshihan/p/8283482.html
Copyright © 2011-2022 走看看