国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

開(kāi)發(fā)中proc文件系統(tǒng)的簡(jiǎn)單使用

這篇具有很好參考價(jià)值的文章主要介紹了開(kāi)發(fā)中proc文件系統(tǒng)的簡(jiǎn)單使用。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

使用proc文件系統(tǒng)



在Linux系統(tǒng)中, “/proc”文件系統(tǒng)十分有用, 它被內(nèi)核用于向用戶導(dǎo)出信息。 “/proc”文件系統(tǒng)是一個(gè)虛擬文件系統(tǒng), 通過(guò)它可以在Linux內(nèi)核空間和用戶空間之間進(jìn)行通信。 在/proc文件系統(tǒng)中, 我們可以將對(duì)虛擬文件的讀寫作為與內(nèi)核中實(shí)體進(jìn)行通信的一種手段, 與普通文件不同的是, 這些虛擬文件的內(nèi)容都是動(dòng)態(tài)創(chuàng)建的。

“/proc”下的絕大多數(shù)文件是只讀的, 以顯示內(nèi)核信息為主。 但是“/proc”下的文件也并不是完全只讀的, 若節(jié)點(diǎn)可寫, 還可用于一定的控制或配置目的, 例如前面介紹的寫/proc/sys/kernel/printk可以改變printk() 的打印級(jí)別。

Linux系統(tǒng)的許多命令本身都是通過(guò)分析“/proc”下的文件來(lái)完成的, 如ps、 top、 uptime和free等。 例如, free命令通過(guò)分析/proc/meminfo文件得到可用內(nèi)存信息, 下面顯示了對(duì)應(yīng)的meminfo文件和free命令的結(jié)果。

1.meminfo文件

開(kāi)發(fā)中proc文件系統(tǒng)的簡(jiǎn)單使用,Linux驅(qū)動(dòng),驅(qū)動(dòng)開(kāi)發(fā),linux,arm開(kāi)發(fā),驅(qū)動(dòng)開(kāi)發(fā),嵌入式,調(diào)試

2. free命令

開(kāi)發(fā)中proc文件系統(tǒng)的簡(jiǎn)單使用,Linux驅(qū)動(dòng),驅(qū)動(dòng)開(kāi)發(fā),linux,arm開(kāi)發(fā),驅(qū)動(dòng)開(kāi)發(fā),嵌入式,調(diào)試

3、創(chuàng)建 /proc 節(jié)點(diǎn)

  • struct proc_dir_entry
    內(nèi)核使用
    proc_dir_entry 結(jié)構(gòu)體來(lái)描述
    /proc 文件系統(tǒng)中的一個(gè)目錄或者文件節(jié)點(diǎn)
/* 進(jìn)程目錄項(xiàng)結(jié)構(gòu)體 /
struct proc_dir_entry {
    unsigned int low_ino; / 低位 inode 編號(hào) /
    umode_t mode; / 文件訪問(wèn)權(quán)限 /
    nlink_t nlink; / 鏈接計(jì)數(shù) /
    kuid_t uid; / 用戶 ID /
    kgid_t gid; / 組 ID /
    loff_t size; / 文件大小 */
    const struct inode_operations proc_iops; / inode 操作函數(shù)集指針 */
    const struct file_operations proc_fops; / 文件操作函數(shù)集指針 */
    struct proc_dir_entry *next, *parent, subdir; / 目錄項(xiàng)指針 */
    void data; / 自定義數(shù)據(jù)指針 /
    atomic_t count; / 使用計(jì)數(shù) /
    atomic_t in_use; / 調(diào)用模塊的進(jìn)程數(shù);負(fù)數(shù)表示正在卸載 */
    struct completion pde_unload_completion; / 卸載完成信號(hào)量指針 /
    struct list_head pde_openers; / 打開(kāi)文件的進(jìn)程鏈表頭 /
    spinlock_t pde_unload_lock; / 卸載鎖 /
    u8 namelen; / 名稱長(zhǎng)度 /
    char name[]; / 名稱 */
};
  • proc_create
    內(nèi)核提供了一套
    API用于在
    proc 文件系統(tǒng)中創(chuàng)建 文件節(jié)點(diǎn)
    /目錄:
