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));
    }
  • 相关阅读:
    HDU 4611 Balls Rearrangement 数学
    Educational Codeforces Round 11 D. Number of Parallelograms 暴力
    Knockout.Js官网学习(简介)
    Entity Framework 关系约束配置
    Entity Framework Fluent API
    Entity Framework DataAnnotations
    Entity Framework 系统约定配置
    Entity Framework 自动生成CodeFirst代码
    Entity Framework CodeFirst数据迁移
    Entity Framework CodeFirst尝试
  • 原文地址:https://www.cnblogs.com/taoshihan/p/8283482.html
Copyright © 2011-2022 走看看