久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx

php擴展與嵌入--資源數據類型2

2023-09-25    分類: 網站建設

在資源變量中存儲的復雜的數據類型通常在初始化時需要一些內存分配,CPU時間或網絡通信。但是在請求之間保留類似于數據庫連接這種資源,必須要做到持久。資源是否持久是一個必須要考慮到的因素。
首先看內存分配的問題: 在使用php的時候,偏向使用emalloc因為它是malloc的帶回收的版本。但是持久化的資源必須在請求間都存在。對于一個文件句柄類的資源來說,假如要加入一個存儲文件名的需求,那么必須在頭文件中加入如下的代碼:
typedef struct _php_sample_descriptor_data {
    char *filename;
    FILE *fp;
} php_sample_descriptor_data;
行使這個結構可以存儲文件名和文件句柄資源,從而能夠在不同的請求之間進行共享。
對應的,要在源文件中進行響應的更改:
static void php_sample_descriptor_dtor( //這個是進行資源回收的回調函數,定義在資源的初始化處。
zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
    php_sample_descriptor_data *fdata =
      (php_sample_descriptor_data*)rsrc->ptr;
    fclose(fdata->fp);
    efree(fdata->filename);
    efree(fdata);
}
這個靜態函數用來進行資源的回收,需要在初始化資源的時候進行指定回調。
進行修改后的文件打開函數,需要增添給資源分配空間的操作:
PHP_FUNCTION(sample_fopen) //修改后的fopen
{
    php_sample_descriptor_data *fdata;
    FILE *fp;
    char *filename, *mode;
    int filename_len, mode_len;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
    &filename, &filename_len,
    &mode, &mode_len) == FAILURE) {// 獲取文件名和文件長度 
        RETURN_NULL();
    }
    if (!filename_len  !mode_len) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING,
      "Invalid filename or mode length");
        RETURN_FALSE;
    }
    fp = fopen(filename, mode);
    if (!fp) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING,
      "Unable to open %s using mode %s",
      filename, mode);
        RETURN_FALSE;
    }
    fdata = emalloc(sizeof(php_sample_descriptor_data)); //給包含了文件資源和文件名的結構分配空間
    fdata->fp = fp;
    fdata->filename = estrndup(filename, filename_len);
    ZEND_REGISTER_RESOURCE(return_value, fdata,
  le_sample_descriptor); // 注冊資源
}

對于文件寫入函數fwrite同樣需要修改:
PHP_FUNCTION(sample_fwrite)
{
    php_sample_descriptor_data *fdata;
    zval *file_resource;
    char *data;
    int data_len;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
  &file_resource, &data, &data_len) == FAILURE ) {
        RETURN_NULL();
    }
    ZEND_FETCH_RESOURCE(fdata, php_sample_descriptor_data*,
        &file_resource, -1,
        PHP_SAMPLE_DESCRIPTOR_RES_NAME, le_sample_descriptor);
    RETURN_LONG(fwrite(data, 1, data_len, fdata->fp));
} 

對于sample_fclose函數并不需要改變什么,因為它沒有操作現實的資源。下面這個函數可以從資源中拿到原本的文件名:
PHP_FUNCTION(sample_fname)
{
    php_sample_descriptor_data *fdata;
    zval *file_resource;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
  &file_resource) == FAILURE ) {
        RETURN_NULL();
    }
    ZEND_FETCH_RESOURCE(fdata, php_sample_descriptor_data*,
        &file_resource, -1,
        PHP_SAMPLE_DESCRIPTOR_RES_NAME, le_sample_descriptor);
    RETURN_STRING(fdata->filename, 1);
} 


在完成了內存分配之后,因為必須保持持久化,所以必須延遲析構
對于非持久的資源來說,一旦存放著資源id的變量被unset或fallen out of scope了,那么它們就被從EG(regular_list)中去除掉了。而EG(persistent_list)中使用的索引是鍵值類的,元素在請求的不會不會被主動的去除掉。只有在zend_hash_del()調用或線程/進程完全關閉的情況下才會消弭。 EG(persistent_list)也有dtor方法,但是是zend_register_list_descructors_ex()的第二個參數。一般來說,非持久和持久的資源會被注冊成兩種類型,有的時候也可以合二為一。現在在sample.c中添加一個持久的資源類型。
    static int le_sample_descriptor_persist;
    static void php_sample_descriptor_dtor_persistent(
zend_rsrc_list_entry *rsrc TSRMLS_DC)
{//這是一個持久化的資源析構函數
    php_sample_descriptor_data *fdata =
      (php_sample_descriptor_data*)rsrc->ptr;
    fclose(fdata->fp);
    pefree(fdata->filename, 1);
    pefree(fdata, 1);
}
PHP_MINIT_FUNCTION(sample)
{
    le_sample_descriptor =     zend_register_list_destructors_ex(
  php_sample_descriptor_dtor, NULL,
  PHP_SAMPLE_DESCRIPTOR_RES_NAME, module_number);
    le_sample_descriptor_persist =
    zend_register_list_destructors_ex(
  NULL, php_sample_descriptor_dtor_persistent,
  PHP_SAMPLE_DESCRIPTOR_RES_NAME, module_number);//注冊一個持久化的資源
    return SUCCESS;
} 