static struct proc_dir_entry *proc_create(  const char *name, umode_t mode,
                                            struct proc_dir_entry *parent, 
                const struct file_operations *proc_fops);    
                                            
@ name: 節(jié)點(diǎn)名
@ mode:    權(quán)限位
@ parent:父目錄
@ proc_fops: 文件操作結(jié)構(gòu)體

    struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);

@ name: 目錄名
@ parent:父目錄
  • remove_proc_entry()
    內(nèi)核提供
    remove_proc_entry 來(lái)移除
    proc 文件系統(tǒng)中的 文件
    /目錄 項(xiàng):
void remove_proc_entry(const char *name, struct proc_dir_entry *parent);

@ name: 文件/目錄 名
@ parent:父目錄

4、使用 file_operations 實(shí)現(xiàn) proc 文件讀寫 導(dǎo)向內(nèi)核信息

在調(diào)用 proc_create() 創(chuàng)建文件項(xiàng)時(shí), 提供了一個(gè) file_operations結(jié)構(gòu)體, 實(shí)現(xiàn)里面的read, write方法即可實(shí)現(xiàn)proc 文件讀寫,demo 程序如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <asm/stat.h>
#include <linux/proc_fs.h>

MODULE_LICENSE("GPL");

#define LOG_TAG    "my_test1: "

static char my_buf[256];

//====================================================================================
static ssize_t my_proc_read(struct file *fp, char __user *buf, size_t size, loff_t *pos)
{
    int len = strlen(my_buf);

    pr_info(LOG_TAG "enter %s()\n", __func__);

    if( 0 == *pos )    {
        strncpy(buf, my_buf, sizeof(my_buf));
        *pos += len;
        return len;
    } else
        return 0;
}

static ssize_t my_proc_write(struct file *file,  const char __user *buf, size_t size, loff_t *pos)
{
    int len = size < sizeof(my_buf) ? size : sizeof(my_buf);

    pr_info(LOG_TAG "enter %s()\n", __func__);

    if( 0 == *pos)    {
        memset(my_buf, '\0', sizeof(my_buf));
        len = copy_from_user(my_buf, buf, len);
        *pos += len;
        my_buf[len - 1] = '\0';
        return size;
    }else 
        return 0;
}


static struct file_operations my_file_ops = {
    .owner     = THIS_MODULE,
    .read     = my_proc_read,
    .write     = my_proc_write,
};

//====================================================================================
static int __init my_module_init(void)
{
    struct proc_dir_entry * my_proc_node = NULL;

    pr_info(LOG_TAG "enter %s()\n", __func__);

    my_proc_node = proc_create("my_test1", S_IRUGO | S_IWUGO, NULL, &my_file_ops);
    if( NULL == my_proc_node )    {
        pr_err(LOG_TAG "creat /proc/my_test1 failed\n");
        remove_proc_entry("my_test1", NULL);
        return -1;
    }

    pr_info(LOG_TAG "creat /proc/my_test1 success\n");
    return 0;
}

static void __exit my_module_exit(void)
{
    pr_info(LOG_TAG "enter %s()\n", __func__);

    pr_info(LOG_TAG "remove /proc/my_test1\n");
    remove_proc_entry("my_test1", NULL);
}

module_init(my_module_init);
module_exit(my_module_exit);

5、使用 seq_file 實(shí)現(xiàn) proc 文件的讀取

seq_file只是在普通的文件read中加入了內(nèi)核緩沖的功能,從而實(shí)現(xiàn)順序多次遍歷,讀取大數(shù)據(jù)量的簡(jiǎn)單接口。內(nèi)核使用 seq_file 結(jié)構(gòu)體來(lái)描述seq_file:

/* 序列文件結(jié)構(gòu)體 */
struct seq_file {
    char buf; / 緩沖區(qū)指針 /
    size_t size; / 緩沖區(qū)大小 /
    size_t from; / 開(kāi)始位置 /
    size_t count; / 計(jì)數(shù)器 /
    loff_t index; / 索引 /
    loff_t read_pos; / 讀取位置 /
    u64 version; / 版本號(hào) /
    struct mutex lock; / 互斥鎖 */
    const struct seq_operations op; / 序列操作函數(shù)集指針 /
    int poll_event; / poll() 事件 */
    #ifdef CONFIG_USER_NS
    struct user_namespace user_ns; / 用戶命名空間 */
    #endifvoid private; / 私有數(shù)據(jù)指針 */
};

seq_file一般只提供只讀接口,在使用seq_read時(shí),主要靠下述四個(gè)操作來(lái)完成內(nèi)核自定義緩沖區(qū)的遍歷的輸出操作,其中pos作為遍歷的iterator,在seq_read函數(shù)中被多次使用,用以定位當(dāng)前從內(nèi)核自定義鏈表(不止是鏈表, 還可以是哈希表, 數(shù)組, 紅黑樹)中讀取的當(dāng)前位置,當(dāng)多次讀取時(shí),pos非常重要,且pos總是遵循從0,1,2…end+1遍歷的次序,其即必須作為遍歷內(nèi)核自定義鏈表的下標(biāo),也可以作為返回內(nèi)容的標(biāo)識(shí)。但是我在使用中僅僅將其作為返回內(nèi)容的標(biāo)示,并沒(méi)有將其作為遍歷鏈表的下標(biāo),從而導(dǎo)致返回?cái)?shù)據(jù)量大時(shí)造成莫名奇妙的錯(cuò)誤,注意:start返回的void*v如果非0,被show輸出后,在作為參數(shù)傳遞給next函數(shù),next可以對(duì)其修改,也可以忽略;當(dāng)next或者start返回NULL時(shí),在seq_open中控制路徑到達(dá)seq_end。

struct seq_operations {
    void * (*start) (struct seq_file *m, loff_t *pos);
    void (*stop) (struct seq_file *m, void *v);
    void * (*next) (struct seq_file *m, void *v, loff_t *pos);
    int (*show) (struct seq_file *m, void *v);
};

在讀取 proc file 時(shí):

  • 如果只有一條記錄, 調(diào)用過(guò)程是:
    start->show->stop,
    start->stop.
  • 如果有多條記錄并且能通過(guò)緩沖區(qū)一次傳第完, 調(diào)用過(guò)程是,繼續(xù)
    start->show->next->show->next-> … ->nex->show->stop,
    start->stop .
  • 如果有多條記錄, 比且不能一次通過(guò)緩沖區(qū)傳送完成, 調(diào)用過(guò)程是:
    start->show->next->show->…->show->stop,
    start->show->next->show->…->show->stop, … , start->stop.

seq_file 的緩沖區(qū)通常為1K, 但是會(huì)動(dòng)態(tài)增長(zhǎng)以便能容納至少一條記錄(當(dāng)單條記錄的大小大于1頁(yè)的時(shí)候,這個(gè)就很有用), 通常, 應(yīng)該在start中進(jìn)行必要的加鎖, 在stop中進(jìn)行必要的解鎖一邊避免竟態(tài)。
當(dāng)使用seq_read時(shí), 需要實(shí)現(xiàn)seq_operations, 并且將file和seq_file關(guān)聯(lián)起來(lái)(通常在open操作中進(jìn)行), 同時(shí), seq_file也提供了游離的 seq_lseek, seq_release用于支持llseek和release操作。
使用seq_file 的demo如下:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-793349.html

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <asm/stat.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

#define LOG_TAG    "my_test2: "

MODULE_LICENSE("GPL");

