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

當前位置: 首頁 > news >正文

建設物流網(wǎng)站的規(guī)劃網(wǎng)絡營銷戰(zhàn)略的內(nèi)容

建設物流網(wǎng)站的規(guī)劃,網(wǎng)絡營銷戰(zhàn)略的內(nèi)容,封面型網(wǎng)站布局,平面設計筆記本電腦推薦概述 在Android系統(tǒng)中,所有的應用程序進程以及系統(tǒng)服務進程SystemServer都是由Zygote進程孕育(fork)出來的,這也許就是為什么要把它稱為Zygote(受精卵)的原因吧。由于Zygote進程在Android系統(tǒng)中有著如此重…

概述

在Android系統(tǒng)中,所有的應用程序進程以及系統(tǒng)服務進程SystemServer都是由Zygote進程孕育(fork)出來的,這也許就是為什么要把它稱為Zygote(受精卵)的原因吧。由于Zygote進程在Android系統(tǒng)中有著如此重要的地位,本文將詳細分析它的啟動過程

總體時序

先概述一下總體運行流程,當按電源鍵,首先是加載系統(tǒng)引導程序BootLoader,然后啟動linux內(nèi)核,再啟動init進程,最后Zygote進程啟動完成。理論上Android系統(tǒng)中的所有應用程序理論上都是由Zygote啟動的。Zygote前期啟動啟動服務,后期主要fork程序。

init啟動流程

  • 用戶空間的第一個進程,進程號為1(在《深入理解安卓內(nèi)核思想》的257頁里面寫的是0,在這記錄一下)
  • 職責
  • 創(chuàng)建Zygote
  • 初始化屬性服務
  • init文件位于源碼目錄system/core/init中

init進程的啟動三個階段

  • 啟動電源以及系統(tǒng)的啟動,加載引導程序BootLoader。
  • 啟動Linux內(nèi)核
  • 啟動init進程。
  • 啟動Zygote進程
  • 初始化啟動屬性服務。

Zygote進程

  • 所有App的父進程,ZygoteInit.main
  • Zygote進程,是由init進程通過解析init.rc文件后fork生成的,Zygote進程主要包括
  • 加載Zygoteinit類,注冊Zygote Socket服務端套接字
  • 加載虛擬機
  • 提前加載類PreloadClasses
  • 提前加載資源PreLoadResouces
  • system_server進程,是由Zygote fork而來,System Server是Zygote孵化出的第一個進程,System Server 負責啟動和管理整個Java FrameWork,包含ActivityManagerService, WorkManagerService,PagerManagerService,PowerManagerService等服務

system_server進程

系統(tǒng)各大服務的載體, SystemServer.main system_server進程從源碼角度來看可以分為,引導服務,核心服務和其他服務

  • 引導服務(7個):ActivityManagerService、PowerManagerService、LightsService、DisplayManagerService、PackageManagerService、UserManagerService、SensorService;
  • 核心服務(3個):BatteryService、UsageStatsService、WebViewUpdateService;
  • 其他服務(70個+):AlarmManagerService、VibratorService等。

ServiceManger進程

bInder服務的大管家

ServiceManager 是Binder IPC通信過程中的守護進程,本身也是一個Binder,但是并沒有采用多線程模型來跟Binder通信,而是自行編寫了binder.c直接和Binder驅動來通信,并且只有一個binder_loop來讀取和處理事務,這樣做的好處是簡單和高效 ServiceManager本身工作相對簡單,其工能查詢和注冊服務

流程圖

ServiceManager 集中管理系統(tǒng)內(nèi)的所有服務,通能過權限控制進程是否有權注冊服務,通過字符串來查找是否有對應的Service,由于ServiceManager進程注冊了Service的死亡通知,那么服務所在的進程死亡后,只需告訴ServiceManager,每個Client通過查詢ServiceManager可以獲取Service的情況

啟動主要包括以下幾個階段

  • 打開Binder驅動,并調用mmap()方法分配128k的內(nèi)存映射空間,binder_open
  • 注冊成為Binder服務的大管家binder_become_context_manager
  • 驗證selinux權限,判斷進程是否有權注冊查看指定服務
  • 進入無限循環(huán),處理Client發(fā)來的請求 binder_loop
  • 根據(jù)服務的名稱注冊服務,重復注冊會移除之前的注冊信息
  • 死亡通知,當所在進程死亡后,調用binder_release方法,然后調用binder_node_release,這個過程發(fā)出死亡通知回調