下面的這個fopen函數就兼容了持久與非持久的兩個資源類型:
PHP_FUNCTION(sample_fopen)
{
    php_sample_descriptor_data *fdata;
    FILE *fp;
    char *filename, *mode;
    int filename_len, mode_len;
    zend_bool persist = 0;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"ssb",
      &filename, &filename_len, &mode, &mode_len,
      &persist) == FAILURE) {
        RETURN_NULL();
    }
    if (!filename_len  !mode_len) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING,
      "Invalid filename or mode length");
        RETURN_FALSE;
    }
    fp = fopen(filename, mode);
    if (!fp) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING,
      "Unable to open %s using mode %s",
      filename, mode);
        RETURN_FALSE;
    }
    if (!persist) {//非持久化的資源
        fdata = emalloc(sizeof(php_sample_descriptor_data));
        fdata->filename = estrndup(filename, filename_len);//這個做了申請內存和賦值兩步操作 
        fdata->fp = fp;
        ZEND_REGISTER_RESOURCE(return_value, fdata,
  le_sample_descriptor);
    } else {//持久化的資源
        list_entry le;
        char *hash_key;
        int hash_key_len;
        fdata =pemalloc(sizeof(php_sample_descriptor_data),1);
        fdata->filename = pemalloc(filename_len + 1, 1);
        memcpy(fdata->filename, filename, filename_len + 1);
        fdata->fp = fp;
        ZEND_REGISTER_RESOURCE(return_value, fdata,
    le_sample_descriptor_persist);

        /* Store a copy in the persistent_list 在persistent_list存儲一份副本 */
        le.type = le_sample_descriptor_persist;
        le.ptr = fdata;
        hash_key_len = spprintf(&hash_key, 0,
      "sample_descriptor:%s:%s", filename, mode);
        zend_hash_update(&EG(persistent_list),
  hash_key, hash_key_len + 1,
  (void*)&le, sizeof(list_entry), NULL);
        efree(hash_key);
    }
} 

對于非持久化的資源,給定了一個數字的索引,并存放在了跟請求依存的list中。 對于持久化的資源,給定了一個鍵值類型,這個hashkey可以在接下來的請求中被重新得到。然后把資源放進了persistentlist中。當一個持久的資源out of scope的時候,EG(regular_list)的析構函數會為le_sample_descriptro_persist檢查registerlist析構。發現是NULL的話不會有任何的操作。從而也就保證了持久的資源不會被釋放掉。當資源被從EG(persistent_list)中去除的時候,要么是線程進程結束了,要么是有心刪除掉了。這時候就會去找持久化的析構函數。

資源被申請為持久化的原因就是為了在其他的請求中可以復用
假如想要復用持久化的資源,那就一定要用到hash_key,當sample_fopen被調用的時候,函數會行使請求的文件名和模式重新創建hash_key,然后嘗試在persistent_list中找到它。
PHP_FUNCTION(sample_fopen)
{
    php_sample_descriptor_data *fdata;
    FILE *fp;
    char *filename, *mode, *hash_key;
    int filename_len, mode_len, hash_key_len;
    zend_bool persist = 0; //判斷是否持久
    list_entry *existing_file;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"ssb",
      &filename, &filename_len, &mode, &mode_len,
      &persist) == FAILURE) {
        RETURN_NULL();
    }
    if (!filename_len  !mode_len) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING,
      "Invalid filename or mode length");
        RETURN_FALSE;
    }
    /* 通過獲得一個hash_key嘗試尋找一個已經打開的文件 */
    hash_key_len = spprintf(&hash_key, 0,
  "sample_descriptor:%s:%s", filename, mode);

    if (zend_hash_find(&EG(persistent_list), hash_key,
  hash_key_len + 1, (void **)&existing_file) == SUCCESS) {
        /* 成功的找到了這個已經打開的文件句柄資源 */
        ZEND_REGISTER_RESOURCE(return_value,
  existing_file->ptr, le_sample_descriptor_persist);
        efree(hash_key);
        return;
    }
    fp = fopen(filename, mode);
    if (!fp) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING,
      "Unable to open %s using mode %s",
      filename, mode);
        RETURN_FALSE;
    }
    if (!persist) {
        fdata = emalloc(sizeof(php_sample_descriptor_data));
        fdata->filename = estrndup(filename, filename_len);
        fdata->fp = fp;
        ZEND_REGISTER_RESOURCE(return_value, fdata,
  le_sample_descriptor);
    } else {
        list_entry le;
        fdata =pemalloc(sizeof(php_sample_descriptor_data),1);
        fdata->filename = pemalloc(filename_len + 1, 1);
        memcpy(data->filename, filename, filename_len + 1);
        fdata->fp = fp;
        ZEND_REGISTER_RESOURCE(return_value, fdata,
    le_sample_descriptor_persist);
        /* Store a copy in the persistent_list */
        le.type = le_sample_descriptor_persist;
        le.ptr = fdata;
        /* hash_key has already been created by now */
        zend_hash_update(&EG(persistent_list),
  hash_key, hash_key_len + 1,
  (void*)&le, sizeof(list_entry), NULL);
    }
    efree(hash_key);
}

