中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

wordpress的文件結(jié)構(gòu)百度刷seo關(guān)鍵詞排名

wordpress的文件結(jié)構(gòu),百度刷seo關(guān)鍵詞排名,做門(mén)戶類(lèi)網(wǎng)站報(bào)價(jià),微網(wǎng)站建設(shè)要多少錢(qián)目錄 一、通用堆棧知識(shí)二、雙堆棧用法三、PendSV 中斷介紹和用法四、SVC 軟中斷介紹和用法五、特權(quán)級(jí)和非特權(quán)級(jí)使用方法 一、通用堆棧知識(shí) 在前面講解 STM32 啟動(dòng)文件的時(shí)候就已經(jīng)提到過(guò),有關(guān)堆棧大小的設(shè)置是在啟動(dòng)文件中設(shè)置的: Heap 主要用于 Mal…

目錄

  • 一、通用堆棧知識(shí)
  • 二、雙堆棧用法
  • 三、PendSV 中斷介紹和用法
  • 四、SVC 軟中斷介紹和用法
  • 五、特權(quán)級(jí)和非特權(quán)級(jí)使用方法


一、通用堆棧知識(shí)

在前面講解 STM32 啟動(dòng)文件的時(shí)候就已經(jīng)提到過(guò),有關(guān)堆棧大小的設(shè)置是在啟動(dòng)文件中設(shè)置的:

Heap 主要用于 Malloc、Free,動(dòng)態(tài)內(nèi)存申請(qǐng)和釋放。

Stack 也非常重要,程序編譯后所包含的大量 PUSHPOP 指令操作,系統(tǒng)根據(jù) SP(堆棧指針) 寄存器訪問(wèn)當(dāng)前對(duì)應(yīng)棧內(nèi)存,通過(guò)棧保存臨時(shí)數(shù)據(jù)。大部分的棧都是向下生長(zhǎng)的(也有向上生長(zhǎng)的)。M 內(nèi)核的棧是從高地址向低地址生長(zhǎng)的,下面通過(guò)一個(gè)例子演示一下:

__IO uint32_t a = 0x11111111;
__IO uint32_t b = 0x22222222;
__IO uint32_t c = 0x33333333;
__IO uint32_t d = 0x44444444;
__IO uint32_t e = 0x55555555;
__IO uint32_t f = 0x66666666;
__IO uint32_t g = 0x77777777;
__IO uint32_t h = 0x88888888;

在這里插入圖片描述

然后進(jìn)入調(diào)試狀態(tài),可以看到現(xiàn)在 SP 指針是 0x20000618。

可當(dāng)我們實(shí)際點(diǎn)擊單步調(diào)試的時(shí)候,SP 指針現(xiàn)在又變成了 0x200005F80x20000618 - 0x200005F8 等于十進(jìn)制的 32。也就是說(shuō)少了 32 個(gè)字節(jié)。這里是因?yàn)槌绦蛞粊?lái)就把這 8 個(gè)數(shù)據(jù),共 32 個(gè)字節(jié)的內(nèi)存分配好了。

當(dāng)你把 __IO 去掉后,就不會(huì)出現(xiàn)以上的情況。__IO 其實(shí)就是 volatile,所以在這里就是告訴編譯器它后面所定義的變量隨時(shí)都有可能改變,因此編譯后的程序每次需要存儲(chǔ)或讀取這個(gè)變量的時(shí)候,告訴編譯器對(duì)該變量不做優(yōu)化,都會(huì)直接從變量?jī)?nèi)存地址中讀取數(shù)據(jù),從而可以提供對(duì)特殊地址的穩(wěn)定訪問(wèn)。

下面繼續(xù)執(zhí)行,可以看到,數(shù)據(jù)是從高地址向低地址存儲(chǔ)的。

當(dāng)然,內(nèi)存空間只是連續(xù)字節(jié)數(shù)據(jù)的抽象,本身并不區(qū)分堆和棧的概念,它做的只是存儲(chǔ)和讀寫(xiě)信息。因此,如何定義堆棧、初始化建立堆棧環(huán)境,在嵌入式軟件運(yùn)行前便顯得尤為重要。這涉及到處理器提供的堆棧機(jī)制、操作系統(tǒng)內(nèi)存管理和進(jìn)程切換等方方面面。

二、雙堆棧用法

下圖取自權(quán)威指南:

在搭載實(shí)時(shí)操作系統(tǒng)內(nèi)核的嵌入式軟件中,棧往往分為兩大類(lèi),除了滿足系統(tǒng)基本的主棧(main stack)外,往往還需要進(jìn)程/線程棧(process stack)。這兩部分內(nèi)存空間是獨(dú)立存在的:

  • 主棧位于系統(tǒng)的棧區(qū)(stack)
  • 而線程堆棧往往定義在堆區(qū)(heap)或靜態(tài)區(qū)(static)

無(wú)論是靜態(tài)還是動(dòng)態(tài)創(chuàng)建,線程棧都不會(huì)占用棧區(qū)的主棧空間。即線程棧并不在棧區(qū),可能在數(shù)據(jù)區(qū)或堆區(qū),再次說(shuō)明主棧和線程棧內(nèi)存空間獨(dú)立。

理解這一點(diǎn),是理解 MCU 堆棧的關(guān)鍵前提。

所謂雙堆棧,本質(zhì)上都是 R13,不過(guò)在不同的運(yùn)行狀態(tài)下使用的棧是不同的,并且在同一時(shí)刻,只有其中的一個(gè)??捎?。在系統(tǒng)復(fù)位后、進(jìn)入線程環(huán)境前,默認(rèn)使用主堆棧,中斷服務(wù)程序(ISR)中也是使用主堆棧。RTOS 各線程中的應(yīng)用代碼,則使用線程堆棧。

  • 如果使用了雙堆棧,那么在中斷里只能使用 MSP;而在中斷以外,可以使用 MSP,也可以使用 PSP。(不過(guò)在 RTOS 里,中斷以外全部使用 PSP,后面講原因)。

上電后,系統(tǒng)僅初始化了 MSP,需要通過(guò)額外的匯編代碼建立完整的雙堆棧系統(tǒng),當(dāng)實(shí)時(shí)內(nèi)核準(zhǔn)備就緒,線程調(diào)度正常運(yùn)行,雙堆棧機(jī)制開(kāi)始工作。進(jìn)中斷時(shí)系統(tǒng)根據(jù)當(dāng)前狀態(tài)自動(dòng)切換堆棧,進(jìn)程上下文切換時(shí)會(huì)更新不同線程的 PSP,通過(guò)修改 EXC_RETURN 可以手動(dòng)切換 MSP/PSP。

雙堆棧機(jī)制使得內(nèi)核/ISR 堆棧和線程應(yīng)用堆棧分開(kāi)管理,通過(guò)不同的堆棧指針寄存器完成切換,大大提高了系統(tǒng)的效率,在絕大部分的嵌入式實(shí)時(shí)操作系統(tǒng)中,都使用了雙堆棧機(jī)制,如 ucos、FreeRTOS、RT-Thread 等。

在一些簡(jiǎn)單的應(yīng)用中,例如裸機(jī)程序,可以從頭到尾都只使用主堆棧,只要確保分配足夠的空間即可。

還是一樣,通過(guò)例程來(lái)看,在剛才的程序下面添加:

__set_PSP(__get_MSP()); /* 設(shè)置PSP位置 */
__set_CONTROL(0x02);    /* bit1 = 1表示使用PSP,bit1 = 0表示使用MSP */ 
{__IO uint32_t a1 = 0x11111111;__IO uint32_t b1 = 0x22222222;__IO uint32_t c1 = 0x33333333;__IO uint32_t d1 = 0x44444444;__IO uint32_t e1 = 0x55555555;__IO uint32_t f1 = 0x66666666;__IO uint32_t g1 = 0x77777777;__IO uint32_t h1 = 0x88888888;printf("a1 = %x, b1 = %x\r\n", a1, b1);
}


下面繼續(xù)執(zhí)行:

這里將 PSP 指向 MSP 一樣的地址,然后設(shè)置使用 PSP:

然后繼續(xù)執(zhí)行:

可以看到,現(xiàn)在只是改成使用 PSP 了,其它和 MSP 沒(méi)有什么區(qū)別。

下面我在我的 SysTick_Handler 函數(shù)中打一個(gè)斷點(diǎn),然后全速執(zhí)行:

棧指針又切換回 MSP 了。而退出中斷后,又會(huì)自動(dòng)切換回 PSP:

這也印證了剛才所說(shuō)的,在任務(wù)中使用 PSP,在中斷中使用 MSP。使用雙堆棧,把任務(wù)和中斷使用的棧區(qū)分開(kāi),這樣安全性會(huì)更好一些。

三、PendSV 中斷介紹和用法