static char my_buf[][32] = {    {"i am the 0th record"},    //buf[0]
                {"i am the 1th record"},    //buf[1]
                {"i am the 2th record"},    //buf[2]
                {"i am the 3th record"},    //buf[3]
                {"i am the 4th record"},    //buf[4]
};

//==========================================================================
static void* my_seq_start (struct seq_file *m, loff_t *pos)
{
    pr_info(LOG_TAG "enter %s()\n", __func__);

    if( *pos < 0 || *pos > 4 /*my_buf[][32] index*/)    {
        pr_err(LOG_TAG "invalid pos %ld\n", (long)*pos);
        return NULL;
    }else    
        return my_buf[*pos];
}

static void my_seq_stop (struct seq_file *m, void *v)
{
    pr_info(LOG_TAG "enter %s()\n", __func__);
    pr_info(LOG_TAG "do nothing\n");
}

static void* my_seq_next (struct seq_file *m, void *v, loff_t *pos)
{
    pr_info(LOG_TAG "enter %s()\n", __func__);

    if( ++(*pos) < 0  || *pos > 4 /*my_buf[][32] index*/)    {
        pr_info(LOG_TAG "end\n");
        return NULL;
    }else
        return my_buf[*pos];
}

static int my_seq_show (struct seq_file *m, void *v)
{
    seq_printf(m, "%s\n", (char*)v);
    return 0;    
}

static struct seq_operations my_seq_ops = {
    .start    =    my_seq_start,
    .stop    =    my_seq_stop,
    .next    =    my_seq_next,
    .show    =    my_seq_show,
      };
//==========================================================================

static int my_proc_open(struct inode * inode , struct file * file) 
{ 
    return seq_open(file, &my_seq_ops ); 
}

static struct file_operations my_file_ops = {
    .owner      = THIS_MODULE,
    .open     = my_proc_open,
    .read      = seq_read,
    .llseek  = seq_lseek,
    .release = seq_release,
};

//==========================================================================
static int __init my_module_init(void)
{
    struct proc_dir_entry * my_proc_node = NULL;

    pr_info(LOG_TAG "enter %s()\n", __func__);

    my_proc_node = proc_create("my_test2", S_IRUGO, NULL, &my_file_ops);
    if( NULL == my_proc_node )    {
        pr_err(LOG_TAG "creat /proc/my_test2 failed\n");
        remove_proc_entry("my_test2", NULL);
        return -1;
    }

    pr_info(LOG_TAG "creat /proc/my_test2 success\n");
    return 0;
}

static void __exit my_module_exit(void)
{
    pr_info(LOG_TAG "enter %s()\n", __func__);

    pr_info(LOG_TAG "remove /proc/my_test2\n");
    remove_proc_entry("my_test2", NULL);
}

module_init(my_module_init);
module_exit(my_module_exit);    

