Xposed源码剖析——app_process作用详解

首先吐槽一下CSDN的改版吧,发表这篇文章之前其实我已经将此篇文章写过了两三次了。就是发表不成功。而且CSDN将我的文章草稿也一带>删除掉了。弄得我现在只有使用sublime写一次,保证它们删不掉。


承接上文 http://blog.csdn.net/yzzst/article/details/47659987

上面我们分析Xposed项目的源码,从XposedInstaller开始说明了Xposed安装的原理与过程。我们知道,XposedInstaller主要的工作就是:

  • 替换系统的app_process(当然,这个操作需要Root权限)
  • 将xposed的api文件,XposedBridge.jar文件放置到私有目录中

至于 
为什么要替换app_process文件? 
系统中的app_process文件有什么作用? 
替换后的app_process为什么能够帮助我们hook?

下面我们就开始看看,rovo89大神的xposed开源项目。从GitHub上面clone下来xposed项目,我们在目录中看到其目录结构,如下所示:

从目录中,我们能够清楚的了解到,其中xposed项目现在已经支持Dalvik虚拟机与art虚拟机的架构了。


app_main.cpp 源码阅读与对比

ok这里,我们先从app_process的源码开始阅读,打开app_main.cpp文件,估计大家和我一下,一时间也看不出来xposed针对源码修改了一些什么。

那么,我们就直接拿源码与xposed中的app_main.cpp进行对比。

源码地址:/frameworks/base/cmds/app_process/app_main.cpp

发现了,rovo89针对了一下几个地方进行了修改。

atrace_set_tracing_enabled 进行了替换修改 

onVmCreated 增加了Xposed的回调

main函数中,增加了 xposed 的 options 操作 
 
我们在xposed.cpp中,能够看到其handleOptions的具体逻辑,其实就是处理一些xposed的特殊命令而已。 
如下所示:

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">/** Handle special command line options. */</span>
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">bool</span> handleOptions(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">char</span>* <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> argv[]) {parseXposedProp();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (argc == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">2</span> && <span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">strcmp</span>(argv[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>], <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"--xposedversion"</span>) == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>) {<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Xposed version: %s\n"</span>, xposedVersion);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (argc == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">2</span> && <span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">strcmp</span>(argv[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>], <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"--xposedtestsafemode"</span>) == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>) {<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Testing Xposed safemode trigger\n"</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (detectSafemodeTrigger(shouldSkipSafemodeDelay())) {<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Safemode triggered\n"</span>);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Safemode not triggered\n"</span>);}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;}<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// From Lollipop coding, used to override the process name</span>argBlockStart = argv[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>];uintptr_t start = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">reinterpret_cast</span><uintptr_t>(argv[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>]);uintptr_t end = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">reinterpret_cast</span><uintptr_t>(argv[argc - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>]);end += <span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">strlen</span>(argv[argc - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>]) + <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>;argBlockLength = end - start;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li></ul>

* main函数中,启动的时候增加了启动一些逻辑 * 