App進程

  • 通過Process.start啟動的App進程ActivityThread.main
  • Zygote 孵化出的第一個App進程是Launcher,這是用戶看到的桌面App
  • Zygote 還會創(chuàng)建出Browser,Phone,Email等App進程,每個App至少運行在一個進程上
  • 所有的App進程都是由Zygote fork而成

3)Zygote進程的啟動

Zygote進程, 一個在Android系統(tǒng)中扮演重要角色的進程. 我們知道Android系統(tǒng)中的兩個重要服務PackageManagerService和ActivityManagerService, 都是由SystemServer進程啟動的, 而這個SystemServer進程本身是Zygote進程在啟動的過程中fork出來的. 這樣一來, 想必我們就知道Zygote進程在Android系統(tǒng)中的重要地位了.

從圖中可得知Android系統(tǒng)中各個進程的先后順序為:

init進程 –-> Zygote進程 –> SystemServer進程 –>應用進程

鏈接

  1. 在init啟動Zygote時主要是調用app_main.cpp的main函數(shù)中的AppRuntime.start()方法來啟動Zygote進程的;
  2. 接著到AndroidRuntime的start函數(shù):使用JNI調用ZygoteInit的main函數(shù),之所以這里要使用JNI,是因為ZygoteInit是java代碼。最終,Zygote就從Native層進入了Java FrameWork層。在此之前,并沒有任何代碼進入Java FrameWork層面,因此可以認為,Zygote開創(chuàng)了java FrameWork層。
  3. /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    @UnsupportedAppUsagepublic static void main(String argv[]) {ZygoteServer zygoteServer = null;// Mark zygote start. This ensures that thread creation will throw// an error.ZygoteHooks.startZygoteNoThreadCreation();// Zygote goes into its own process group.try {Os.setpgid(0, 0);} catch (ErrnoException ex) {throw new RuntimeException("Failed to setpgid(0,0)", ex);}Runnable caller;try {// Report Zygote start time to tron unless it is a runtime restartif (!"1".equals(SystemProperties.get("sys.boot_completed"))) {MetricsLogger.histogram(null, "boot_zygote_init",(int) SystemClock.elapsedRealtime());}String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,Trace.TRACE_TAG_DALVIK);bootTimingsTraceLog.traceBegin("ZygoteInit");RuntimeInit.enableDdms();boolean startSystemServer = false;String zygoteSocketName = "zygote";String abiList = null;boolean enableLazyPreload = false;for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = true;} else if ("--enable-lazy-preload".equals(argv[i])) {enableLazyPreload = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);if (abiList == null) {throw new RuntimeException("No ABI list supplied.");}// In some configurations, we avoid preloading resources and classes eagerly.// In such cases, we will preload things prior to our first fork.if (!enableLazyPreload) {bootTimingsTraceLog.traceBegin("ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());preload(bootTimingsTraceLog);EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());bootTimingsTraceLog.traceEnd(); // ZygotePreload} else {Zygote.resetNicePriority();}// Do an initial gc to clean up after startupbootTimingsTraceLog.traceBegin("PostZygoteInitGC");gcAndFinalize();bootTimingsTraceLog.traceEnd(); // PostZygoteInitGCbootTimingsTraceLog.traceEnd(); // ZygoteInit// Disable tracing so that forked processes do not inherit stale tracing tags from// Zygote.Trace.setTracingEnabled(false, 0);Zygote.initNativeState(isPrimaryZygote);ZygoteHooks.stopZygoteNoThreadCreation();zygoteServer = new ZygoteServer(isPrimaryZygote);if (startSystemServer) {
// 使用了forkSystemServer()方法去創(chuàng)建SystemServer進程Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.if (r != null) {r.run();return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// 這里調用了ZygoteServer的runSelectLoop方法來等等ActivityManagerService來請求創(chuàng)建新的應用程序進程            
// loops forever in the zygote.caller = zygoteServer.runSelectLoop(abiList);} 
catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;} 
finally 
{
if (zygoteServer != null) {zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.if (caller != null) {caller.run();
}
}

其中, 在ZygoteInit的forkSystemServer()方法中啟動了SystemServer進程,forkSystemServer()方法核心代碼 :

private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) 
{
// 一系統(tǒng)創(chuàng)建SystemServer進程所需參數(shù)的準備工作try {...
/* Request to fork the system server process 
*/// 3.1pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.runtimeFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);
} 
catch (IllegalArgumentException ex) 
{throw new RuntimeException(ex);}
/* For child process 
*/if (pid == 0) {
if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}
zygoteServer.closeServerSocket();
// 3.2return handleSystemServerProcess(parsedArgs);
}return null;
}