到了這里,關(guān)于開(kāi)發(fā)中proc文件系統(tǒng)的簡(jiǎn)單使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux】linux5.6引入struct proc_ops,用以替代struct file_operations在/proc下進(jìn)行文件操作

    linux5.10生成在/proc目錄下的文件時(shí),利用cat讀取文件,提示: 該報(bào)錯(cuò)是錯(cuò)誤碼:EPERM,不允許操作 發(fā)現(xiàn)是在移植內(nèi)核代碼時(shí),未對(duì)proc接口進(jìn)行適配。 linux-5.6引入結(jié)構(gòu)體struct proc_ops,用以替代struct file_operations在/proc下進(jìn)行文件操作。 proc_create中的proc_ops結(jié)構(gòu)體類型定義改變,導(dǎo)

    2024年02月08日
    瀏覽(18)
  • [驅(qū)動(dòng)開(kāi)發(fā)]Linux內(nèi)核定時(shí)器與中斷的簡(jiǎn)單應(yīng)用

    首先介紹一下定時(shí)器原理。 在linux系統(tǒng)中定時(shí)器有分為軟定時(shí)和硬件定時(shí)器。 以海思某款芯片為例,定時(shí)器模塊又稱為Timer模塊,主要實(shí)現(xiàn)定時(shí)、計(jì)數(shù)功能。 Timer 具有以下特點(diǎn): 帶可編程 8 位預(yù)分頻器的 32bit/16bit 減法定時(shí)器/計(jì)數(shù)器。 Timer 的計(jì)數(shù)時(shí)鐘為 3MHz 時(shí)鐘。 支持 3 種

    2024年02月20日
    瀏覽(34)
  • 2023-07-10 linux IIO子系統(tǒng)使用學(xué)習(xí),在TI 的ads1015驅(qū)動(dòng)里面看到相關(guān)使用,故花點(diǎn)時(shí)間進(jìn)行簡(jiǎn)單的學(xué)習(xí),入門級(jí)別,紀(jì)錄點(diǎn)滴。

    2023-07-10 linux IIO子系統(tǒng)使用學(xué)習(xí),在TI 的ads1015驅(qū)動(dòng)里面看到相關(guān)使用,故花點(diǎn)時(shí)間進(jìn)行簡(jiǎn)單的學(xué)習(xí),入門級(jí)別,紀(jì)錄點(diǎn)滴。

    一、Linux IIO(Industrial I/O)架構(gòu)是Linux內(nèi)核提供的一種用于支持各種類型傳感器和數(shù)據(jù)采集設(shè)備的子系統(tǒng),包括溫度、壓力、濕度、加速度、光度等多種傳感器。 二、這個(gè)就是ads1015的驅(qū)動(dòng),里面用到iio子系統(tǒng)。 ti-ads1015.c ? adc ? iio ? drivers - kernel/git/torvalds/linux.git - Linux kerne

    2024年02月17日
    瀏覽(31)
  • linux i2c驅(qū)動(dòng)開(kāi)發(fā)之最簡(jiǎn)單入門:設(shè)備樹與驅(qū)動(dòng)的匹配

    1在設(shè)備樹中聲明我們的模擬I2C設(shè)備: i2c的設(shè)備加入是必須放在某個(gè)i2c的總線下面的,我們這里是放在 i2c7下面。 可以直接在設(shè)備樹搜索i2c7,然后把status 修改為okay,然后再加入設(shè)備信息. 這里我們指定和驅(qū)動(dòng)匹配的字符串是 myi2c-dev,在bus segment 上分配的地址是 0x70 。 當(dāng)然這

    2024年02月16日
    瀏覽(28)
  • <Linux開(kāi)發(fā)>驅(qū)動(dòng)開(kāi)發(fā) -之-Linux INPUT 子系統(tǒng)

    <Linux開(kāi)發(fā)>驅(qū)動(dòng)開(kāi)發(fā) -之-Linux INPUT 子系統(tǒng)

    <Linux開(kāi)發(fā)>驅(qū)動(dòng)開(kāi)發(fā) -之-Linux INPUT 子系統(tǒng) 交叉編譯環(huán)境搭建: <Linux開(kāi)發(fā)> linux開(kāi)發(fā)工具-之-交叉編譯環(huán)境搭建 uboot移植可參考以下: <Linux開(kāi)發(fā)> -之-系統(tǒng)移植 uboot移植過(guò)程詳細(xì)記錄(第一部分) <Linux開(kāi)發(fā)> -之-系統(tǒng)移植 uboot移植過(guò)程詳細(xì)記錄(第二部分) <Linux開(kāi)發(fā)

    2024年02月09日
    瀏覽(22)
  • Linux驅(qū)動(dòng)開(kāi)發(fā):gpio子系統(tǒng)

    目錄 1、GPIO配置流程 2、GPIO子系統(tǒng)API 2.1?of_find_node_by_path 2.2 of_get_named_gpio 2.3 gpio_request 與?gpiod_get 與?gpiod_get_index 2.4?gpio_direction_input 與?gpiod_direction_input 2.5?gpio_direction_output 與?gpiod_direction_output 2.6?gpio_get_value 與?gpiod_get_value 2.7?gpio_set_value 與?gpiod_set_value 2.8? gpiod_get_from

    2024年02月12日
    瀏覽(17)
  • Linux驅(qū)動(dòng)開(kāi)發(fā):SPI子系統(tǒng)

    Linux驅(qū)動(dòng)開(kāi)發(fā):SPI子系統(tǒng)

    MISO:主設(shè)備數(shù)據(jù)輸入,從設(shè)備數(shù)據(jù)輸出。 MOSI:主設(shè)備數(shù)據(jù)輸出,從設(shè)備數(shù)據(jù)輸入。 SCLK:時(shí)鐘信號(hào),由主設(shè)備產(chǎn)生。 CS:? ? 從設(shè)備片選信號(hào),由主設(shè)備控制。 CPOL(時(shí)鐘極性) :? ?0:時(shí)鐘起始位低電平 ? ? ?1:時(shí)鐘起始為高電平 ? CPHA(時(shí)鐘相位) :0:第一個(gè)時(shí)鐘周期采樣? ?1

    2024年02月06日
    瀏覽(26)
  • 嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā)系列五:Linux系統(tǒng)和HelloWorld

    嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā)系列五:Linux系統(tǒng)和HelloWorld

    三個(gè)問(wèn)題 了解Hello World程序的執(zhí)行過(guò)程有什么用? 編譯和執(zhí)行:Hello World程序的執(zhí)行分為兩個(gè)主要步驟:編譯和執(zhí)行。編譯器將源代碼轉(zhuǎn)換為可執(zhí)行文件,然后計(jì)算機(jī)執(zhí)行該文件并輸出相應(yīng)的結(jié)果。了解這個(gè)過(guò)程可以幫助我們理解如何將代碼轉(zhuǎn)化為可運(yùn)行的程序。 語(yǔ)法和語(yǔ)義

    2024年02月13日
    瀏覽(26)
  • 【Linux驅(qū)動(dòng)開(kāi)發(fā)】010 pinctrl子系統(tǒng)

    【Linux驅(qū)動(dòng)開(kāi)發(fā)】010 pinctrl子系統(tǒng)

    上一章我們編寫了基于設(shè)備樹的 LED 驅(qū)動(dòng),但是驅(qū)動(dòng)的本質(zhì)還是沒(méi)變,都是配置 LED 燈所使用的 GPIO 寄存器,驅(qū)動(dòng)開(kāi)發(fā)方式和裸機(jī)基本沒(méi)啥區(qū)別。本章我們就來(lái)學(xué)習(xí)一下如何借助 pinctrl 和 gpio 子系統(tǒng)來(lái)簡(jiǎn)化 GPIO 驅(qū)動(dòng)開(kāi)發(fā)。? ?Linux 內(nèi)核針對(duì) PIN 的配置推出了 pinctrl 子系統(tǒng),對(duì)于

    2024年02月14日
    瀏覽(21)
  • 【Linux驅(qū)動(dòng)開(kāi)發(fā)】011 gpio子系統(tǒng)

    【Linux驅(qū)動(dòng)開(kāi)發(fā)】011 gpio子系統(tǒng)

    前面我們編寫了基于設(shè)備樹的 LED 驅(qū)動(dòng),但是驅(qū)動(dòng)的本質(zhì)還是沒(méi)變,都是配置 LED 燈所使用的 GPIO 寄存器,驅(qū)動(dòng)開(kāi)發(fā)方式和裸機(jī)基本沒(méi)啥區(qū)別。本章我們就來(lái)學(xué)習(xí)一下如何借助 pinctrl 和 gpio 子系統(tǒng)來(lái)簡(jiǎn)化 GPIO 驅(qū)動(dòng)開(kāi)發(fā)。? ?Linux 內(nèi)核針對(duì) PIN 的配置推出了 pinctrl 子系統(tǒng),對(duì)于

    2024年02月03日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包