注重因為所有的擴展都使用相同的哈希表單去存儲資源,所以命名很主要。一般都是用擴展和資源類型名作為前綴。

檢查資源可用性:
盡管像文件這種資源可以長期打開,但是類似遠程網絡資源這種假如在請求之間長期不用的話就有問題。所以在使用一個persistent資源之前,要先確定可用性。
if (zend_hash_find(&EG(persistent_list), hash_key,
        hash_key_len + 1, (void**)&socket) == SUCCESS) {
    if (php_sample_socket_is_alive(socket->ptr)) {
        ZEND_REGISTER_RESOURCE(return_value,
socket->ptr, le_sample_socket);
        return;
    }
    zend_hash_del(&EG(persistent_list),
        hash_key, hash_key_len + 1); //這里會去調用之前注冊好的析構函數
}









分享標題:php擴展與嵌入--資源數據類型2
本文URL:http://www.js-pz168.com/news31/283731.html

成都網站建設公司_創新互聯,為您提供網站建設面包屑導航、App設計、軟件開發、品牌網站制作品牌網站建設

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站托管運營
久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx
狠狠色丁香婷婷综合久久片| 国产凹凸在线观看一区二区| 国产乱人伦偷精品视频免下载| 福利一区二区在线| http;//www.99re视频| 精品91免费| 亚洲欧美日韩精品综合在线观看| 欧美亚洲国产一区二区三区va | 精品亚洲成a人在线观看 | 欧美三电影在线| 精品福利视频一区二区三区| 中文字幕在线不卡一区| 日日夜夜精品视频免费| 精品亚洲欧美一区| 91麻豆国产福利在线观看| 欧美一区二区三区精美影视 | 欧美色综合网站| 欧美精品一区二区三区四区 | 五月婷婷一区| 91精品国产综合久久精品app | 精品不卡在线| 日本高清不卡在线观看| 精品国产凹凸成av人网站| 国产精品久久久久久久久晋中 | 99精品国产视频| 亚洲精品日韩成人| 久久久久一区二区三区四区| 天堂va蜜桃一区二区三区| 不卡大黄网站免费看| 亚洲精品乱码视频| 久久久99久久| 麻豆精品视频在线| 久久国产精品99久久久久久丝袜 | 亚洲国产一区二区三区在线| 日韩美女视频一区二区在线观看| 亚洲午夜视频在线| 114国产精品久久免费观看| 欧洲av在线精品| 最新久久zyz资源站| 国产成人av一区二区三区在线观看| 日本黑人久久| 国产亚洲欧美色| 国产在线观看一区二区| 日韩欧美亚洲在线| 久久精子c满五个校花| 激情综合色综合久久| 欧美日韩精品免费观看视一区二区| 欧美一级一级性生活免费录像| 亚洲成人精品影院| 国产69精品久久久久9999apgf | 狠狠色丁香久久婷婷综| 日韩精品电影网站| 欧美激情一区二区| 国产99精品在线观看| 自拍偷拍99| 亚洲精品乱码久久久久| 99视频在线免费观看| 91精品国产色综合久久| 日本vs亚洲vs韩国一区三区二区 | 欧美久久久影院| 午夜精品福利在线| 精品国产乱码久久久久软件| 欧美精品一区二区三区一线天视频| 久草这里只有精品视频| 亚洲欧洲一区二区福利| 国产精品乱码一区二区三区软件| 成人综合在线观看| 欧美日韩日日摸| 午夜精品久久久久久久99水蜜桃| 久久国产欧美精品| 国产欧美一区二区三区在线看蜜臀| 国产激情视频一区二区三区欧美| 91久久精品一区二区| 亚洲午夜在线电影| 鲁片一区二区三区| 国产精品日韩精品欧美在线| av在线免费不卡| 欧美一区二区视频在线观看2020| 久久疯狂做爰流白浆xx| 中文字幕在线中文字幕日亚韩一区| 一区二区三区鲁丝不卡| 精品1区2区| 国产精品人妖ts系列视频| 91亚洲国产成人精品一区二三 | 色婷婷av一区| 亚洲国产视频a| 日本黑人久久| 一区二区三区中文字幕电影| 精品国产乱码久久久久久丨区2区| 国产午夜精品久久久久久免费视 | 久久伊人蜜桃av一区二区| 国产成人精品1024| 欧美伦理影视网| 韩国女主播一区二区三区| 欧美最猛黑人xxxxx猛交| 日本中文字幕不卡| 中文字幕一区二区三区有限公司| 亚洲成a人片在线观看中文| 青娱乐国产91| 一区二区三区日本| 欧美一级二级三级九九九| 中文字幕日韩一区二区| 精品国产一区二区三区麻豆小说| 中文字幕不卡三区| 国产欧美亚洲日本| 国产精品福利一区二区| 国产一区二区精品免费| 中文字幕在线不卡一区| 久久精品国产综合精品 | 欧美一级二级在线观看| 国产风韵犹存在线视精品| 欧美一区二区三区影视| 高清国产午夜精品久久久久久| 日韩视频一区二区| 99久久精品国产一区二区三区| xf在线a精品一区二区视频网站| 91网址在线看| 中文字幕av免费专区久久| 国产伦精品一区二区三区视频免费 | 麻豆精品视频在线| 欧美乱妇23p| 国产91丝袜在线18| 久久理论电影网| 国产欧美亚洲日本| 亚洲老妇xxxxxx| 亚洲第一综合| 麻豆成人av在线| 欧美一级夜夜爽| 91免费精品国自产拍在线不卡| 中文字幕免费不卡在线| 欧美精品一区三区在线观看| 亚洲成av人片在线观看| 在线观看免费视频综合| 国产精品一区2区| 久久伊99综合婷婷久久伊| 国产欧美丝袜| 亚洲第一二三四区| 欧美无人高清视频在线观看| 成人自拍视频在线| 国产欧美精品区一区二区三区| 久久精品日产第一区二区三区乱码 | 国产精品久久久久久妇女6080| 日本黄网免费一区二区精品| 视频在线观看91| 欧美二区在线观看| 91亚洲国产成人精品一区二区三 | 国产精品综合在线视频| 久久先锋影音av鲁色资源| 国产日韩欧美精品| 亚洲国产欧美在线人成| 欧美午夜片在线看| www.av亚洲| 中文字幕一区二区三区色视频| 日韩在线电影一区| 久久精品99久久久| 2021中文字幕一区亚洲| 久久狠狠久久综合桃花| 日本欧美肥老太交大片| 欧美mv和日韩mv国产网站| 国产乱码一区| 视频一区二区不卡| 日韩欧美中文字幕精品| 黄色99视频| 蜜臀av在线播放一区二区三区| 精品免费国产一区二区三区四区| 精品久久中出| 久久机这里只有精品| www激情久久| 少妇精品久久久久久久久久| 国产一区二区三区香蕉| 亚洲国产精品成人综合色在线婷婷 | 一区2区3区在线看| 欧美精品乱人伦久久久久久| 成人h在线播放| 日韩有码一区二区三区| 欧美va亚洲va国产综合| 欧美日韩国产高清视频| 国产综合久久久久久久久久久久| 亚洲国产精品黑人久久久| 国产91对白在线观看九色| 国产精品欧美一区二区三区| 一本一道久久a久久精品综合蜜臀| 成人网页在线观看| 尤物在线观看一区| 九色91在线视频| av一区观看| 亚洲国产欧美不卡在线观看| 国产美女主播视频一区| 国产精品的网站| 欧美日韩卡一卡二| 国产欧美综合精品一区二区| 久久精品国产亚洲一区二区三区| 国产亚洲精品资源在线26u| 制服诱惑一区| 国产成人女人毛片视频在线| 免费xxxx性欧美18vr| 国产精品嫩草影院av蜜臀| 欧美日韩一区二区在线观看视频 | 精品国产电影一区二区| 亚洲一区精彩视频|