久久福利影视-久久成人综合网-久久成人亚洲-久久成人性色生活片-免费的黄色小视频-免费的黄视频

蒙狼科技logo
設為首頁| 聯系我們
咨詢熱線: 13917498722
  您的位置: 首頁 > 網站資訊 > php擴展與嵌入--資源數據類型2

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

發布日期:2017/7/26
在資源變量中存儲的復雜的數據類型通常在初始化時需要一些內存分配,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); //這里會去調用之前注冊好的析構函數
}













其他相關文章
  • 網站遷移的那些事
  • 了解網站影響力的不同階段
  • 干貨分享比較火的APP推廣方法
  • 網站建設基礎知識之老板們應該細致哪些?
  • 企業建網站要從這九方面入手
  • 天也網絡做網站技巧之內容原創




  • 企業網站后臺使用
    購物網站后臺使用
    網站產品圖片的處理



    農業銀行支付
    建設銀行支付
    郵政儲蓄銀行支付



    企業網站建設
    整站建設
    購物網站



    企業網站建設建議
    注冊適合自己的域名
    什么是虛擬主機




    售前咨詢QQ: 838821345
    售后服務QQ: 464698733
    應急手機:13917498722


    微信掃一掃
    添加24小時微信客服


    郵箱:lang@MENGL.CN
    地址:上海寶山區城銀路555弄2號樓3樓
    ICP備案:滬ICP備12042844號-3
     滬公網安備:31011402002917號
    做網站 | 企業網站建設 | 上海做網站 | 企業網站制作 | 做網站的公司 | 關于蒙狼 | 整站建設 | 購物網站 | 企業網絡營銷 | 成功案例 | 加盟代理 | 在線訂單
    服務區域: 臨港新區做網站 徐匯做網站 閔行做網站 長寧做網站 虹口做網站 黃浦做網站 盧灣做網站 靜安做網站 浦東做網站 楊浦做網站 普陀做網站 閘北做網站 寶山做網站 嘉定做網站 松江做網站 昆山做網站
    Copyright 2012-2025 上海蒙狼網絡科技有限公司 www.133985.com All Rights Reserved
    性色AV无码专区亚洲AV毛片子| 久久AV伊人蜜臀一区二区| 玩弄肥美高大的熟妇| 国产成在线观看免费视频成本人| 亚洲 校园 欧美 国产 另类 | 国产成人18黄网站免费观看| 亚洲AV无码一区二区二三区入口| 噜噜噜亚洲色成人网站| 爸爸你不能谢在里面来| 午夜宅男在线永久免费观看网| 久久久久影院美女国产主播| 巴西大屁股妓女BBW| 小雪你的奶好大把腿张开| 久久水蜜桃亚洲AV无码精品麻豆| 把她按在桌上疯狂顶撞| 午夜精品久久久久久久无码| 护士的小嫩嫩好紧好爽| 47147人文艺术欣赏| 天堂А√在线地址资源| 久久精品人妻一区二区三区av| YSL小金管水蜜桃色| 性色AV一区二区三区咪爱四虎| 局长趴在雪白的身上耸动| 从大树开始的进化漫画| 亚洲国产精品悠悠久久琪琪| 欧美黑人XXXX高潮猛交| 国产乱子伦一区二区三区=| 在线 | 一区二区三区| 色噜噜狠狠色综合久色AⅤ网黑| 狠狠色噜噜狠狠狠狠7777| FREE性满足VIDE0SHD| 性色AⅤ无码久久久久久精品 | 久久99久国产麻精品66| 宝贝你夹得太紧了我都要断了| 亚洲AV无码久久久久久精品同性| 你的奶好大让老子摸摸的说说| 不卡无码人妻一区二区三区| 亚洲插肏熟女人妇的屄网址| 欧美日韩人妻精品一区二区在线| 国产调教性奴在线观看W| 6080电影网站| 驯服人妻HD中字日本| 内射极品少妇一区二区av| 国产精品夜间视频香蕉 | 午夜不卡久久精品无码免费| 麻豆WWW传媒入口| 国产精华最好的产品有哪些| 中文字幕AⅤ人妻一区二区| 无码AV在线一区二区| 免费网站正能量WWW正能量| 国产精品一区二区香蕉| 99精品国产福久久久久久| 亚洲AV日韩AV高潮潮喷无码| 欧洲美女粗暴交视频| 精产国品一二二线三线区别| 成人区人妻精品一区二| 亚洲综合AV色婷婷国产野外| 人妻精品久久无码区| 精品成人免费一区二区| 成人午夜亚洲精品无码区| 亚洲午夜性猛春交XXXX| 少妇被粗大的猛烈进出视频| 久久亚洲AV午夜福利精品一区| 国产高清在线精品一区二区三区| 中文字幕在线观看| 天天摸天天做天天爽水多| 免费高清A级毛片在线播放| 国产XXXX99真实实拍| 中文字幕天天躁日日躁狠狠躁免费| 无码人妻精品一区二区三区免费看 | 亚洲丰满少妇多毛大隂户 | 美国6一12呦女精品| 丰满熟妇BBWBBWBBWBB| 曰韩精品无码一区二区三区视频| 色婷婷一区二区三区四区成人网| 局长从后面握住我的奶| 国产乱亲BBBB| 宝宝又大了1V1| 一本大道东京热无码| 无人高清影视在线观看| 免费十大软件大全下载安装| 国内ZOOM人与ZOOM| 成熟人妻AV无码专区| 制服视频在线一区二区| 亚洲AV纯肉无码精品动漫| 日产无人区一线二线三线小说| 精品国产性色无码AV网站| 丰满熟女高潮毛茸茸欧洲视频| 中文无码人妻有码人妻中文字幕| 亚洲AV无码久久精品蜜桃播放| 日韩AV无码一区二区三区不卡| 久久熟妇一区二区三区紧湿 | 日韩一中文字无码不卡| 美女扒开屁股让男人桶GIF动态 | 在线观看免费A∨网站| 亚洲AV成人综合网| 色婷婷综合久久久久中文一区二区| 蜜臀AV在线无码国产| 激情射精爆插热吻无码视频| 国产AⅤ激情无码久久久无码| 99热这里只有精品免费播放| 亚洲综合另类小说色区一| 双腿被绑成M型调教PⅠAY照片| 久久香蕉国产线看观看怡红院妓院| 国产强伦姧在线看无码| 从厨房一路顶撞到卧室门好吗| 97SE亚洲国产综合自在线不卡| 亚洲色AV天天天天天天| 熟女乱色一区二区三区| 破外女出血视频全过程| 邻居少妇很紧毛多水多| 娇妻被领导抱进卧室| 国产精品无码免费专区午夜| AV永久天堂一区二区三区香港| 一本大道久久东京热无码AV| 亚洲AV纯肉无码精品动漫| 四虎成人精品一区二区免费网站 | 人妻厨房出轨上司HD院线| 老师粉嫩小泬喷水视频90| 精品国产成人A区在线观看| 国产精品自在线拍国产手机版| 大陆少妇XXXX做受| VODAFONEWIFI性另类| 亚洲中文久久精品无码照片| 亚洲AV免费高潮喷水| 天天躁日日躁狠狠躁AV中文| 日韩一区二区三区无码影院| 欧美熟女一区二区三区| 免费观看高清日本AⅤ| 久久亚洲AV无码AV男人的天堂| 精品国产精品久久一区免费式| 国产亚洲午夜高清国产拍精品 | 草莓丝瓜榴莲绿巨人WWW| 又爽又刺激免费男女视频| 亚洲区色情区激情区小说色情书| 亚洲AⅤ中文无码字幕色| 偷拍精品视频一区二区三区| 色欲老女人人妻综合网| 欧美乱大交XXXXX潮喷| 免费观看美女裸体的网站| 久久久久亚洲AV成人网人人| 精品无码久久久久久久久| 黑人玩弄漂亮少妇高潮大叫| 国产玉足榨精视频在线观看| 国产精品免费精品自在线观看| 国产成人午夜在线视频A站 | 少妇呻吟喷水视频正在播放| 日韩精品无码一区二区三区AV | 18禁无遮挡啪啪无码网站| 欲香欲色天天天综合和网| 一本久久综合亚洲鲁鲁五月天| 亚洲午夜福利AV一区二区无码| 亚洲欧美成人精品香蕉网| 掀开老师的裙子挺进去| 无码人妻巨屁股系列大又挺拔 | 国产高清免费AV片在线观看不卡| 丰满护士巨好爽好大乳小说| 大肉大捧一进一出的视频| 村长压在小雪身上耕耘视频| 成熟人妻换╳╳╳╳| 刺激交换经历过程小说| 刺骨PO不吃肉干嘛| 丰满妇女强高潮18ⅩXXX在线| 丰满的少妇愉情HD高清果冻传媒| 丰满人妻一区二区三区免费视频 | 人妻少妇中文字幕| 人妻体内射精一区二区| 女教师娇喘潮喷抽搐在线视频| 久久久久久精品国产亚洲AV麻豆 | 亚洲熟妇丰满XXXXX黑| 亚洲无熟妇成人无码| 伊人久久大香线蕉AV色婷婷色 | 亚洲成AV人片一区二区小说| 亚洲国产成人无码网站大全| 亚洲乱码日产精品BD在线观看| 亚洲人成网站18禁止影院| 亚洲综合精品第一页| 在线观看亚洲AV每日更新| 性欧美一区二区三区| 与亲女洗澡时伦了毛片| 真实国产乱啪福利露脸| 2022最新韩国理伦片在线观看| 2012电影在线观看神马影院| 99久久免费国产精品| 啊灬啊灬啊灬快灬高潮了女| 成人午夜精品久久久久久久| 国产成人片AⅤ在线观看| 国产人无码A在线西瓜影音| 狠狠色噜噜狠狠狠888米奇| 久久精品国产免费观看| 麻豆一二三区AV精品传媒| 欧美ZC00O人与善交| 女人无遮挡无内衣内裤网站| 人妻AⅤ中文字幕| 色综合视频一区二区三区| 无码中文国产不卡视频| 亚洲国产精品久久久久4婷婷| 亚洲制服丝袜中文字幕在线| 中英字幕乱码在线观看| 宝宝才两根手指就疼哭了怎么回事 |