PendSV 典型使用場(chǎng)合是在上下文切換時(shí)(在不同任務(wù)之間切換)。上下文切換的本質(zhì)就是保存當(dāng)前執(zhí)行現(xiàn)場(chǎng) A,切換到另一個(gè)任務(wù) B 里面。切換回來(lái)時(shí)又要恢復(fù)執(zhí)行現(xiàn)場(chǎng) A(將一系列的寄存器入棧、出棧)。

由于 PendSV 的特點(diǎn)就是支持緩期執(zhí)行,所以 RTOS 可以利用它這個(gè)特點(diǎn),進(jìn)行任務(wù)調(diào)度過(guò)程的上下文切換。而為什么要使用緩期執(zhí)行的特點(diǎn)來(lái)進(jìn)行上下文切換呢?簡(jiǎn)單的說(shuō)就是任何 RTOS,都需要盡量不打斷外設(shè)中斷。 我們來(lái)舉例說(shuō)明,假如一個(gè)系統(tǒng)中有兩個(gè)就緒的任務(wù),上下文切換被切換的場(chǎng)合可以是:

  1. 執(zhí)行一個(gè)系統(tǒng)調(diào)用
  2. 系統(tǒng)滴答定時(shí)器 SYSTICK 中斷,觸發(fā)了任務(wù)的調(diào)度。

假如我們?cè)?Systick 中斷服務(wù)程序中,啟動(dòng)上下文切換,流程圖如下:

但若在產(chǎn)生 SysTick 異常時(shí)正在響應(yīng)一個(gè)中斷,則 SysTick 異常會(huì)搶占其ISR。在這種情況下,OS 是不能執(zhí)行上下文切換的,否則將使中斷請(qǐng)求被延遲,而且在真實(shí)系統(tǒng)中延遲時(shí)間還往往不可預(yù)知——任何有一丁點(diǎn)實(shí)時(shí)要求的系統(tǒng)都決不能容忍這種事。因此,在 CM3 中也是,如果 OS 在某中斷活躍時(shí)嘗試切入線程模式,將觸犯用法 fault 異常。

為解決此問(wèn)題,早期的 OS 大多會(huì)檢測(cè)當(dāng)前是否有中斷在活躍中,只有在無(wú)任何中斷需要響應(yīng)時(shí),才執(zhí)行上下文切換(切換期間無(wú)法響應(yīng)中斷)。然而,這種方法的弊端在于,它可以把任務(wù)切換動(dòng)作拖延很久(因?yàn)槿绻麚屨剂?IRQ,則本次 SysTick 在執(zhí)行后不得作上下文切換,只能等待下一次 SysTick 異常),尤其是當(dāng)某中斷源的頻率和 SysTick 異常的頻率比較接近時(shí),會(huì)發(fā)生“共振”,使上下文切換遲遲不能進(jìn)行。

如果將 SysTick 的優(yōu)先級(jí)設(shè)置為最低,然后在 SysTick 中進(jìn)行上下文切換,然后任務(wù)調(diào)度。這樣不會(huì)觸發(fā) Fault。但是也有一個(gè)問(wèn)題:

  • 一般 OS 在調(diào)度任務(wù)時(shí),會(huì)關(guān)閉中斷,也就是進(jìn)入臨界區(qū),而 OS 任務(wù)調(diào)度是要耗時(shí)的,這就會(huì)出現(xiàn)一種情況: 在任務(wù)調(diào)度期間,如果新的外部 IRQ 發(fā)生,CPU 將不能夠快速響應(yīng)處理。

而現(xiàn)在有了 PendSVPendSV 異常會(huì)自動(dòng)延遲上下文切換的請(qǐng)求(緩期執(zhí)行),直到其它的 ISR 都完成了處理后才放行。為實(shí)現(xiàn)這個(gè)機(jī)制,需要把PendSV 為最低優(yōu)先級(jí)的異常。

如果 OS 檢測(cè)到某 IRQ 正在活動(dòng)并且被 SysTick 搶占,它將懸起一個(gè) PendSV 異常,以便緩期執(zhí)行上下文切換。

下面用一個(gè)數(shù)組模擬??臻g,來(lái)展示一下函數(shù)的切換:

uint32_t  PspStack[100];  /* PspStack??臻g */int main(void)
{...p_stk = &PspStack[100];/* 硬件自動(dòng)入棧 */*(--p_stk) = (uint32_t)0x01000000;  /* xPSR    */*(--p_stk) = (uint32_t)PrintfLogo;  /* PC  */*(--p_stk) = (uint32_t)0x00000000;  /* R14 (LR) */*(--p_stk) = (uint32_t)0xAAAAAAAA;  /* R12 */*(--p_stk) = (uint32_t)0xBBBBBBBB;  /* R3  */*(--p_stk) = (uint32_t)0xCCCCCCCC;  /* R2  */*(--p_stk) = (uint32_t)0xDDDDDDDD;  /* R1  */*(--p_stk) = (uint32_t)0xEEEEEEEE;  /* R0 : argument *//* 根據(jù)需要手動(dòng)入棧的 */*(--p_stk) = (uint32_t)0x11111111;  /* R11*/*(--p_stk) = (uint32_t)0x22222222;  /* R10*/*(--p_stk) = (uint32_t)0x33333333;  /* R9 */*(--p_stk) = (uint32_t)0x44444444;  /* R8 */*(--p_stk) = (uint32_t)0x55555555;  /* R7 */*(--p_stk) = (uint32_t)0x66666666;  /* R6 */*(--p_stk) = (uint32_t)0x77777777;  /* R5 */*(--p_stk) = (uint32_t)0x88888888;  /* R4 *//* 使能PendSV中斷 */SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;/*##- 測(cè)試SVC軟中斷 ####################################################*/SVCTest(0x11223344, 0x55667788, 0xaabbddee);...
}void PendSV_Handler(void)
{__asm("BKPT 0");__set_PSP((uint32_t)&PspStack[92]);
}

在 M 內(nèi)核,R0、R1、R2、R3、R12、R14(LR)、R15(PC)、xPSR,這 8 個(gè)寄存器是自動(dòng)入棧的。而其余的寄存器是手動(dòng)入棧的。

開(kāi)啟了 PendSV 中斷后,當(dāng)來(lái)到 SVCTest(后面會(huì)介紹)時(shí)就會(huì)觸發(fā) PendSV 異常。

PendSV_Handler 函數(shù)中,我們使 PSP 指向 &PspStack[92],也就是 PrintfLogo。所以當(dāng)觸發(fā) PendSV 中斷的時(shí)候,我們會(huì)將 PSP 指針指向 PrintfLogo 函數(shù)。也就是說(shuō),原本正常情況下,PC 指針保存的是當(dāng)前 main 函數(shù)中下一條指令的地址,這里我們手動(dòng)將其修改成了另一個(gè)函數(shù)的地址。這就是任務(wù)切換的本質(zhì)。

來(lái)看現(xiàn)象:

再執(zhí)行一步的時(shí)候就會(huì)跳轉(zhuǎn)到 PendSV_Handler。

當(dāng)跳出 PendSV_Handler 函數(shù)后,正常情況下我們應(yīng)該繼續(xù)在 main 函數(shù)中向后執(zhí)行,而這里會(huì)跳轉(zhuǎn)到 PrintfLogo 函數(shù)中:

旁邊的寄存器的值和我們硬件自動(dòng)入棧的值也是對(duì)應(yīng)的:

四、SVC 軟中斷介紹和用法

SVC 用于生成系統(tǒng)函數(shù)調(diào)用的請(qǐng)求,例如,用戶程序不允許直接訪問(wèn)硬件,操作系統(tǒng)可以通過(guò) SVC 提供對(duì)硬件的訪問(wèn)。因此,當(dāng)用戶程序想要使用某些硬件時(shí),可以使用 SVC 指令,然后執(zhí)行操作系統(tǒng)中的軟件異常處理程序,并提供用戶應(yīng)用程序請(qǐng)求的服務(wù)。通過(guò)這種方式,對(duì)硬件的訪問(wèn)由操作系統(tǒng)控制,操作系統(tǒng)可以阻止用戶應(yīng)用程序直接訪問(wèn)硬件,從而提供更可靠的系統(tǒng)。

SVC 還可以使軟件更具可移植性,因?yàn)橛脩舫绦虿恍枰烙布木幊碳?xì)節(jié)。用戶程序只需要知道應(yīng)用程序編程接口(API)函數(shù) ID 和參數(shù),而實(shí)際的硬件級(jí)編程是由設(shè)備驅(qū)動(dòng)程序處理的。

SVC 異常由 SVC 指令產(chǎn)生,該指令需要一個(gè)立即數(shù)作為參數(shù),根據(jù)這個(gè)參數(shù)執(zhí)行不同的 SVC 處理函數(shù)。例:

SVC #0x3 ;  調(diào)用SVC 函數(shù)3
SVC 0x3 ;   傳統(tǒng)的語(yǔ)法(沒(méi)有#)也可行

在 C 語(yǔ)言中,可以使用編譯器關(guān)鍵字函數(shù) __svc 或者使用內(nèi)聯(lián)匯編代碼來(lái)執(zhí)行 SVC 指令。

對(duì)于操作系統(tǒng)來(lái)說(shuō),當(dāng) SVC 處理程序被執(zhí)行時(shí),我們可以通過(guò)讀取堆棧中的 PC 值來(lái)確定 SVC 指令中的立即數(shù)據(jù)值,然后從該地址讀取指令并屏蔽不需要的位。如果使用的PSP堆棧,則還需要通過(guò)LR寄存器判斷當(dāng)前使用的是哪個(gè)堆棧。

在 ARM7 中有一個(gè)軟件中斷指令 SWI(Software interrupt instruction)。實(shí)際上,SVC 指令的二進(jìn)制編碼與 ARM7 中的 SWI 是相同的。由于異常模型發(fā)生了變化,這條指令被重命名,以確保程序員能夠正確地將軟件代碼從 ARM7 移植到 Cortex-M3。

當(dāng) SVC 指令被執(zhí)行后,處理器會(huì)根據(jù)中斷向量表中的信息跳轉(zhuǎn)到相應(yīng)的 SVC 中斷處理函數(shù),執(zhí)行 SVC 指令時(shí),處理器會(huì)自動(dòng)保存當(dāng)前的上下文,并將處理器的模式切換為特權(quán)模式,從而允許執(zhí)行受限的操作。

簡(jiǎn)單來(lái)說(shuō),RTOS 內(nèi)核中的各個(gè) API,不是在任務(wù)里執(zhí)行的,而是在 SVC 軟中斷里執(zhí)行的。這樣一來(lái),就把 RTOS 內(nèi)核和任務(wù)隔離開(kāi)了。

__svc 是 MDK 內(nèi)置的一個(gè)定義前綴,用于設(shè)置 SVC 軟中斷的序號(hào)(0~255),可以用來(lái)區(qū)分不同的使用場(chǎng)景

void __svc(0)  SVCTest(uint32_t a, uint32_t b, uint32_t c); /* SVC軟中斷 */.../*##- 測(cè)試SVC軟中斷 ####################################################*/
SVCTest(0x11223344, 0x55667788, 0xaabbddee);


單步運(yùn)行后直接跳轉(zhuǎn),并且把函數(shù)數(shù)據(jù)也一并保存在 R0、R1、R2 寄存器中:


當(dāng)我們調(diào)用 OS 內(nèi)核的 API 的時(shí)候,一調(diào)用就會(huì)進(jìn)入到 SVC 中斷,讓這個(gè)函數(shù)直接在 SVC 中斷中執(zhí)行,這樣把 OS 的函數(shù)和我們自己寫(xiě)的應(yīng)用程序隔離開(kāi)了。

五、特權(quán)級(jí)和非特權(quán)級(jí)使用方法

特權(quán)級(jí)和非特權(quán)級(jí)只是針對(duì)中斷外的任務(wù)來(lái)說(shuō)的,中斷全部都是特權(quán)級(jí)

如果代碼是在中斷里執(zhí)行,則只能是特權(quán)級(jí);中斷以外可以是特權(quán)級(jí),也可以是非特權(quán)級(jí)。

非特權(quán)級(jí)主要是 RTX 在使用。如果是在非特權(quán)級(jí)的模式下,則不能訪問(wèn)和配置 Cortex-M 內(nèi)核相關(guān)的寄存器(例如 SCB),否則會(huì)觸發(fā)異常。

/*##- 測(cè)試非特權(quán)級(jí) ####################################################*/
__set_CONTROL(0x01);  /* bit0 = 1表示應(yīng)用程序工作在非特權(quán)級(jí)模式,bit1 = 0表示應(yīng)用程序工作在特權(quán)級(jí)模式 */ 
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;  /* 操作SCB就會(huì)進(jìn)入異常 */

例程中先開(kāi)啟非特權(quán)模式,然后再操作 SCB(系統(tǒng)控制塊)寄存器時(shí)會(huì)觸發(fā)異常:

直接就來(lái)到 HardFault 了。

那非特權(quán)級(jí)模式下核心外設(shè)寄存器如何初始化?

如果用戶將 RTX 操作系統(tǒng)的任務(wù)設(shè)置在非特權(quán)級(jí)模式下運(yùn)行,那么核心外設(shè)寄存器應(yīng)該放在哪里進(jìn)行初始化呢,主要有以下兩種方法:

  • 使用 SVC(Supervisor Call)軟中斷。
  • 在初始化和開(kāi)啟RTX多任務(wù)前做核心外設(shè)的初始化。

那在 Cortex-M3/M4/M7 內(nèi)核如何切換兩種模式?Cortex-M3/M4/M7 中的特殊功能寄存器包括:

  • 程序狀態(tài)寄存器組(PSRs、xPSR)
  • 中斷屏蔽寄存器組(PRIMASK、FAULTMASK、BASEPRI)
  • 控制寄存器(CONTROL)

其中控制寄存器 CONTROL 是用來(lái)設(shè)置特權(quán)級(jí)和非特權(quán)級(jí)切換的,CONTROL 寄存器定義如下:

前面的例子中也演示了如何設(shè)置 CONTROL 寄存器:

__set_CONTROL(uint32_t control)
http://www.risenshineclean.com/news/48837.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)行業(yè)數(shù)據(jù)seo推薦
  • 商洛免費(fèi)做網(wǎng)站百度廣告聯(lián)系方式
  • 豐金網(wǎng)絡(luò) 做網(wǎng)站數(shù)字營(yíng)銷(xiāo)網(wǎng)站
  • 怎么做培訓(xùn)班網(wǎng)站石家莊關(guān)鍵詞優(yōu)化軟件
  • 什么是網(wǎng)絡(luò)營(yíng)銷(xiāo)包含哪些內(nèi)容全網(wǎng)營(yíng)銷(xiāo)與seo
  • 清理網(wǎng)站數(shù)據(jù)庫(kù)源碼交易平臺(tái)
  • 南昌那個(gè)公司做網(wǎng)站好今日最新國(guó)際新聞?lì)^條
  • 金昌網(wǎng)站seo合肥seo推廣培訓(xùn)班
  • 蘇州專業(yè)做網(wǎng)站公司有哪些小說(shuō)推廣關(guān)鍵詞怎么弄
  • 做網(wǎng)站需要的照片網(wǎng)站建設(shè)公司哪個(gè)好呀
  • 建站公司 萬(wàn)維科技外鏈交換平臺(tái)
  • 網(wǎng)站設(shè)置密碼百度網(wǎng)站域名注冊(cè)
  • 給企業(yè)做宣傳網(wǎng)站的好處百度上如何發(fā)廣告
  • 開(kāi)發(fā)平臺(tái)游戲名詞解釋搜索引擎優(yōu)化
  • 貴陽(yáng)疫情最新消息今天寧波seo排名優(yōu)化培訓(xùn)
  • 網(wǎng)站建設(shè)公司信息搜索引擎營(yíng)銷(xiāo)的優(yōu)勢(shì)和劣勢(shì)
  • 織夢(mèng)的手機(jī)端網(wǎng)站模板技能培訓(xùn)有哪些科目
  • 破解版下載大全免費(fèi)下載seo優(yōu)化軟件有哪些
  • 湛江免費(fèi)建站哪里有淘寶聯(lián)盟怎么推廣
  • 鄭州網(wǎng)站開(kāi)發(fā)設(shè)計(jì)公司電話個(gè)人如何優(yōu)化網(wǎng)站有哪些方法
  • 如何建立網(wǎng)站做微商企業(yè)網(wǎng)站模板 免費(fèi)
  • 多語(yǔ)種網(wǎng)站建設(shè)手機(jī)版怎么用百度快照
  • 馬鞍山住房和城鄉(xiāng)建設(shè)局網(wǎng)站免費(fèi)發(fā)帖論壇大全
  • 國(guó)內(nèi)ip地址代理免費(fèi)信息流優(yōu)化師簡(jiǎn)歷怎么寫(xiě)
  • 建立網(wǎng)站站點(diǎn)的步驟技術(shù)培訓(xùn)平臺(tái)
  • 做電影網(wǎng)站服務(wù)器需求seo導(dǎo)航站
  • 給網(wǎng)站做接口企業(yè)培訓(xùn)考試系統(tǒng)
  • 廬江有做網(wǎng)站的嗎財(cái)經(jīng)新聞每日財(cái)經(jīng)報(bào)道
  • 連江網(wǎng)站建設(shè)服務(wù)index百度指數(shù)
  • 高德地圖有外資背景嗎優(yōu)化大師官方