Android SystemServer 启动流程

原文地址:

Android SystemServer学习

http://blog.csdn.net/cloudwu007/article/details/6701765

 

Linux内核启动后,Android系统启动有4个步骤;

(1)init进程启动

(2)Native服务启动

(3)System Server及Java服务启动

(4)Home启动


Init进程启动后,将根据init.rc及initXXX.rc的内容执行一系列的命令,包括创建mount目录,安装文件系统,设置属性,启动adb,systemserver,mediaserver


system/core/rootdir/init.rc 内容如下




代码中service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server将启动systemserver。



具体调用路径如下:


app_process主入口函数,启动system server时命令行为app_process -Xzygote /system/bin --zygote --start-system-server。

frameworks/base/cmds/app_process/app_main.cpp


启动ZygoteInit进程,以后所有的java进程均须通过此进程fork而成。


frameworks/base/core/jni/AndroidRuntime.cpp

 


ZygoteInit进程入口函数:

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

启动system server。
  1.     privatestatic boolean startSystemServer() 
  2.             throws MethodAndArgsCaller, RuntimeException { 
  3.         /* Hardcoded command line to start the system server */ 
  4.         String args[] = { 
  5.             "--setuid=1000"
  6.             "--setgid=1000",             
  7. ...         "--capabilities=130104352,130104352"
  8.             "--runtime-init"
  9.             "--nice-name=system_server"
  10.             "com.android.server.SystemServer",//指定要启动的类名 
  11.         }; 
  12.         ZygoteConnection.Arguments parsedArgs = null;... 
  13.         try
  14.             parsedArgs = new ZygoteConnection.Arguments(args); 
  15. ... 
  16.             /* Request to fork the system server process */ 
  17.             pid = Zygote.forkSystemServer(                  //fork出进程 
  18.                     parsedArgs.uid, parsedArgs.gid, 
  19.                     parsedArgs.gids, debugFlags, null, 
  20.                     parsedArgs.permittedCapabilities, 
  21.                     parsedArgs.effectiveCapabilities); 
  22.         } catch (IllegalArgumentException ex) { 
  23.             throw new RuntimeException(ex); 
  24.         } 
  25.  
  26.         /* For child process */ 
  27.         if (pid == 0) { 
  28.             handleSystemServerProcess(parsedArgs);         //在fork出的进程里执行systemserver启动 
  29.         } 
  30.  
  31.         return true
  32.     } 


进程fork出来后,关闭socket并初始化进程

  1. private staticvoid handleSystemServerProcess( 
  2.         ZygoteConnection.Arguments parsedArgs) 
  3.         throws ZygoteInit.MethodAndArgsCaller { 
  4.     closeServerSocket(); 
  5.     RuntimeInit.zygoteInit(parsedArgs.remainingArgs); 


所有java进程的共同入口zygoteInit()。


frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
  1.     public static final void zygoteInit(String[] argv) 
  2.             throws ZygoteInit.MethodAndArgsCaller { 
  3. ... 
  4.         commonInit();  //初始化时区,设置agent 
  5.         zygoteInitNative();    //调用到com_android_internal_os_RuntimeInit_zygoteInit@AndroidRuntime.cpp -> gCurRuntime->onZygoteInit(),此处启动ThreadPool 
  6. ... 
  7.         invokeStaticMain(startClass, startArgs); //调用com.android.server.SystemServer的main方法 
  8.     } 


zygoteInitNative()将调用到JNI方法,并最终调用到onZygoteInit以启动进程池。

frameworks/base/cmds/app_process/app_main.cpp

  1. virtual void onZygoteInit() 
  2.     sp<ProcessState> proc = ProcessState::self(); 
  3.     if (proc->supportsProcesses()) { 
  4.         LOGV("App process: starting thread pool.\n"); 
  5.         proc->startThreadPool(); //启动线程池处理Binder事件 
  6.     }         

systemServer进程主函数入口:

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

  1. public staticvoid main(String[] args) { 
  2.  
  3.     // The system server has to run all of the time, so it needs to be 
  4.     // as efficient as possible with its memory usage. 
  5.     VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); 
  6.  
  7.     System.loadLibrary("android_servers");//Load JNI library here that is used by SystemServer 
  8.     init1(args);     //这里调用到android_server_SystemServer_init1@com_android_server_SystemServer.cpp 

systemServer初始化函数1,用来启动进程内所有的native服务,因为其他java服务依赖这些服务。

frameworks/base/services/jni/com_android_server_SystemServer.cpp

  1. static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) 
  2.     system_init(); 