具体的, 我们可以看到。runtime.start那一段。做出了一个启动。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    isXposedLoaded = xposed::initialize(zygote, startSystemServer, className, argc, argv);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (zygote) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 当xposed成功启动的时候,start XPOSED_CLASS_DOTS_ZYGOTE这个类</span>runtime.start(isXposedLoaded ? XPOSED_CLASS_DOTS_ZYGOTE : <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"com.android.internal.os.ZygoteInit"</span>,startSystemServer ? <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"start-system-server"</span> : <span class="hljs-string" style="color:#0880;box-sizing: border-box;">""</span>);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (className) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Remainder of args get passed to startup class main()</span>runtime.mClassName = className;runtime.mArgC = argc - i;runtime.mArgV = argv + i;<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 当xposed成功启动的时候,start XPOSED_CLASS_DOTS_ZYGOTE这个类</span>runtime.start(isXposedLoaded ? XPOSED_CLASS_DOTS_TOOLS : <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"com.android.internal.os.RuntimeInit"</span>,application ? <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"application"</span> : <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"tool"</span>);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {fprintf(stderr, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Error: no class name or --zygote supplied.\n"</span>);app_usage();LOG_ALWAYS_FATAL(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"app_process: no class name or --zygote supplied."</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">10</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

这里的我们看到,在main函数中启动了逻辑,

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">runtime.<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">start</span>(isXposedLoaded ? XPOSED_CLASS_DOTS_ZYGOTE : <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"com.android.internal.os.ZygoteInit"</span>,startSystemServer ? <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"start-system-server"</span> : <span class="hljs-string" style="color:#0880;box-sizing: border-box;">""</span>);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

其中,XPOSED_CLASS_DOTS_ZYGOTE 变量在,xposed.h头文件中有定义,如下所示:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">define</span> XPOSED_CLASS_DOTS_ZYGOTE "de.robv.android.xposed.XposedBridge"</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

发现,其实这个类就是我们之前向私有目录防止的XposedBridge项目的包名。

而runtime.start这个包名有什么作用呢?我们在AndroidRuntime中找到start方法的具体逻辑 
在源代码中/frameworks/base/core/jni/AndroidRuntime.cpp中看到

<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">/** Start <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> Android runtime.  This involves starting <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual machine* <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">and</span> calling <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"static void main(String[] args)"</span> method <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> <span class="hljs-type" style="box-sizing: border-box;">class</span>* named <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">by</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"className"</span>.** Passes <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> main function two arguments, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> <span class="hljs-type" style="box-sizing: border-box;">class</span> <span class="hljs-property" style="box-sizing: border-box;">name</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">and</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> specified* options <span class="hljs-type" style="box-sizing: border-box;">string</span>.*/
void AndroidRuntime::start(const char* className, const char* options)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

系统源码对start方法的定义,就是启动对应类的 start void main入口函数。这里,就将三个项目的逻辑连接起来了。


XposedBridge.java

我们在XposedBridge.java代码中,看到其main方法,如下所示:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/*** Called when native methods and other things are initialized, but before preloading classes etc.*/</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Initialize the Xposed framework and modules</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {SELinuxHelper.initOnce();SELinuxHelper.initForProcess(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>);runtime = getRuntime();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (initNative()) {XPOSED_BRIDGE_VERSION = getXposedVersion();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (isZygote) {startsSystemServer = startsSystemServer();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 为启动一个新的 zygote做好 hook准备</span>initForZygote();}<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 载入Xposed的一些modules</span>loadModules();} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {log(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Errors during native Xposed initialization"</span>);}} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Throwable t) {log(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Errors during Xposed initialization"</span>);log(t);disableHooks = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;}<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 调用系统原来的启动方法</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (isZygote)ZygoteInit.main(args);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span>RuntimeInit.main(args);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li></ul>

ok,那么,整个app_process的复制hook逻辑,到这里我们已经清楚了。逻辑如下图所示。

那么,xposed具体怎么实现系统api逻辑的replace和inject我们下次在做分析。

原文地址: http://blog.csdn.net/yzzst/article/details/47829657

Xposed源码剖析——app_process作用详解相关推荐

  1. React 源码系列 | React Context 详解

    目前来看 Context 是一个非常强大但是很多时候不会直接使用的 api.大多数项目不会直接使用 createContext 然后向下面传递数据,而是采用第三方库(react-redux). 想想项 ...

  2. mysql data文件夹恢复_【专注】Zabbix源码安装教程—步骤详解(2)安装并配置mysql...

    四.安装并配置mysql(1) 解压mysql-5.7.26.tar.gz与boost_1_59_0.tar.gz #tar -xvf mysql-5.7.26.tar.gz #tar -xvf bo ...

  3. php+mysql案例含源码_【专注】Zabbix源码安装教程—步骤详解(1)安装前准备

    一.实验环境准备 Rhel 7.6 x86_64(server) 192.168.163.72 Rhel 6.5 x86_64(agent) 192.168.163.61 均已配置操作安装光盘为YUM ...

  4. dockerfile源码安装mysql_docker容器详解五: dockerfile实现tomcat环境以及源码安装mysql...

    tomcat 上一节讲到了dockerfile的基础,这一次咱们来作一个小的练习 首先要了解tomcat安装的整个过程 首先搭建 jdk环境: 下载jdk包,解压以后添加环境变量 而后搭建tomcat ...

  5. Xposed源码剖析——概述

    XPosed是与Cydia其名的工具,它能够让Android设备在没有修改源码的情况下修改系统中的API运行结果.我们通常称之为:God Mode(上帝模式). 之前享大家分享了Xposed的基础,X ...

  6. Xposed源码剖析——Xposed初始化

    承接上文 http://blog.csdn.net/yzzst/article/details/47829657 之前我们看过了app_main.cpp源码,知道了在其中,启动了XposedBridg ...

  7. 未能找到元数据文件_Flink 源码:Checkpoint 元数据详解

    本文是 Flink 源码解析系列,通过阅读本文你能 get 到以下点: Flink 任务从 Checkpoint 处恢复流程概述 Checkpoint 元数据详解 从源码层分析:JM 该如何合理地给每 ...

  8. 源码免杀教程 源码免杀思路详解

    绝对不一样的源码免杀教程!绝对不一样的免杀实战体验!清晰的思路!细致全面的思路详解!让你感到免杀原来可以这么简单!教你如何在源代码中找出被杀代码,修改代码从而达到免杀效果! 免杀之-网络攻防入门书籍推 ...

  9. javaweb_笔记2(Servlet源码分析;request详解;请求域;转发和重定向;WebServlet注解;jsp基础语法,JavaBean。)

    1.HttpServlet源码分析 HttpServlet类是专门为HTTP协议准备的.比GenericServlet更加适合HTTP协议下的开发. HttpServlet在哪个包下? jakarta ...

最新文章

  1. 天翼云从业认证(2.2)云计算的模式、应用和行业生态
  2. NYOJ 275 队花的烦恼一
  3. .NET 开源配置组件 AgileConfig 初体验
  4. 基于墨刀实现的短视频分享软件原型设计
  5. -组件基础-局部组件 // 局部组件的简写
  6. php 静态成员(static)抽象类(abstract)和接口(interface)
  7. linux+应用程序高级编程,linux-----shell高级编程----grep应用
  8. sql在insert的同时把某个字段返回来_项目实践:后端接口统一规范的同时,如何优雅得扩展规范?...
  9. python消费kafka逻辑处理导致cpu升高_爬虫架构|利用Kafka处理数据推送问题(1)
  10. CFS调度器(1)-基本原理
  11. JDK如何安装与配置环境变量
  12. 线性代数【13】基,基本向量、坐标系的构建和线性生成空间SPAN (向量线性相关)
  13. 光纤存储服务器虚拟化,光纤存储DELL MD3600连接VMware ESX 65
  14. mysql删表数据不删表结构_在SQL中删除表数据和删除表结构有什么不同
  15. Karl Rove和Dick Cheney加入了REST争论
  16. 老子《道德经》里的投资之道
  17. 计算机操作系统计算题及答案(5),5计算机操作系统练习题及答案.doc
  18. 您需要对象吗,我帮你new一个吧?
  19. 软件测试这些年的变化及未来发展趋势
  20. 一个北京24岁女孩的征男友要求!

热门文章

  1. 用命令行CMD .bat 相关操作 如: 创建快捷方式 复制文件等
  2. velocity 继续之 语法学习篇
  3. 利用Web Services实现软件自动升级
  4. 求指定范围内的所有素数C++代码实现
  5. Python学习:模块
  6. Python学习笔记:异步IO(2)
  7. 基于VTK的Qt应用程序开发
  8. 吴恩达的 CS229,有人把它浓缩成 6 张中文速查表!
  9. Go协程池设计思路(Task-Job-Worker)
  10. VTK修炼之道23:图像基本操作_灰度图像映射成伪彩色图像(查表法)