可以看到,forkSystemServer()方法中,注釋3.1調用了Zygote的forkSystemServer()方法去創(chuàng)建SystemServer進程,其內(nèi)部會執(zhí)行nativeForkSystemServer這個Native方法,它最終會使用fork函數(shù)在當前進程創(chuàng)建一個SystemServer進程。如果pid等于0,即當前是處于新創(chuàng)建的子進程ServerServer進程中,則在注釋3.2處使用handleSystemServerProcess()方法處理SystemServer進程的一些處理工作。

從以上的分析可以得知,Zygote進程啟動中承擔的主要職責如下:

  • 1、創(chuàng)建AppRuntime,執(zhí)行其start方法,啟動Zygote進程。。
  • 2、創(chuàng)建JVM并為JVM注冊JNI方法。
  • 3、使用JNI調用ZygoteInit的main函數(shù)進入Zygote的Java FrameWork層。
  • 4、使用registerZygoteSocket方法創(chuàng)建服務器端Socket,并通過runSelectLoop方法等等AMS的請求去創(chuàng)建新的應用進程。
  • 5、啟動SystemServer進程。
  1. 調用了handleSystemServerprocess()方法來啟動SystemServer進程。handleSystemServerProcess()方法如下所示:
/*** Finish remaining work for the newly forked system server process.
*/
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {...
if (parsedArgs.invokeWith != null) {...} 
else {ClassLoader cl = null;
if (systemServerClasspath != null) {
// 1cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);}
/** Pass the remaining arguments to SystemServer.
*/// 2return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}

在注釋1處,使用了systemServerClassPath和targetSdkVersion創(chuàng)建了一個PathClassLoader。接著,在注釋2處,執(zhí)行了ZygoteInit的zygoteInit()方法,該方法如下所示:

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) 
{
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
// 1ZygoteInit.nativeZygoteInit();
// 2return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
  1. zygoteInit()方法的注釋2處,這里調用了RuntimeInit 的 applicationInit() 方法,代碼如下所示:

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {...
// Remaining arguments are passed to the start class's static mainreturn findStaticMain(args.startClass, args.startArgs, classLoader);
}

在applicationInit()方法中最后調用了findStaticMain()方法:

protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {
Class<?> cl;
try {
// 1cl = Class.forName(className, true, classLoader);
} 
catch (ClassNotFoundException ex) {
throw new RuntimeException("Missing class when invoking static main " + className,ex);
}
Method m;try {
// 2m = cl.getMethod("main", new Class[] { String[].class });
} 
catch (NoSuchMethodException ex) {
throw new RuntimeException("Missing static main on " + className, ex);} 
catch (SecurityException ex) {throw new RuntimeException("Problem getting static main on " + className, ex);}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);}
/** This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/// 3return new MethodAndArgsCaller(m, argv);
}

首先,在注釋1處,通過發(fā)射得到了SystemServer類。接著,在注釋2處,找到了SystemServer中的main()方法。最后,在注釋3處,會將main()方法傳入MethodAndArgsCaller()方法中,這里的MethodAndArgsCaller()方法是一個Runnable實例,它最終會一直返回出去,直到在ZygoteInit的main()方法中被使用,如下所示:

if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} 
in the parent (zygote) process, and {
@code r != null} 
in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}

可以看到,最終直接調用了這個Runnable實例的run()方法,代碼如下所示:

/*** Helper class which holds a method and arguments and can call them. This is used as part of
* a trampoline to get rid of the initial process setup stack frames.
*/
static class MethodAndArgsCaller implements Runnable {
/** method to call 
*/private final Method mMethod;
/** argument array 
*/private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;mArgs = args;}
public void run() {try {
// 1mMethod.invoke(null, new Object[] { 
mArgs });} 
catch (IllegalAccessException ex) {throw new RuntimeException(ex);} 
catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} 
else if (cause instanceof Error) {
throw (Error) cause;}
throw new RuntimeException(ex);
}
}
}