frameworks/base/cmds/system_server/library/system_init.cpp

  1. extern "C" status_t system_init() 
  2.     sp<ProcessState> proc(ProcessState::self()); 
  3.      
  4.     sp<IServiceManager> sm = defaultServiceManager(); 
  5.     LOGI("ServiceManager: %p\n", sm.get()); 
  6.      
  7.     sp<GrimReaper> grim = new GrimReaper(); 
  8.     sm->asBinder()->linkToDeath(grim, grim.get(), 0); 
  9.      
  10.     char propBuf[PROPERTY_VALUE_MAX]; 
  11.     property_get("system_init.startsurfaceflinger", propBuf,"1"); 
  12.     if (strcmp(propBuf, "1") == 0) {        //可以通过改变属性来设置SurfaceFlinger是否run在systemserver里 
  13.         // Start the SurfaceFlinger 
  14.         SurfaceFlinger::instantiate(); 
  15.     } 
  16.  
  17.     // Start the sensor service 
  18.     SensorService::instantiate();       //启动SensorService 
  19.  
  20.     // On the simulator, audioflinger et al don't get started the 
  21.     // same way as on the device, and we need to start them here 
  22.     if (!proc->supportsProcesses()) {//在phone上,这些service在mediaserver中创建。模拟器上,以下service在此进程创建 
  23.  
  24.         // Start the AudioFlinger 
  25.         AudioFlinger::instantiate(); 
  26.  
  27.         // Start the media playback service 
  28.         MediaPlayerService::instantiate(); 
  29.  
  30.         // Start the camera service 
  31.         CameraService::instantiate(); 
  32.  
  33.         // Start the audio policy service 
  34.         AudioPolicyService::instantiate(); 
  35.     } 
  36.      
  37.     AndroidRuntime* runtime = AndroidRuntime::getRuntime(); 
  38.  
  39.     runtime->callStatic("com/android/server/SystemServer","init2");//调用init2@SystemServer.java,在这里创建工作线程以启动各java服务并进入循环处理各service请求 
  40.          
  41.     if (proc->supportsProcesses()) { 
  42.         ProcessState::self()->startThreadPool();  //启动线程池,注意:由于前面已经调用过startThreadPool,故此次调用不做任何事情 
  43.         IPCThreadState::self()->joinThreadPool(); //主线程加入到线程池里 
  44.     } 
  45.     return NO_ERROR; 

进程初始化函数init2,用来启动进程内所有的java服务。

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

  1. public class SystemServer 
  2.     public static finalvoid init2() { 
  3.         Slog.i(TAG, "Entered the Android system server!"); 
  4.         Thread thr = new ServerThread();              //创建新线程 
  5.         thr.setName("android.server.ServerThread"); 
  6.         thr.start();     //启动工作线程,在此线程启动各种服务 
  7.     } 