在注釋1處,這個mMethod就是指的SystemServer的main()方法,這里動態(tài)調用了SystemServer的main()方法,最終,SystemServer進程就進入了SystemServer的main()方法中了。這里還有個遺留問題,為什么不直接在findStaticMain()方法中直接動態(tài)調用SystemServer的main()方法呢?原因就是這種遞歸返回后再執(zhí)行入口方法的方式會讓SystemServer的main()方法看起來像是SystemServer的入口方法,而且,這樣也會清除之前所有SystemServer相關設置過程中需要的堆棧幀。

--------走到 SystemService 進程

  1. /frameworks/base/services/java/com/android/server/SystemServer.java

接下來我們看看SystemServer的main()方法:

/**
* The main entry point from zygote.
*/
public static void main(String[] args) 
{
new SystemServer().run();
}

main()方法中調用了SystemServer的run()方法,如下所示:

private void run() {try {...
// 1Looper.prepareMainLooper();...
// Initialize native services.
// 2System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.performPendingShutdown();
// Initialize the system context.createSystemContext();
// Create the system service manager.
// 3mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.get();} 
finally {traceEnd();  
// InitBeforeStartServices}
// Start services.try {
traceBeginAndSlog("StartServices");
// 4startBootstrapServices();
// 5startCoreServices();
//6startOtherServices();
SystemServerInitThreadPool.shutdown();} 
catch (Throwable ex) {Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;} 
finally {
traceEnd();
}...
// Loop forever.
// 7Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

在注釋1處,創(chuàng)建了消息Looper。

在注釋2處,加載了動態(tài)庫libandroid_servers.so。

在注釋3處,創(chuàng)建了SystemServerManager,它的作用是對系統(tǒng)服務進行創(chuàng)建、啟動和生命周期管理。

在注釋4處的startBootstarpServices()方法中使用SystemServiceManager啟動了ActivityManagerService、PackageManagerService、PowerManagerService等引導服務。

在注釋5處的startCoreServices()方法中則啟動了BatteryService、WebViewUpdateService、DropBoxManagerService、UsageStatsService4個核心服務。

在注釋6處的startOtherServices()方法中啟動了WindowManagerService、InputManagerService、CameraService等其它服務。這些服務的父類都是SystemService。

可以看到,上面把系統(tǒng)服務分成了三種類型:引導服務、核心服務、其它服務。這些系統(tǒng)服務共有100多個,其中對于我們來說比較關鍵的有:

  • 引導服務:ActivityManagerService,負責四大組件的啟動、切換、調度。
  • 引導服務:PackageManagerService,負責對APK進行安裝、解析、刪除、卸載等操作。
  • 引導服務:PowerManagerService,負責計算系統(tǒng)中與Power相關的計算,然后決定系統(tǒng)該如何反應。
  • 核心服務:BatteryService,管理電池相關的服務。
  • 其它服務:WindowManagerService,窗口管理服務。
  • 其它服務:InputManagerService,管理輸入事件。

很多系統(tǒng)服務的啟動邏輯都是類似的,這里我以啟動ActivityManagerService服務來進行舉例,代碼如下所示:

mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();

SystemServiceManager 的 startService() 方法啟動了ActivityManagerService,該啟動方法如下所示:

@SuppressWarnings("unchecked")
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {final String name = serviceClass.getName();
...try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);
// 1service = constructor.newInstance(mContext);
} 
catch (InstantiationException ex) {...
// 2startService(service);return service;
} 
finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}

在注釋1處使用反射創(chuàng)建了ActivityManagerService實例,并在注釋2處調用了另一個startService()重載方法,如下所示:

public void startService(@NonNull final SystemService service) {
// Register it.
// 1mServices.add(service);
// Start it.long time = SystemClock.elapsedRealtime();
try {
// 2service.onStart();
} 
catch (RuntimeException ex) 
{
throw new RuntimeException("Failed to start service " + service.getClass().getName()+ ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}

在注釋1處,首先會將ActivityManagerService添加在mServices中,它是一個存儲SystemService類型的ArrayList,這樣就完成了ActivityManagerService的注冊。

在注釋2處,調用了ActivityManagerService的onStart()方法完成了啟動ActivityManagerService服務。

除了使用SystemServiceManager的startService()方法來啟動系統(tǒng)服務外,也可以直接調用服務的main()方法來啟動系統(tǒng)服務,如PackageManagerService:

mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

這里直接調用了PackageManagerService的main()方法:

public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.PackageManagerServiceCompilerMapping.checkProperties();
// 1PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);
m.enableSystemUserPackages();
// 2ServiceManager.addService("package", m);
// 3final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}

在注釋1處,直接新建了一個PackageManagerService實例,

注釋2處將PackageManagerService注冊到服務大管家ServiceManager中,ServiceManager用于管理系統(tǒng)中的各種Service,用于系統(tǒng)C/S架構中的Binder進程間通信,即如果Client端需要使用某個Servcie,首先應該到ServiceManager查詢Service的相關信息,然后使用這些信息和該Service所在的Server進程建立通信通道,這樣Client端就可以服務端進程的Service進行通信了。

7. SystemService 進程總結

SystemService的啟動流程分析至此已經(jīng)完結,經(jīng)過以上的分析可知,SystemService進程被創(chuàng)建后,主要的處理如下:

  • 1、啟動Binder線程池,這樣就可以與其他進程進行Binder跨進程通信。
  • 2、創(chuàng)建SystemServiceManager,它用來對系統(tǒng)服務進行創(chuàng)建、啟動和生命周期管理。
  • 3、啟動各種系統(tǒng)服務:引導服務、核心服務、其他服務,共100多種。應用開發(fā)主要關注引導服務ActivityManagerService、PackageManagerService和其他服務WindowManagerService、InputManagerService即可。
http://www.risenshineclean.com/news/37841.html

相關文章:

  • 網(wǎng)站浮動窗口如何做江西seo推廣
  • 建設網(wǎng)站企業(yè)排行網(wǎng)絡營銷工程師前景
  • 網(wǎng)站開發(fā)費用稅常德網(wǎng)站設計
  • wordpress主題ruikedu正規(guī)seo關鍵詞排名哪家專業(yè)
  • 怎么做app和網(wǎng)站購物最好的營銷策劃公司
  • php網(wǎng)站后臺管理模板推廣排名
  • 什么是網(wǎng)站排名優(yōu)化百度關鍵詞挖掘工具
  • 廣廣東網(wǎng)站建設百度軟件下載中心官方網(wǎng)站
  • 網(wǎng)站建設頁面設計南寧百度seo軟件
  • 姑蘇網(wǎng)站制作國家免費培訓機構
  • 公司要網(wǎng)站建設實時熱搜
  • 梧州市網(wǎng)站建設seo是什么級別
  • 專業(yè)網(wǎng)站構建谷歌優(yōu)化的最佳方案
  • wordpress怎么復制頁面福州網(wǎng)站優(yōu)化公司
  • 南昌網(wǎng)站建設web8848百度一下 官方網(wǎng)
  • 企業(yè)做網(wǎng)站的注意什么百度用戶服務中心官網(wǎng)
  • 常德網(wǎng)站建設案例教程seo培訓一對一
  • 怎么做查詢網(wǎng)站網(wǎng)站排名怎么做上去
  • 做建筑的網(wǎng)站百度百科創(chuàng)建
  • 織夢做的網(wǎng)站怎么樣今日新聞最新事件
  • 減肥養(yǎng)生網(wǎng)站建設自制網(wǎng)站教程
  • 衡水建設投資集團網(wǎng)站萬能軟文范例800字
  • 網(wǎng)站加載頁模板太倉seo網(wǎng)站優(yōu)化軟件
  • 那個網(wǎng)站專做地質基礎信息域名查詢服務器
  • 網(wǎng)站在工信部備案百度seo優(yōu)化招聘
  • 網(wǎng)站為什么不被收錄網(wǎng)絡營銷工具包括
  • 3建設營銷型網(wǎng)站流程圖生成關鍵詞的軟件免費
  • 基于web前端的旅游網(wǎng)站論文自己做一個網(wǎng)站需要多少錢
  • 北京網(wǎng)站制作公司興田德潤可信賴網(wǎng)絡營銷主要學什么
  • 企業(yè)網(wǎng)站建設方案價位企業(yè)網(wǎng)站設計服務