此工作线程(线程1)实现Java Service注册初始化及进入SystemServer事件处理循环。

  1. class ServerThread extends Thread { 
  2.     @Override 
  3.     public void run() { 
  4.         Looper.prepare();          //在此线程内处理system server相关消息 
  5.  
  6.         android.os.Process.setThreadPriority( 
  7.                 android.os.Process.THREAD_PRIORITY_FOREGROUND); 
  8.  
  9.         BinderInternal.disableBackgroundScheduling(true); 
  10.         android.os.Process.setCanSelfBackground(false); 
  11.          // Critical services... 
  12.         try
  13.             ServiceManager.addService("entropy",new EntropyService());//注册Service到ServiceManager 
  14.             power = new PowerManagerService(); 
  15.             ServiceManager.addService(Context.POWER_SERVICE, power); 
  16.             context = ActivityManagerService.main(factoryTest); //注意:此处启动ActivityManagerService 
  17. ... 
  18.             pm = PackageManagerService.main(context,factoryTest != SystemServer.FACTORY_TEST_OFF); 
  19.             ActivityManagerService.setSystemProcess(); 
  20. ... 
  21.             ContentService.main(context,factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL); 
  22.             ActivityManagerService.installSystemProviders() 
  23. ... 
  24.             wm = WindowManagerService.main(context, power,factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);//启动Windows Manager 
  25.             ServiceManager.addService(Context.WINDOW_SERVICE, wm); 
  26.             ((ActivityManagerService)ServiceManager.getService("activity")).setWindowManager(wm); 
  27. ... 
  28.          wm.systemReady();          //通知SystemReady 
  29.         power.systemReady(); 
  30.         try
  31.             pm.systemReady(); 
  32.         } catch (RemoteException e) { 
  33.         } 
  34. ... 
  35.         // We now tell the activity manager it is okay to run third party 
  36.         // code.  It will call back into us once it has gotten to the state 
  37.         // where third party code can really run (but before it has actually 
  38.         // started launching the initial applications), for us to complete our 
  39.         // initialization. 
  40.         ((ActivityManagerService)ActivityManagerNative.getDefault()) 
  41.                 .systemReady(new Runnable() { 
  42.             public void run() { 
  43.                 if (statusBarF != null) statusBarF.systemReady2(); 
  44.                 if (batteryF != null) batteryF.systemReady(); 
  45.                 if (connectivityF != null) connectivityF.systemReady(); 
  46.                 if (dockF != null) dockF.systemReady(); 
  47.                 if (usbF != null) usbF.systemReady(); 
  48.                 if (uiModeF != null) uiModeF.systemReady(); 
  49.                 if (recognitionF != null) recognitionF.systemReady(); 
  50.                 Watchdog.getInstance().start(); 
  51.  
  52.                 // It is now okay to let the various system services start their 
  53.                 // third party code... 
  54.  
  55.                 if (appWidgetF != null) appWidgetF.systemReady(safeMode); 
  56.                 if (wallpaperF != null) wallpaperF.systemReady(); 
  57.                 if (immF != null) immF.systemReady(); 
  58.                 if (locationF != null) locationF.systemReady(); 
  59.                 if (throttleF != null) throttleF.systemReady(); 
  60.             } 
  61. ... 
  62.         Looper.loop(); //进入循环,处理请求 
  63.     } 

ActivityManagerService主入口:

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java


  1. <span style="font-size:18px;">   publicstaticfinal Context main(int factoryTest) { 
  2.         AThread thr = new AThread();   //创建工作线程2 
  3.         thr.start();                    //启动线程 
  4.  
  5.         synchronized (thr) {//等待</span><span style="font-size:16px;"><span style="font-size:18px;">ActivityManagerService对象创建完成 
  6.             while (thr.mService == null) { 
  7.                 try
  8.                     thr.wait(); 
  9.                 } catch (InterruptedException e) { 
  10.                 } 
  11.             } 
  12.         }</span> 
  13.         ActivityManagerService m = thr.mService; 
  14.         mSelf = m; 
  15.  
  16.         ActivityThread at = ActivityThread.systemMain(); //加载system应用,并把此线程(工作线程1)作为SystemServer进程的system线程 
  17.         mSystemThread = at; 
  18.         Context context = at.getSystemContext(); 
  19.         m.mContext = context; 
  20.         m.mFactoryTest = factoryTest; 
  21.         m.mMainStack = new ActivityStack(m, context,true); 
  22.          
  23.         m.mBatteryStatsService.publish(context); 
  24.         m.mUsageStatsService.publish(context); 
  25.  
  26.         synchronized (thr) { 
  27.             thr.mReady = true
  28.             thr.notifyAll(); 
  29.         } 
  30.  
  31.         m.startRunning(null,null,null,null);//初始化变量并设置system ready为true 
  32.          
  33.         return context; 
  34.     }</span> 


线程2中作为ActivityManager的工作线程,在其中处理ActivityManager相关的消息。

  1. static class AThreadextends Thread { 
  2.     ActivityManagerService mService; 
  3.     boolean mReady = false
  4.  
  5.     public AThread() { 
  6.         super("ActivityManager"); 
  7.     } 
  8.  
  9.     public void run() { 
  10.         Looper.prepare(); 
  11.  
  12.         android.os.Process.setThreadPriority( 
  13.                 android.os.Process.THREAD_PRIORITY_FOREGROUND); 
  14.         android.os.Process.setCanSelfBackground(false); 
  15.  
  16.         ActivityManagerService m = new ActivityManagerService(); 
  17.  
  18.         synchronized (this) { 
  19.             mService = m; 
  20.             notifyAll(); 
  21.         } 
  22.  
  23.         synchronized (this) { 
  24.             while (!mReady) { 
  25.                 try
  26.                     wait(); 
  27.                 } catch (InterruptedException e) { 
  28.                 } 
  29.             } 
  30.         } 
  31.  
  32.         Looper.loop(); 
  33.     } 


ActivityThread.systemMain()将加载系统应用apk:


ActivityThread.java

  1.     public static final ActivityThread systemMain() { 
  2.         ActivityThread thread = new ActivityThread(); 
  3.         thread.attach(true);          //加载system应用 
  4.         return thread; 
  5.     } 
  6.  
  7.     private finalvoid attach(boolean system) { 
  8.         sThreadLocal.set(this); 
  9.         mSystemThread = system; 
  10.         if (!system) {...             
  11.         } else
  12.             // Don't set application object here -- if the system crashes, 
  13.             // we can't display an alert, we just want to die die die. 
  14.             android.ddm.DdmHandleAppName.setAppName("system_process"); 
  15.             try
  16.                 mInstrumentation = new Instrumentation(); 
  17.                 ContextImpl context = new ContextImpl(); 
  18.                 context.init(getSystemContext().mPackageInfo, null, this); 
  19.                 Application app = Instrumentation.newApplication(Application.class, context);//创建Application对象并实例化android.app.Application对象 
  20.                 mAllApplications.add(app); 
  21.                 mInitialApplication = app; 
  22.                 app.onCreate();  //调用onCreate 
  23.             } catch (Exception e) { 
  24.                 throw new RuntimeException( 
  25.                         "Unable to instantiate Application():" + e.toString(), e); 
  26.             } 
  27.         } 


ActivityManagerService.java

  1. public finalvoid startRunning(String pkg, String cls, String action, 
  2.         String data) { 
  3.     synchronized(this) { 
  4.         if (mStartRunning) { 
  5.             return
  6.         } 
  7.         mStartRunning = true
  8.         mTopComponent = pkg != null && cls !=null 
  9.                 ? new ComponentName(pkg, cls) :null
  10.         mTopAction = action != null ? action : Intent.ACTION_MAIN; 
  11.         mTopData = data; 
  12.         if (!mSystemReady) { 
  13.             return
  14.         } 
  15.     } 
  16.  
  17.     systemReady(null);       //设置system ready为true,但此句似乎无用因为mSystemReady此时必然为true,故调用systemReady(null)什么事也不做 


  1.     public void systemReady(final Runnable goingCallback) {... 
  2.         synchronized(this) { 
  3.             if (mSystemReady) { 
  4.                 if (goingCallback !=null) goingCallback.run(); //如果有Runnable要运行 
  5.                 return
  6.             } 
  7.              
  8.             // Check to see if there are any update receivers to run. 
  9.             if (!mDidUpdate) { 
  10.                 if (mWaitingUpdate) { 
  11.                     return
  12.                 } 
  13.                 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); 
  14.                 List<ResolveInfo> ris = null
  15.                 try
  16.                     ris = AppGlobals.getPackageManager().queryIntentReceivers( 
  17.                                 intent, null, 0); 
  18.                 } catch (RemoteException e) { 
  19.                 } 
  20.                 if (ris != null) { 
  21.                     for (int i=ris.size()-1; i>=0; i--) { 
  22.                         if ((ris.get(i).activityInfo.applicationInfo.flags 
  23.                                 &ApplicationInfo.FLAG_SYSTEM) ==0) { 
  24.                             ris.remove(i); 
  25.                         } 
  26.                     } 
  27.                     intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE); 
  28.                      
  29.                     ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers(); 
  30.                      
  31.                     final ArrayList<ComponentName> doneReceivers =new ArrayList<ComponentName>(); 
  32.                     for (int i=0; i<ris.size(); i++) { 
  33.                         ActivityInfo ai = ris.get(i).activityInfo; 
  34.                         ComponentName comp = new ComponentName(ai.packageName, ai.name); 
  35.                         if (lastDoneReceivers.contains(comp)) { 
  36.                             ris.remove(i); 
  37.                             i--; 
  38.                         } 
  39.                     } 
  40.                      
  41.                     for (int i=0; i<ris.size(); i++) { 
  42.                         ActivityInfo ai = ris.get(i).activityInfo; 
  43.                         ComponentName comp = new ComponentName(ai.packageName, ai.name); 
  44.                         doneReceivers.add(comp); 
  45.                         intent.setComponent(comp); 
  46.                         IIntentReceiver finisher = null
  47.                         if (i == ris.size()-1) { 
  48.                             finisher = new IIntentReceiver.Stub() { 
  49.                                 publicvoid performReceive(Intent intent,int resultCode, 
  50.                                         String data, Bundle extras, boolean ordered, 
  51.                                         boolean sticky) { 
  52.                                     // The raw IIntentReceiver interface is called 
  53.                                     // with the AM lock held, so redispatch to 
  54.                                     // execute our code without the lock. 
  55.                                     mHandler.post(new Runnable() { 
  56.                                         publicvoid run() { 
  57.                                             synchronized (ActivityManagerService.this) { 
  58.                                                 mDidUpdate = true
  59.                                             } 
  60.                                             writeLastDonePreBootReceivers(doneReceivers); 
  61.                                             systemReady(goingCallback); 
  62.                                         } 
  63.                                     }); 
  64.                                 } 
  65.                             }; 
  66.                         } 
  67.                         broadcastIntentLocked(null,null, intent,null, finisher, 
  68.                                 0, null, null,null,true,false, MY_PID, Process.SYSTEM_UID); 
  69.                         if (finisher !=null) { 
  70.                             mWaitingUpdate = true
  71.                         } 
  72.                     } 
  73.                 } 
  74.                 if (mWaitingUpdate) { 
  75.                     return
  76.                 } 
  77.                 mDidUpdate = true
  78.             } 
  79.              
  80.             mSystemReady = true;    //置位 
  81.             // silent reboot bit will be off on normal power down 
  82.             if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_poweron_sound)) { 
  83.                 ConfigInfo.pwrSnd_setSilentreboot(1); 
  84.             } else if (mContext.getResources() 
  85.                     .getBoolean(com.android.internal.R.bool.config_mute_poweron_sound)) { 
  86.                 // Request that the next BootAnimation plays its sound. 
  87.                 ConfigInfo.pwrSnd_setSilentreboot(0); 
  88.             } 
  89.  
  90.             if (!mStartRunning) { //如果ActivityManagerService.startRunning已运行过,则无需继续 
  91.                 return
  92.             } 
  93.         } 
  94.  
  95.         ArrayList<ProcessRecord> procsToKill = null
  96.         synchronized(mPidsSelfLocked) { 
  97.             for (int i=mPidsSelfLocked.size()-1; i>=0; i--) { 
  98.                 ProcessRecord proc = mPidsSelfLocked.valueAt(i); 
  99.                 if (!isAllowedWhileBooting(proc.info)){//检查FLAG_PERSISTENT是否为真 
  100.                     if (procsToKill ==null) { 
  101.                         procsToKill = new ArrayList<ProcessRecord>(); 
  102.                     } 
  103.                     procsToKill.add(proc);        //如果应用未指明为persistent,则不能在system ready前运行 
  104.                 } 
  105.             } 
  106.         } 
  107.          
  108.         synchronized(this) { 
  109.             if (procsToKill !=null) { 
  110.                 for (int i=procsToKill.size()-1; i>=0; i--) { 
  111.                     ProcessRecord proc = procsToKill.get(i); 
  112.                     Slog.i(TAG, "Removing system update proc: " + proc); 
  113.                     removeProcessLocked(proc, true);       //杀掉所有已运行的非persistent应用 
  114.                 } 
  115.             } 
  116.              
  117.             // Now that we have cleaned up any update processes, we 
  118.             // are ready to start launching real processes and know that 
  119.             // we won't trample on them any more. 
  120.             mProcessesReady = true;          //为真时,才允许launch正常的应用 
  121.         }...     
  122.         synchronized(this) { 
  123.             // Make sure we have no pre-ready processes sitting around.            
  124. ...  
  125.        retrieveSettings(); 
  126.  
  127.         if (goingCallback !=null) goingCallback.run(); 
  128.          
  129.         synchronized (this) { 
  130.             if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { 
  131.                 try
  132.                     List apps = AppGlobals.getPackageManager(). 
  133.                         getPersistentApplications(STOCK_PM_FLAGS); 
  134.                     if (apps != null) { 
  135.                         int N = apps.size(); 
  136.                         int i; 
  137.                         for (i=0; i<N; i++) { 
  138.                             ApplicationInfo info 
  139.                                 = (ApplicationInfo)apps.get(i); 
  140.                             if (info !=null && 
  141.                                     !info.packageName.equals("android")) { 
  142.                                 addAppLocked(info);         //启动所有标为persistent的且package名字为android的应用 
  143.                             } 
  144.                         } 
  145.                     } 
  146.                 } catch (RemoteException ex) { 
  147.                     // pm is in same process, this will never happen. 
  148.                 } 
  149.             } 
  150.  
  151.             // Start up initial activity. 
  152.             mBooting = true
  153.              
  154.             try
  155.                 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {//如果/data/system文件夹的uid和当前system UID不匹配 
  156.                     Message msg = Message.obtain(); 
  157.                     msg.what = SHOW_UID_ERROR_MSG; 
  158.                     mHandler.sendMessage(msg); 
  159.                 } 
  160.             } catch (RemoteException e) { 
  161.             } 
  162.  
  163.             mMainStack.resumeTopActivityLocked(null);//启动初始进程Home 
  164.         } 
  165.     } 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 12 SystemServer启动流程如下: 1. 引导加载:系统启动时,先加载引导程序,进行硬件初始化、内核加载等操作。 2. Zygote 进程启动:Zygote 是 Android 系统中的一个特殊进程,负责孵化其他应用进程。Zygote 进程会预加载一些常用的类和资源,以加快应用的启动速度。 3. SystemServer 进程启动:Zygote 进程会 fork 出 SystemServer 进程,该进程是 Android 系统中的核心服务进程。SystemServer 进程负责启动和管理系统级别的服务,例如 ActivityManagerService、PackageManagerService、WindowManagerService 等。 4. SystemServer 初始化:SystemServer 进程启动后,会进行一系列的初始化操作。首先会创建 Looper 线程,用于接收消息并处理各个服务的初始化工作。然后依次创建各个系统服务,并调用它们的启动方法。 5. 启动系统服务:SystemServer 进程会按照一定顺序启动各个系统服务。每个系统服务都有自己的初始化流程,例如 PackageManagerService 会加载应用程序列表、数据目录等;ActivityManagerService 会初始化进程间通信机制等。 6. 启动应用进程:在系统服务启动完成后,SystemServer 进程会通过 Zygote 孵化出其他应用进程。应用进程会根据 AndroidManifest.xml 中的配置进行初始化,包括创建 Application、加载资源等。 总结来说,Android 12 SystemServer启动流程包括引导加载、Zygote 进程启动、SystemServer 进程启动、SystemServer 初始化、启动系统服务和启动应用进程等步骤。这些步骤都是为了在系统启动时提供必要的服务和资源。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值