{"id":3063,"date":"2026-07-12T20:31:00","date_gmt":"2026-07-12T12:31:00","guid":{"rendered":"https:\/\/cocozq.com\/?p=3063"},"modified":"2026-07-12T20:44:56","modified_gmt":"2026-07-12T12:44:56","slug":"%e4%b8%ba-harmonyos-%e5%ae%9a%e5%88%b6-go-%e5%b7%a5%e5%85%b7%e9%93%be%ef%bc%9a%e5%be%81%e6%9c%8d-musl-emulated-tls","status":"publish","type":"post","link":"https:\/\/cocozq.com\/?p=3063","title":{"rendered":"\u4e3a HarmonyOS \u5b9a\u5236 Go \u5de5\u5177\u94fe\uff1a\u5f81\u670d musl emulated TLS"},"content":{"rendered":"<h1>\u4e3a HarmonyOS \u5b9a\u5236 Go \u5de5\u5177\u94fe\uff1a\u5f81\u670d musl emulated TLS<\/h1>\n<blockquote><p>\n  \u8fd9\u4e24\u5468\u79fb\u690d\u81ea\u5df1\u4e00\u4e2a\u5b89\u5353\u7248\u672c\u677f\u51f3\u8f6f\u4ef6\u5230\u9e3f\u8499Next\u7cfb\u7edf\u4e0a\uff0c\u4eca\u5929\u7ec8\u4e8e\u6210\u529f\u8dd1\u901a\u4e86\uff0c\u8bb0\u5f55\u4e00\u4e0b\u6700\u5173\u952e\u7684\u5b9e\u73b0\u90e8\u5206\n<\/p><\/blockquote>\n<h2>\u524d\u8a00<\/h2>\n<p>Go \u8bed\u8a00\u5bf9 Linux\/arm64 \u5e73\u53f0\u7684\u652f\u6301\u975e\u5e38\u6210\u719f\u2014\u2014\u524d\u63d0\u662f\u4f60\u8fd0\u884c\u5728\u6807\u51c6\u7684 glibc \u73af\u5883\u4e0b\u3002HarmonyOS \u4f7f\u7528 musl libc\uff0c\u5176 emulated TLS \u673a\u5236\u4e0e glibc \u7684 TLS \u5b9e\u73b0\u5b58\u5728\u6839\u672c\u6027\u5dee\u5f02\uff0c\u5bfc\u81f4\u6807\u51c6 Go \u7f16\u8bd1\u7684 c-shared \u5e93\u5728 HarmonyOS VPN \u6c99\u76d2\u4e2d\u65e0\u6cd5\u6b63\u5e38\u52a0\u8f7d\u3002\u672c\u6587\u8be6\u7ec6\u8bb0\u5f55\u4e86\u5bf9 Go 1.21.13 runtime \u6e90\u7801\u8fdb\u884c 12 \u5904\u5173\u952e\u4fee\u6539\u7684\u5168\u8fc7\u7a0b\uff0c\u6db5\u76d6 TLS \u5bfb\u5740\u6a21\u578b\u91cd\u5199\u3001clone \u7cfb\u7edf\u8c03\u7528\u9002\u914d\u3001cgo \u521d\u59cb\u5316\u91cd\u6784\u7b49\u5e95\u5c42\u5de5\u4f5c\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cocozq.com\/zq\/wp-content\/uploads\/2026\/07\/harmonyos_go_runtime.png\" alt=\"harmonyos_go_runtime\" \/><\/p>\n<hr \/>\n<h2>\u4e00\u3001\u95ee\u9898\uff1a\u6807\u51c6 Go \u5728 HarmonyOS \u4e0a\u7684\u5d29\u6e83<\/h2>\n<h3>1.1 \u4f7f\u7528\u573a\u666f<\/h3>\n<p>CocoProxy HarmonyOS \u5ba2\u6237\u7aef\u9700\u8981\u5c06 Go \u4ee3\u7406\u5f15\u64ce\u7f16\u8bd1\u4e3a <code>c-shared<\/code> \u6a21\u5f0f\u7684 <code>.so<\/code> \u6587\u4ef6\uff0c\u901a\u8fc7 NAPI \u88ab VPN Extension Ability \u52a0\u8f7d\u3002\u6784\u5efa\u547d\u4ee4\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-bash line-numbers\">CGO_ENABLED=1 GOOS=linux GOARCH=arm64 \\\nCC=clang CGO_CFLAGS=\"--target=aarch64-linux-ohos --sysroot=...\" \\\ngo build -buildmode=c-shared -tags=\"with_gvisor,ohos\" \\\n  -ldflags=\"-extldflags '... napi_reg.o'\" \\\n  -o libcocoproxy.so\n<\/code><\/pre>\n<h3>1.2 \u5d29\u6e83\u73b0\u8c61<\/h3>\n<p>\u4f7f\u7528\u6807\u51c6 Go 1.21.13 \u7f16\u8bd1\u7684 <code>.so<\/code> \u5728 <code>dlopen<\/code> \u65f6\uff0c<code>.init_array<\/code> \u4e2d\u7684 Go runtime \u521d\u59cb\u5316\u51fd\u6570 <code>_rt0_arm64_linux_lib<\/code> \u5d29\u6e83\u3002\u7531\u4e8e <code>.init_array<\/code> \u6309\u987a\u5e8f\u6267\u884c\uff0c\u540e\u7eed\u7684 <code>RegisterCocoProxyModule<\/code>\uff08NAPI \u6a21\u5757\u6ce8\u518c\u51fd\u6570\uff09\u6c38\u8fdc\u4e0d\u4f1a\u88ab\u8c03\u7528\uff0c\u5bfc\u81f4\uff1a<\/p>\n<pre><code class=\"line-numbers\">ArkCompiler: module libcocoproxy.so does not provide an export name 'getDebug'\n<\/code><\/pre>\n<h3>1.3 \u5d29\u6e83\u7684\u6839\u56e0<\/h3>\n<p>\u5d29\u6e83\u53d1\u751f\u5728 Go runtime \u5c1d\u8bd5\u901a\u8fc7 TLS \u8bbf\u95ee goroutine \u7684 <code>g<\/code> \u6307\u9488\u65f6\u3002\u6807\u51c6 Go \u5047\u8bbe\u7684\u662f glibc \u98ce\u683c\u7684 TLS \u5b9e\u73b0\uff0c\u800c HarmonyOS \u7684 musl libc \u4f7f\u7528\u5b8c\u5168\u4e0d\u540c\u7684 emulated TLS \u673a\u5236\u3002<\/p>\n<hr \/>\n<h2>\u4e8c\u3001TLS \u5b9e\u73b0\u5dee\u5f02\uff1aglibc vs musl<\/h2>\n<h3>2.1 glibc TLS \u5de5\u4f5c\u539f\u7406<\/h3>\n<p>\u5728 glibc \u73af\u5883\u4e0b\uff0cTLS \u53d8\u91cf\u901a\u8fc7\u7ebf\u7a0b\u6307\u9488\uff08TP\uff09\u76f4\u63a5\u5bfb\u5740\u3002\u5185\u6838\u5728\u521b\u5efa\u7ebf\u7a0b\u65f6\u8bbe\u7f6e TPIDR_EL0 \u5bc4\u5b58\u5668\u6307\u5411 TLS \u5757\uff0c\u6bcf\u4e2a TLS \u53d8\u91cf\u6709\u4e00\u4e2a\u76f8\u5bf9\u4e8e TP \u7684\u56fa\u5b9a\u504f\u79fb\u91cf\uff1a<\/p>\n<pre><code class=\"line-numbers\">\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                    glibc TLS \u6a21\u578b                        \u2502\n\u2502                                                          \u2502\n\u2502  TPIDR_EL0 \u2500\u2500\u2192 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                  \u2502\n\u2502                \u2502  TLS \u53d8\u91cf 1 (offset=0)  \u2502                  \u2502\n\u2502                \u2502  TLS \u53d8\u91cf 2 (offset=8)  \u2502                  \u2502\n\u2502                \u2502  ...                    \u2502                  \u2502\n\u2502                \u2502  tls_g \u504f\u79fb\u91cf (\u5982 0x10)  \u2502 \u2190 \u8fd0\u884c\u65f6\u8ba1\u7b97   \u2502\n\u2502                \u2502  ...                    \u2502                  \u2502\n\u2502                \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                  \u2502\n\u2502                                                          \u2502\n\u2502  \u8bbf\u95ee TLS \u53d8\u91cf:                                           \u2502\n\u2502    __asm__(\"mrs %0, tpidr_el0\" : \"=r\"(tp));              \u2502\n\u2502    value = *(tp + offset);        \u2190 \u76f4\u63a5\u52a0\u504f\u79fb\u91cf\u8bbf\u95ee       \u2502\n\u2502                                                          \u2502\n\u2502  Go runtime \u7684 load_g:                                    \u2502\n\u2502    MRS TPIDR_EL0, R0                                     \u2502\n\u2502    MOVD tls_g(SB), R11                                   \u2502\n\u2502    MOVD (R0)(R11), g      \u2190 g = *(TP + tls_g)  \u4e00\u7ea7\u95f4\u63a5  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n<\/code><\/pre>\n<p>Go runtime \u7684 <code>tls_g<\/code> \u53d8\u91cf\u5b58\u50a8\u7684\u504f\u79fb\u91cf\u6307\u5411 TLS \u5757\u4e2d\u4e00\u4e2a 8 \u5b57\u8282\u7684 slot\uff0c\u8be5 slot \u76f4\u63a5\u5b58\u653e <code>g<\/code> \u6307\u9488\u3002\u8fd9\u662f\u4e00\u7ea7\u95f4\u63a5\u5bfb\u5740\uff1a<code>*(TP + tls_g) = g<\/code>\u3002<\/p>\n<h3>2.2 musl emulated TLS \u5de5\u4f5c\u539f\u7406<\/h3>\n<p>musl libc \u8fd0\u884c\u5728\u6ca1\u6709\u5185\u6838 TLS \u652f\u6301\u6216 TLS \u63cf\u8ff0\u7b26\uff08TLS descriptor\uff09\u4e0d\u53ef\u7528\u7684\u73af\u5883\u4e2d\uff0c\u91c7\u7528&#8221;\u6a21\u62df TLS&#8221;\u65b9\u6848\uff1a<\/p>\n<ul>\n<li>\u4e0d\u4f7f\u7528 <code>__tls_get_addr<\/code> \u7cfb\u7edf\u8c03\u7528<\/li>\n<li>TLS \u53d8\u91cf\u5b58\u50a8\u5728\u7ebf\u7a0b\u7279\u5b9a\u6570\u636e\uff08TSD\uff09\u533a\u4e2d\uff0c\u901a\u8fc7 <code>pthread_key<\/code> \u673a\u5236\u7ba1\u7406<\/li>\n<li><code>pthread_setspecific(key, value)<\/code> \u5c06\u503c\u5b58\u50a8\u5728 TP \u9644\u8fd1\u7684 TSD \u6570\u7ec4\u4e2d<\/li>\n<li><code>pthread_getspecific(key)<\/code> \u4ece TSD \u6570\u7ec4\u4e2d\u8bfb\u53d6\u503c<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                  musl emulated TLS \u6a21\u578b                   \u2502\n\u2502                                                          \u2502\n\u2502  TPIDR_EL0 \u2500\u2500\u2192 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                  \u2502\n\u2502                \u2502  TSD slot 0           \u2502                  \u2502\n\u2502                \u2502  TSD slot 1           \u2502                  \u2502\n\u2502                \u2502  ...                  \u2502                  \u2502\n\u2502    tls_g \u2500\u2500\u2192   \u2502  TSD slot[k] \u2500\u2500\u2192 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510             \u2502\n\u2502                \u2502  ...              \u2502 g_slot \u2502 \u2190 malloc \u5206\u914d\u2502\n\u2502                \u2502                    \u2514\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2518             \u2502\n\u2502                \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518               \u2502\n\u2502                                          \u2502                \u2502\n\u2502                                          \u25bc                \u2502\n\u2502                                     g = *g_slot           \u2502\n\u2502                                                          \u2502\n\u2502  \u8bbf\u95ee TLS \u53d8\u91cf:                                           \u2502\n\u2502    pthread_getspecific(key) \u2192 \u641c\u7d22 TSD \u6570\u7ec4\u627e\u5230 slot     \u2502\n\u2502    \u6216\u8005: *(TP + computed_offset) \u2192 slot \u6307\u9488 \u2192 value     \u2502\n\u2502                                                          \u2502\n\u2502  \u5173\u952e\u5dee\u5f02: *(TP + tls_g) \u4e0d\u662f g \u503c\uff0c                      \u2502\n\u2502            \u800c\u662f g_slot \u7684\u6307\u9488\uff01                            \u2502\n\u2502            \u9700\u8981 *( *(TP + tls_g) ) = g  \u4e24\u7ea7\u95f4\u63a5          \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n<\/code><\/pre>\n<h3>2.3 \u5dee\u5f02\u5bf9\u6bd4<\/h3>\n<pre><code class=\"line-numbers\">              glibc                          musl\n         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\nTP \u2500\u2500\u2192   \u2502 slot[k]  \u2502 = g             \u2502 slot[k]  \u2502 \u2500\u2500\u2192 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n         \u2502          \u2502                  \u2502          \u2502     \u2502 g_ptr \u2502 = g\n         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518     \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n  \u8bbf\u95ee\u65b9\u5f0f:                       \u8bbf\u95ee\u65b9\u5f0f:\n  *(TP + offset) = g             *(TP + offset) = &amp;g_ptr\n  \u4e00\u7ea7\u95f4\u63a5                        *(*(TP + offset)) = g\n                                 \u4e24\u7ea7\u95f4\u63a5\n<\/code><\/pre>\n<p>\u6807\u51c6 Go \u53ea\u505a\u4e00\u7ea7\u95f4\u63a5\uff0c\u5728 musl \u73af\u5883\u4e0b\u8bfb\u51fa\u7684\u662f <code>g_slot<\/code> \u7684\u5730\u5740\u800c\u4e0d\u662f <code>g<\/code> \u503c\u3002\u5982\u679c <code>g_slot<\/code> \u5c1a\u672a\u521d\u59cb\u5316\uff08\u4e3a NULL \u6216\u5783\u573e\u503c\uff09\uff0cload_g \u8bfb\u5230\u7684\u5c31\u662f\u65e0\u6548\u6307\u9488\uff0c\u540e\u7eed\u4efb\u4f55\u4f7f\u7528 <code>g<\/code> \u7684\u64cd\u4f5c\u90fd\u4f1a\u5d29\u6e83\u3002<\/p>\n<hr \/>\n<h2>\u4e09\u3001\u4fee\u6539 1\uff1a\u4e24\u7ea7 TLS \u95f4\u63a5\u5bfb\u5740<\/h2>\n<h3>3.1 tls_arm64.h \u2014 \u5b9a\u4e49 MUSL_TLS \u5b8f<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/tls_arm64.h<\/code><\/p>\n<pre><code class=\"language-c line-numbers\">\/\/ \u6807\u51c6\u7248\n#ifdef GOOS_linux\n#define TLS_linux\n#endif\n\n\/\/ \u5b9a\u5236\u7248\n#ifdef GOOS_linux\n#define TLS_linux\n#define TLSG_IS_VARIABLE\n#define MUSL_TLS          \/\/ \u2190 \u65b0\u589e\uff1a\u542f\u7528 musl TLS \u4ee3\u7801\u8def\u5f84\n#endif\n<\/code><\/pre>\n<p><code>TLSG_IS_VARIABLE<\/code> \u544a\u8bc9 Go runtime <code>tls_g<\/code> \u662f\u4e00\u4e2a\u53d8\u91cf\u800c\u975e TLS \u6bb5\u4e2d\u7684\u504f\u79fb\u91cf\uff08\u56e0\u4e3a musl \u4e0b TLS \u4e0d\u5728 TLS \u6bb5\u4e2d\uff09\u3002<code>MUSL_TLS<\/code> \u5728\u6c47\u7f16\u4e2d\u4f5c\u4e3a\u6761\u4ef6\u7f16\u8bd1\u6807\u5fd7\uff0c\u9009\u62e9\u4e24\u7ea7\u95f4\u63a5\u5bfb\u5740\u7684\u4ee3\u7801\u8def\u5f84\u3002<\/p>\n<h3>3.2 tls_arm64.s \u2014 \u91cd\u5199 load_g \/ save_g<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/tls_arm64.s<\/code><\/p>\n<p>\u8fd9\u662f\u6700\u6838\u5fc3\u7684\u4fee\u6539\u3002\u5c06 <code>load_g<\/code> \u548c <code>save_g<\/code> \u4ece\u4e00\u7ea7\u95f4\u63a5\u6539\u4e3a\u4e24\u7ea7\u95f4\u63a5\uff1a<\/p>\n<pre><code class=\"language-asm line-numbers\">\/\/ ===== \u6807\u51c6\u7248 load_g =====\nTEXT runtime\u00b7load_g(SB),NOSPLIT,$0\n    MRS_TPIDR_R0                \/\/ R0 = TP (Thread Pointer)\n    MOVD  runtime\u00b7tls_g(SB), R27\n    MOVD  (R0)(R27), g          \/\/ g = *(TP + tls_g)  \u2190 \u4e00\u7ea7\u95f4\u63a5\n\n\/\/ ===== \u5b9a\u5236\u7248 load_g =====\nTEXT runtime\u00b7load_g(SB),NOSPLIT,$0\n    WORD  $0xd53bd040           \/\/ MRS TPIDR_EL0, R0  (\u786c\u7f16\u7801\u6307\u4ee4)\n    MOVD  runtime\u00b7tls_g(SB), R27\n    ADD   R27, R0, R27          \/\/ R27 = TP + tls_g (slot \u5730\u5740)\n    MOVD  (R27), R27            \/\/ R27 = *(TP + tls_g) = slot \u6307\u9488 (\u4e00\u7ea7)\n    MOVD  (R27), g              \/\/ g = *slot = *(slot + 0)  (\u4e8c\u7ea7, tls_g2=0)\n<\/code><\/pre>\n<pre><code class=\"language-asm line-numbers\">\/\/ ===== \u6807\u51c6\u7248 save_g =====\nTEXT runtime\u00b7save_g(SB),NOSPLIT,$0\n    MRS_TPIDR_R0\n    MOVD  runtime\u00b7tls_g(SB), R27\n    MOVD  g, (R0)(R27)          \/\/ *(TP + tls_g) = g  \u2190 \u4e00\u7ea7\u95f4\u63a5\n\n\/\/ ===== \u5b9a\u5236\u7248 save_g =====\nTEXT runtime\u00b7save_g(SB),NOSPLIT,$0\n    WORD  $0xd53bd040           \/\/ MRS TPIDR_EL0, R0\n    MOVD  runtime\u00b7tls_g(SB), R27\n    ADD   R27, R0, R27          \/\/ R27 = TP + tls_g\n    MOVD  (R27), R27            \/\/ R27 = *(TP + tls_g) = slot \u6307\u9488\n    MOVD  g, (R27)              \/\/ *slot = g  \u2190 \u4e24\u7ea7\u95f4\u63a5\u5199\u5165\n<\/code><\/pre>\n<h3>3.3 \u4e3a\u4ec0\u4e48\u8981\u786c\u7f16\u7801 MRS \u6307\u4ee4<\/h3>\n<p>\u6ce8\u610f\u5230\u5b9a\u5236\u7248\u4f7f\u7528 <code>WORD $0xd53bd040<\/code> \u800c\u975e <code>MRS_TPIDR_R0<\/code> \u5b8f\u3002\u539f\u56e0\uff1a<\/p>\n<ul>\n<li><code>MRS_TPIDR_R0<\/code> \u5b9a\u4e49\u5728 <code>tls_arm64.h<\/code>\uff0c\u5176\u5b9e\u73b0\u56e0\u5e73\u53f0\u800c\u5f02<\/li>\n<li>\u5728\u4fee\u6539\u4e86 <code>tls_arm64.h<\/code> \u540e\uff0c\u8be5\u5b8f\u7684\u884c\u4e3a\u53ef\u80fd\u4e0d\u7b26\u5408\u9884\u671f<\/li>\n<li>\u786c\u7f16\u7801 <code>0xd53bd040<\/code> \u5bf9\u5e94 <code>MRS TPIDR_EL0, R0<\/code>\uff0c\u8fd9\u662f ARMv8 \u7684\u6807\u51c6\u6307\u4ee4\uff0c\u660e\u786e\u65e0\u6b67\u4e49<\/li>\n<\/ul>\n<p>\u540c\u6837\uff0c<code>asm_arm64.s<\/code> \u4e2d rt0_go \u7684 TLS \u521d\u59cb\u5316\u4f7f\u7528 <code>WORD $0xd53bd060<\/code>\uff08<code>MRS TPIDRRO_EL0, R0<\/code>\uff0c\u8bfb\u53d6\u53ea\u8bfb\u7684 TPIDRRO_EL0\uff09\uff0c\u800c\u4e0d\u662f\u5b8f\u3002<\/p>\n<h3>3.4 tls_g \u548c tls_g2 \u7684\u5b58\u50a8\u65b9\u5f0f<\/h3>\n<pre><code class=\"language-asm line-numbers\">\/\/ \u6807\u51c6\u7248: tls_g \u5728 TLS \u6bb5\u4e2d\uff08glibc \u4e13\u7528\uff09\nGLOBL runtime\u00b7tls_g+0(SB), TLSBSS, $8\n\n\/\/ \u5b9a\u5236\u7248: tls_g \u662f\u666e\u901a\u6570\u636e\u53d8\u91cf\uff08NOPTR\uff09\uff0ctls_g2 \u540c\u7406\nDATA  runtime\u00b7tls_g+0(SB)\/8, $0\nGLOBL runtime\u00b7tls_g+0(SB), NOPTR, $8\nDATA  runtime\u00b7tls_g2+0(SB)\/8, $0\nGLOBL runtime\u00b7tls_g2+0(SB), NOPTR, $8\n<\/code><\/pre>\n<p>\u5173\u952e\u5dee\u5f02\uff1a<br \/>\n&#8211; <code>TLSBSS<\/code>\uff1a\u53d8\u91cf\u4f4d\u4e8e TLS \u6bb5\uff0c\u6bcf\u4e2a\u7ebf\u7a0b\u6709\u72ec\u7acb\u526f\u672c\u2014\u2014\u8fd9\u662f glibc \u7684\u65b9\u5f0f<br \/>\n&#8211; <code>NOPTR<\/code> + <code>DATA<\/code>\uff1a\u53d8\u91cf\u662f\u666e\u901a\u5168\u5c40\u6570\u636e\uff0c\u6240\u6709\u7ebf\u7a0b\u5171\u4eab\u540c\u4e00\u4e2a\u503c\u2014\u2014musl \u9700\u8981 <code>inittls<\/code> \u5728\u8fd0\u884c\u65f6\u8bbe\u7f6e\u504f\u79fb\u91cf<\/p>\n<p><code>tls_g<\/code> \u5b58\u50a8\u7684\u662f TSD \u504f\u79fb\u91cf\uff08\u5982 <code>0x70<\/code>\uff09\uff0c<code>tls_g2<\/code> \u5b58\u50a8\u4e8c\u7ea7\u504f\u79fb\uff08\u901a\u5e38\u4e3a 0\uff0c\u5373 slot \u7684\u8d77\u59cb\u4f4d\u7f6e\u5c31\u662f g\uff09\u3002<\/p>\n<h3>3.5 \u65b0\u589e getTLSg \u51fd\u6570<\/h3>\n<pre><code class=\"language-asm line-numbers\">\/\/ \u8fd4\u56de tls_g \u7684\u503c\uff0c\u4f9b Go \u5c42\u9762\u7684 cocoAllocateTLS \u4f7f\u7528\nTEXT runtime\u00b7getTLSg(SB),NOSPLIT,$0-8\n    MOVD  runtime\u00b7tls_g(SB), R0\n    MOVD  R0, ret+0(FP)\n    RET\n<\/code><\/pre>\n<h3>3.6 race_arm64.s \u2014 load_g \u5b8f\u7684\u6761\u4ef6\u7f16\u8bd1<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/race_arm64.s<\/code><\/p>\n<p>race \u68c0\u6d4b\u5668\u4e5f\u4f7f\u7528 <code>load_g<\/code> \u5b8f\uff0c\u9700\u8981\u540c\u6837\u7684\u4e24\u7ea7\u95f4\u63a5\u4fee\u6539\uff1a<\/p>\n<pre><code class=\"language-asm line-numbers\">\/\/ \u6807\u51c6\u7248\n#define load_g \\\n    MRS_TPIDR_R0 \\\n    TP_ALIGN \\\n    MOVD    runtime\u00b7tls_g(SB), R11 \\\n    MOVD    (R0)(R11), g           \/\/ \u4e00\u7ea7\u95f4\u63a5\n\n\/\/ \u5b9a\u5236\u7248\n#ifdef MUSL_TLS\n#define load_g \\\n    MRS_TPIDR_R0 \\\n    TP_ALIGN \\\n    MOVD    runtime\u00b7tls_g(SB), R11 \\\n    ADD     R11, R0, R11 \\\n    MOVD    (R11), R11 \\\n    MOVD    runtime\u00b7tls_g2(SB), R26 \\\n    MOVD    (R11)(R26), g          \/\/ \u4e24\u7ea7\u95f4\u63a5\n#else\n#define load_g \\\n    MRS_TPIDR_R0 \\\n    TP_ALIGN \\\n    MOVD    runtime\u00b7tls_g(SB), R11 \\\n    MOVD    (R0)(R11), g\n#endif\n<\/code><\/pre>\n<hr \/>\n<h2>\u56db\u3001\u4fee\u6539 2\uff1aCLONE_SETTLS \u4e0e\u65b0\u7ebf\u7a0b TLS \u5206\u914d<\/h2>\n<h3>4.1 \u95ee\u9898\u63cf\u8ff0<\/h3>\n<p>\u6807\u51c6 Go \u521b\u5efa\u65b0 OS \u7ebf\u7a0b\u65f6\uff0c<code>clone<\/code> \u7cfb\u7edf\u8c03\u7528\u4e0d\u4f20 TLS \u53c2\u6570\uff1a<\/p>\n<pre><code class=\"language-asm line-numbers\">\/\/ \u6807\u51c6\u7248 sys_linux_arm64.s\nTEXT runtime\u00b7clone(SB),NOSPLIT|NOFRAME,$0\n    MOVW  flags+0(FP), R0\n    MOVD  stk+8(FP), R1\n    ...\n    MOVD  $SYS_clone, R8\n    SVC                         \/\/ clone(flags, stk, mp, gp, fn)\n<\/code><\/pre>\n<p>\u5b50\u7ebf\u7a0b\u542f\u52a8\u540e\uff0cTPIDR_EL0 \u7ee7\u627f\u7236\u7ebf\u7a0b\u7684\u503c\uff08\u6216\u4e3a 0\uff09\uff0c\u6ca1\u6709\u72ec\u7acb\u7684 TLS \u5757\u3002\u5728 glibc \u73af\u5883\u4e0b\uff0ccgo \u7684 pthread \u673a\u5236\u4f1a\u968f\u540e\u8bbe\u7f6e TLS\uff1b\u4f46\u5728 musl\/OHOS \u73af\u5883\u4e0b\uff0c\u65b0\u7ebf\u7a0b\u7684 TLS \u5fc5\u987b\u5728 clone \u65f6\u5c31\u901a\u8fc7 <code>CLONE_SETTLS<\/code> \u8bbe\u7f6e\u3002<\/p>\n<h3>4.2 sys_linux_arm64.s \u2014 clone \u589e\u52a0 TLS \u53c2\u6570<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/sys_linux_arm64.s<\/code><\/p>\n<pre><code class=\"language-asm line-numbers\">\/\/ \u6807\u51c6\u7248: 5 \u4e2a\u53c2\u6570\n\/\/ int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));\n\n\/\/ \u5b9a\u5236\u7248: 6 \u4e2a\u53c2\u6570\n\/\/ int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void), void *tls);\n\nTEXT runtime\u00b7clone(SB),NOSPLIT|NOFRAME,$0\n    MOVW  flags+0(FP), R0\n    MOVD  stk+8(FP), R1\n    ...\n+   MOVD  tls+40(FP), R3        \/\/ \u2190 \u65b0\u589e\uff1aTLS \u5757\u5730\u5740 \u2192 x3 \u5bc4\u5b58\u5668\n    MOVD  $SYS_clone, R8\n    SVC\n\n    \/\/ \u7236\u8fdb\u7a0b\u8fd4\u56de\n    CMP   ZR, R0\n    BEQ   child\n-   MOVW  R0, ret+40(FP)\n+   MOVW  R0, ret+48(FP)        \/\/ \u2190 \u8fd4\u56de\u503c\u504f\u79fb\u8c03\u6574\uff08\u591a\u4e86 tls \u53c2\u6570\uff09\n    RET\n\nchild:\n    ...\n    MOVD  R10, g_m(R11)\n    MOVD  R11, g\n+   CALL  runtime\u00b7save_g(SB)   \/\/ \u2190 \u65b0\u589e\uff1a\u5b50\u7ebf\u7a0b\u7acb\u5373\u4fdd\u5b58 g \u5230 TLS\n<\/code><\/pre>\n<p><code>CLONE_SETTLS<\/code> \u6807\u5fd7\u544a\u8bc9\u5185\u6838\u5c06 x3 \u5bc4\u5b58\u5668\u7684\u503c\u8bbe\u7f6e\u4e3a\u65b0\u7ebf\u7a0b\u7684 TPIDR_EL0\u3002\u8fd9\u6837\u5b50\u7ebf\u7a0b\u4ece\u7b2c\u4e00\u6761\u6307\u4ee4\u8d77\u5c31\u6709\u6b63\u786e\u7684\u7ebf\u7a0b\u6307\u9488\u3002<\/p>\n<h3>4.3 os_linux.go \u2014 cloneFlags \u589e\u52a0 CLONE_SETTLS<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/os_linux.go<\/code><\/p>\n<pre><code class=\"language-go line-numbers\">\/\/ \u6807\u51c6\u7248\ncloneFlags = _CLONE_VM | _CLONE_FS | _CLONE_FILES |\n    _CLONE_SIGHAND | _CLONE_SYSVSEM | _CLONE_THREAD\n\n\/\/ \u5b9a\u5236\u7248\ncloneFlags = _CLONE_VM | _CLONE_FS | _CLONE_FILES |\n    _CLONE_SIGHAND | _CLONE_SYSVSEM | _CLONE_THREAD |\n    _CLONE_SETTLS    \/\/ \u2190 \u65b0\u589e\uff1aHarmonyOS\/musl \u9700\u8981\u5728 clone \u65f6\u8bbe\u7f6e TLS\n<\/code><\/pre>\n<h3>4.4 cocoAllocateTLS \u2014 \u4e3a\u65b0\u7ebf\u7a0b\u5206\u914d TLS \u5757<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/os_linux.go<\/code><\/p>\n<p>\u65b0\u589e\u51fd\u6570\uff0c\u5728\u6bcf\u4e2a\u65b0 OS \u7ebf\u7a0b\u521b\u5efa\u524d\u5206\u914d TLS \u5757\u5e76\u8bbe\u7f6e\u4e24\u7ea7\u6307\u9488\u94fe\uff1a<\/p>\n<pre><code class=\"language-go line-numbers\">const cocoTLSBlockSize = 16384  \/\/ 16KB TLS \u5757\n\n\/\/go:nosplit\n\/\/go:nowritebarrier\nfunc cocoAllocateTLS() unsafe.Pointer {\n    tlsG := getTLSg()       \/\/ \u83b7\u53d6 tls_g \u504f\u79fb\u91cf\n    if tlsG == 0 {\n        return nil\n    }\n\n    block := sysAlloc(cocoTLSBlockSize, &amp;memstats.other_sys)  \/\/ \u5206\u914d 16KB\n    if block == nil {\n        throw(\"cocoAllocateTLS: sysAlloc failed\")\n    }\n\n    \/\/ TP \u6307\u5411\u5757\u7684\u4e2d\u95f4\u4f4d\u7f6e\uff08\u524d\u540e\u90fd\u6709\u7a7a\u95f4\uff0c\u907f\u514d\u6ea2\u51fa\uff09\n    tpOffset := uintptr(cocoTLSBlockSize \/ 2)\n    tp := uintptr(block) + tpOffset\n\n    \/\/ \u8bbe\u7f6e\u4e24\u7ea7\u6307\u9488\u94fe\n    slotAddr := tp + tlsG            \/\/ *(TP + tls_g) \u6307\u5411\u7684\u4f4d\u7f6e\n    gSlotAddr := slotAddr + 8        \/\/ g-slot \u7684\u5730\u5740\uff08tls_g2=0 \u65f6\u5c31\u662f slot \u672c\u8eab\uff09\n    *(*uintptr)(unsafe.Pointer(slotAddr)) = gSlotAddr  \/\/ slot \u2192 g-slot\n    *(*uintptr)(unsafe.Pointer(gSlotAddr)) = 0          \/\/ g-slot \u2192 nil\n\n    return unsafe.Pointer(tp)        \/\/ \u4f20\u7ed9 clone \u7684 TLS \u53c2\u6570\n}\n<\/code><\/pre>\n<p>TLS \u5757\u7684\u5185\u5b58\u5e03\u5c40\uff1a<\/p>\n<pre><code class=\"line-numbers\">  \u5206\u914d\u7684 16KB \u5757\n  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n  \u2502                    \u2190 \u524d\u90e8\u7a7a\u95f4 (8KB) \u2192                  \u2502\n  \u2502                                                       \u2502\n  \u2502  ...                                                  \u2502\n  \u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2190 TP \u6307\u5411\u8fd9\u91cc\uff08\u5757\u7684\u4e2d\u95f4\uff09               \u2502\n  \u2502  \u2502 slot_ptr \u2502  \u2190 TP + tls_g\uff1a\u5b58\u50a8 g-slot \u7684\u5730\u5740       \u2502\n  \u2502  \u2502 g_slot   \u2502  \u2190 TP + tls_g + 8\uff1a\u5b58\u50a8 g \u6307\u9488          \u2502\n  \u2502  \u2502 ...      \u2502                                         \u2502\n  \u2502  \u2502                    \u2190 \u540e\u90e8\u7a7a\u95f4 (8KB) \u2192                \u2502\n  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n  load_g \u7684\u6548\u679c\uff1a\n    R0 = TP\n    R27 = tls_g\n    R27 = TP + tls_g \u2192 \u6307\u5411 slot_ptr\n    R27 = *slot_ptr \u2192 \u6307\u5411 g_slot\n    g = *g_slot \u2192 g \u503c\n<\/code><\/pre>\n<h3>4.5 newosproc \u2014 \u4f20\u9012 TLS \u7ed9 clone<\/h3>\n<pre><code class=\"language-go line-numbers\">func newosproc(mp *m) {\n    ...\n    tls := cocoAllocateTLS()                    \/\/ \u2190 \u65b0\u589e\n    print(\"newosproc: cocoAllocateTLS returned tls=\", tls, \"\\n\")\n\n    var oset sigset\n    sigprocmask(_SIG_SETMASK, &amp;sigset_all, &amp;oset)\n    ret := retryOnEAGAIN(func() int32 {\n        r := clone(cloneFlags, stk, unsafe.Pointer(mp),\n            unsafe.Pointer(mp.g0),\n            unsafe.Pointer(abi.FuncPCABI0(mstart)),\n            tls)                                 \/\/ \u2190 \u65b0\u589e tls \u53c2\u6570\n        ...\n    })\n    ...\n}\n<\/code><\/pre>\n<h3>4.6 newosproc0 \u540c\u6837\u9002\u914d<\/h3>\n<pre><code class=\"language-go line-numbers\">func newosproc0(stacksize uintptr, fn unsafe.Pointer) {\n    ...\n    tls := cocoAllocateTLS()\n    var flags int32 = cloneFlags\n    if tls == nil {\n        flags &amp;^= _CLONE_SETTLS              \/\/ tls \u4e3a nil \u65f6\u4e0d\u8bbe\u7f6e\n    }\n    ret := clone(flags, ..., fn, tls)         \/\/ \u4f20\u9012 tls\n    ...\n}\n<\/code><\/pre>\n<hr \/>\n<h2>\u4e94\u3001\u4fee\u6539 3\uff1acgo inittls \u91cd\u5199<\/h2>\n<h3>5.1 \u539f\u59cb inittls \u7684\u95ee\u9898<\/h3>\n<p>\u6807\u51c6 Go \u7684 <code>gcc_linux_arm64.c<\/code> \u4e2d\uff0c<code>x_cgo_inittls<\/code> \u51fd\u6570\u5b9e\u73b0\u975e\u5e38\u7b80\u5355\uff1a<\/p>\n<pre><code class=\"language-c line-numbers\">\/\/ \u6807\u51c6\u7248 \u2014 \u53ea\u5728 glibc \u4e0b\u6709\u6548\nvoid (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common));\n\/\/ \u5b9e\u9645\u5b9e\u73b0\u7531 glibc \u7684 __tls_get_addr \u673a\u5236\u63d0\u4f9b\n\/\/ musl \u4e0b\u8fd9\u4e2a\u6307\u9488\u4e3a NULL\uff0c\u4e0d\u4f1a\u8c03\u7528\n<\/code><\/pre>\n<p>\u6807\u51c6\u5b9e\u73b0\u4f9d\u8d56 glibc \u7684 <code>__tls_get_addr<\/code> \u548c ELF TLS \u6bb5\uff0c\u8fd9\u4e9b\u5728 musl \u4e0b\u90fd\u4e0d\u5b58\u5728\u3002\u9700\u8981\u5b8c\u5168\u91cd\u5199 <code>inittls<\/code> \u51fd\u6570\u3002<\/p>\n<h3>5.2 \u63a2\u6d4b\u5f0f TSD \u504f\u79fb\u91cf\u53d1\u73b0<\/h3>\n<p>musl \u7684 <code>pthread_setspecific<\/code> \u5c06\u503c\u5b58\u50a8\u5728 TP \u9644\u8fd1\u7684 TSD \u6570\u7ec4\u4e2d\uff0c\u4f46\u5177\u4f53\u7684\u504f\u79fb\u91cf\u6ca1\u6709\u516c\u5f00\u6587\u6863\u3002\u6211\u4eec\u7684\u65b9\u6848\u662f\u901a\u8fc7&#8221;\u63a2\u9488\u6cd5&#8221;\u53d1\u73b0\uff1a<\/p>\n<pre><code class=\"line-numbers\">inittls \u63a2\u6d4b\u6d41\u7a0b:\n\n[1] \u521b\u5efa pthread_key: k = pthread_key_create(&amp;k, nil)\n\n[2] \u8bbe\u7f6e\u63a2\u9488\u503c: pthread_setspecific(k, magic1 = 0x23581321345589)\n\n[3] \u8bfb\u53d6 TP: __asm__(\"mrs %0, tpidr_el0\" : \"=r\"(tp))\n\n[4] \u641c\u7d22 TSD \u6570\u7ec4:\n    for (i = -4096; i &lt; 4096; i += 8) {\n        if (*(void**)(tp + i + k*8) == magic1) {\n            \/\/ \u53ef\u80fd\u627e\u5230\u4e86\uff01\n            \/\/ \u7528\u7b2c\u4e8c\u4e2a magic \u503c\u786e\u8ba4\n            pthread_setspecific(k, magic2);\n            if (*(void**)(tp + i + k*8) == magic2) {\n                tsd_offset = i;  \/\/ \u786e\u8ba4\uff1aTSD \u6570\u7ec4\u8d77\u59cb\u504f\u79fb\n                break;\n            }\n        }\n    }\n\n[5] \u8ba1\u7b97 tls_g \u504f\u79fb\u91cf:\n    *tlsg = tsd_offset + k * sizeof(void*)\n    \/\/ \u5373\uff1a*(TP + *tlsg) = pthread_getspecific(k) \u7684\u5b58\u50a8\u4f4d\u7f6e\n<\/code><\/pre>\n<p>\u4e3a\u4ec0\u4e48\u641c\u7d22\u8303\u56f4\u662f \u00b14KB\uff1f\u56e0\u4e3a musl \u7684 TSD \u6570\u7ec4\u53ef\u80fd\u5728 TP \u4e4b\u524d\u6216\u4e4b\u540e\uff0c\u504f\u79fb\u91cf\u4e0d\u786e\u5b9a\u3002\u7528\u4e24\u4e2a\u4e0d\u540c\u7684 magic \u503c\u4ea4\u53c9\u9a8c\u8bc1\uff0c\u907f\u514d\u8bef\u5339\u914d\u3002<\/p>\n<h3>5.3 SIGSEGV \u5b89\u5168\u63a2\u6d4b<\/h3>\n<p>\u7531\u4e8e TP \u9644\u8fd1\u5e76\u975e\u6240\u6709\u5185\u5b58\u90fd\u53ef\u8bfb\uff0c\u641c\u7d22\u65f6\u53ef\u80fd\u89e6\u53d1 SIGSEGV\u3002\u5b9a\u5236\u7248\u4f7f\u7528 <code>sigsetjmp\/siglongjmp<\/code> \u505a\u5b89\u5168\u63a2\u6d4b\uff1a<\/p>\n<pre><code class=\"language-c line-numbers\">static sigjmp_buf inittls_jmpbuf;\nstatic void inittls_sigsegv_handler(int sig) {\n    siglongjmp(inittls_jmpbuf, 1);\n}\n\n\/\/ \u5728\u641c\u7d22\u524d\u5b89\u88c5\u4fe1\u53f7\u5904\u7406\u5668\nstruct sigaction sa, oldsa;\nsa.sa_handler = inittls_sigsegv_handler;\nsigaction(SIGSEGV, &amp;sa, &amp;oldsa);\nsigaction(SIGBUS, &amp;sa, &amp;oldsa);\n\n\/\/ \u641c\u7d22\u65f6\u7528 sigsetjmp \u4fdd\u62a4\nfor (i = -4096; i &lt; 4096; i += sizeof(void*)) {\n    if (sigsetjmp(inittls_jmpbuf, 1) == 0) {\n        \/\/ \u5c1d\u8bd5\u8bfb\u53d6 *(TP + i + k*8)\n        if (p[k] == magic1) { ... }\n    }\n    \/\/ \u5982\u679c\u89e6\u53d1 SIGSEGV\uff0c\u4f1a\u8df3\u56de sigsetjmp\uff0c\u7ee7\u7eed\u641c\u7d22\n}\n\n\/\/ \u6062\u590d\u539f\u59cb\u4fe1\u53f7\u5904\u7406\u5668\nsigaction(SIGSEGV, &amp;oldsa, nil);\n<\/code><\/pre>\n<h3>5.4 \u8bbe\u7f6e g-slot<\/h3>\n<p>\u627e\u5230 TSD \u504f\u79fb\u540e\uff0c\u4e3a <code>tls_g<\/code> \u5206\u914d g-slot \u5e76\u8bbe\u7f6e\u4e24\u7ea7\u6307\u9488\u94fe\uff1a<\/p>\n<pre><code class=\"language-c line-numbers\">\/\/ \u4e3a\u4e3b\u7ebf\u7a0b\u5206\u914d g-slot\nstatic void *g_storage_main;\ng_storage_main = NULL;\npthread_setspecific(k, &amp;g_storage_main);\n\/\/ \u6b64\u65f6 *(TP + tls_g) = &amp;g_storage_main\n\/\/ load_g: *(*(TP + tls_g)) = *(&amp;g_storage_main) = g_storage_main = g\n\n\/\/ \u9a8c\u8bc1\nvoid *check = pthread_getspecific(k);\nvoid *slot = *(void**)((char*)tp + (intptr_t)(*tlsg));\nassert(check == slot);\n<\/code><\/pre>\n<h3>5.5 x_cgo_init \u7b7e\u540d\u53d8\u66f4<\/h3>\n<p>\u7531\u4e8e\u589e\u52a0\u4e86 <code>tls_g2<\/code> \u53c2\u6570\uff0c<code>x_cgo_init<\/code> \u7684\u7b7e\u540d\u4e5f\u53d8\u4e86\uff1a<\/p>\n<pre><code class=\"language-c line-numbers\">\/\/ \u6807\u51c6\u7248\nvoid x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)\n\n\/\/ \u5b9a\u5236\u7248\nvoid x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase, void **tlsg2)\n<\/code><\/pre>\n<p>\u5bf9\u5e94 <code>asm_arm64.s<\/code> \u4e2d\u7684\u8c03\u7528\u4e5f\u9700\u8981\u4f20\u5165 <code>tls_g2<\/code> \u7684\u5730\u5740\uff1a<\/p>\n<pre><code class=\"language-asm line-numbers\">\/\/ \u6807\u51c6\u7248 \u2014 \u4ec5 Android \u4f20 TLS base\n#ifdef GOOS_android\n    MRS_TPIDR_R0\n    MOVD  R0, R3           \/\/ arg 3: TLS base\n    MOVD  $tls_g(SB), R2   \/\/ arg 2: &amp;tls_g\n#else\n    MOVD  $0, R2           \/\/ arg 2: \u4e0d\u4f7f\u7528\n#endif\n\n\/\/ \u5b9a\u5236\u7248 \u2014 \u6240\u6709 Linux \u73af\u5883\u90fd\u4f20\n    WORD  $0xd53bd040      \/\/ MRS TPIDR_EL0, R0\n    MOVD  R0, R3           \/\/ arg 3: TLS base\n    MOVD  $tls_g(SB), R2   \/\/ arg 2: &amp;tls_g\n    MOVD  $tls_g2(SB), R4  \/\/ arg 4: &amp;tls_g2  \u2190 \u65b0\u589e\n<\/code><\/pre>\n<h3>5.6 threadentry \u2014 \u65b0\u7ebf\u7a0b\u7684 TLS \u8bbe\u7f6e<\/h3>\n<p>cgo \u521b\u5efa\u65b0\u7ebf\u7a0b\u65f6\uff0c<code>threadentry<\/code> \u51fd\u6570\u4e5f\u9700\u8981\u8bbe\u7f6e\u4e24\u7ea7 TLS\uff1a<\/p>\n<pre><code class=\"language-c line-numbers\">static void* threadentry(void *v) {\n    \/\/ 1. \u63a2\u6d4b\u5f53\u524d\u7ebf\u7a0b\u7684 TSD \u504f\u79fb\n    \/\/    \uff08\u53ef\u80fd\u4e0e\u4e3b\u7ebf\u7a0b\u4e0d\u540c\uff0c\u56e0\u4e3a pthread_key \u7f16\u53f7\u53ef\u80fd\u4e0d\u540c\uff09\n\n    \/\/ 2. \u5206\u914d g-slot\n    gslot = malloc(sizeof(void*));\n    *gslot = NULL;\n    pthread_setspecific(g_cgo_tls_key, gslot);\n\n    \/\/ 3. \u5982\u679c\u65b0\u7ebf\u7a0b\u7684 tls_g \u504f\u79fb\u4e0e\u4e3b\u7ebf\u7a0b\u4e0d\u540c\uff0c\u9700\u8981\u4fee\u6b63\n    \/\/    \u5c06\u4e3b\u7ebf\u7a0b\u7684 tls_g \u504f\u79fb\u5904\u4e5f\u6307\u5411\u65b0\u7ebf\u7a0b\u7684 g-slot\n    if (new_tls_g != main_tls_g) {\n        void **slot_at_main_offset = (void**)((char*)tp + main_tls_g);\n        *slot_at_main_offset = gslot;\n    }\n\n    \/\/ 4. \u8fdb\u5165 Go \u4ee3\u7801\n    crosscall1(ts.fn, setg_gcc, (void*)ts.g);\n}\n<\/code><\/pre>\n<hr \/>\n<h2>\u516d\u3001\u4fee\u6539 4\uff1afprintf \u2192 hilog<\/h2>\n<h3>6.1 VPN \u6c99\u76d2\u4e2d\u7684 stderr \u5d29\u6e83<\/h3>\n<p>HarmonyOS VPN Extension \u8fd0\u884c\u5728\u53d7\u9650\u6c99\u76d2\u4e2d\uff0c<code>stderr<\/code>\uff08fd=2\uff09\u4e0d\u662f\u4e00\u4e2a\u6b63\u5e38\u7684\u6587\u4ef6\u63cf\u8ff0\u7b26\u3002\u5411\u5176\u5199\u5165\u4f1a\u5bfc\u81f4 SIGSEGV\u3002Go runtime \u7684 cgo \u4ee3\u7801\u4e2d\u591a\u5904\u4f7f\u7528 <code>fprintf(stderr)<\/code>\uff1a<\/p>\n<pre><code class=\"language-c line-numbers\">\/\/ gcc_fatalf.c \u2014 \u6807\u51c6\u7248\nvoid fatalf(const char* format, ...) {\n    fprintf(stderr, \"runtime\/cgo: \");    \/\/ \u2190 SIGSEGV!\n    vfprintf(stderr, format, ap);\n    fprintf(stderr, \"\\n\");\n    abort();\n}\n\n\/\/ gcc_libinit.c \u2014 \u6807\u51c6\u7248\nvoid x_cgo_sys_thread_create(void* (*func)(void*), void* arg) {\n    int err = _cgo_try_pthread_create(&amp;p, NULL, func, arg);\n    if (err != 0) {\n        fprintf(stderr, \"pthread_create failed: %s\", strerror(err));  \/\/ \u2190 SIGSEGV!\n        abort();\n    }\n}\n<\/code><\/pre>\n<h3>6.2 \u89e3\u51b3\u65b9\u6848\uff1a\u52a8\u6001\u52a0\u8f7d OH_Log_Print<\/h3>\n<pre><code class=\"language-c line-numbers\">\/\/ gcc_fatalf.c \u2014 \u5b9a\u5236\u7248\n#include &lt;dlfcn.h&gt;\n\ntypedef void (*OH_LogPrintFunc)(int type, int level, unsigned int domain,\n    const char *tag, const char *fmt, ...);\n\nstatic OH_LogPrintFunc _get_oh_log_print(void) {\n    static OH_LogPrintFunc fn = NULL;\n    if (!fn) {\n        void *h = dlopen(\"libhilog_ndk.z.so\", RTLD_NOW);\n        if (h) {\n            fn = (OH_LogPrintFunc)dlsym(h, \"OH_Log_Print\");\n        }\n    }\n    return fn;\n}\n\nvoid fatalf(const char* format, ...) {\n    va_list ap;\n    OH_LogPrintFunc logfn = _get_oh_log_print();\n    if (logfn) {\n        va_start(ap, format);\n        logfn(OH_LOG_APP, OH_LOG_FATAL, 0, \"runtime\/cgo\", format, ap);\n        va_end(ap);\n    }\n    abort();\n}\n<\/code><\/pre>\n<p><code>gcc_libinit.c<\/code> \u540c\u7406\uff0c\u5c06 <code>fprintf(stderr) + abort()<\/code> \u6539\u4e3a\u8c03\u7528 <code>fatalf()<\/code>\uff0c\u95f4\u63a5\u4f7f\u7528 hilog\u3002<\/p>\n<h3>6.3 \u4e3a\u4ec0\u4e48\u7528 dlopen \u800c\u975e\u76f4\u63a5\u94fe\u63a5<\/h3>\n<ul>\n<li><code>libhilog_ndk.z.so<\/code> \u662f HarmonyOS \u7cfb\u7edf\u5e93\uff0c\u4e0d\u5728\u7f16\u8bd1\u65f6\u7684 sysroot \u4e2d<\/li>\n<li>VPN \u6c99\u76d2\u53ef\u80fd\u9650\u5236\u76f4\u63a5\u94fe\u63a5\u7cfb\u7edf\u5e93<\/li>\n<li>dlopen \u8fd0\u884c\u65f6\u52a0\u8f7d\u66f4\u7075\u6d3b\uff0c\u52a0\u8f7d\u5931\u8d25\u65f6\u53ea\u662f\u65e5\u5fd7\u4e22\u5931\uff0c\u4e0d\u4f1a\u5d29\u6e83<\/li>\n<\/ul>\n<hr \/>\n<h2>\u4e03\u3001\u4fee\u6539 5\uff1aargv \u7a7a\u6307\u9488\u9632\u62a4<\/h2>\n<h3>7.1 \u95ee\u9898\u63cf\u8ff0<\/h3>\n<p>c-shared \u6a21\u5f0f\u4e0b\uff0cGo runtime \u7684 <code>args()<\/code> \u51fd\u6570\u63a5\u6536\u5230\u7684 <code>argv<\/code> \u53c2\u6570\u53ef\u80fd\u4e3a <code>nil<\/code>\uff1a<\/p>\n<pre><code class=\"language-go line-numbers\">\/\/ \u6807\u51c6\u7248\nfunc args(c int32, v **byte) {\n    argc = c\n    argv = v         \/\/ \u2190 v \u4e3a nil \u65f6\uff0c\u540e\u7eed argv \u4f7f\u7528\u4f1a\u5d29\u6e83\n    sysargs(c, v)    \/\/ \u2190 \u540c\u6837\u53ef\u80fd\u5d29\u6e83\n}\n<\/code><\/pre>\n<p>\u8fd9\u5728 glibc \u73af\u5883\u4e0b\u4e0d\u4f1a\u53d1\u751f\uff0c\u56e0\u4e3a <code>dlopen<\/code> \u603b\u662f\u63d0\u4f9b\u6709\u6548\u7684 argv\u3002\u4f46\u5728 HarmonyOS \u7684 ArkCompiler NAPI \u52a0\u8f7d\u6d41\u7a0b\u4e2d\uff0c<code>_rt0_arm64_linux_lib<\/code> \u88ab\u8c03\u7528\u65f6 argv \u786e\u5b9e\u53ef\u80fd\u4e3a nil\u3002<\/p>\n<h3>7.2 \u89e3\u51b3\u65b9\u6848<\/h3>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/runtime1.go<\/code><\/p>\n<pre><code class=\"language-go line-numbers\">var csharedEmptyArgv [3]*byte  \/\/ \u5b89\u5168\u7684\u7a7a argv\n\nfunc args(c int32, v **byte) {\n    argc = c\n    if islibrary &amp;&amp; v == nil {\n        argv = &amp;csharedEmptyArgv[0]   \/\/ \u2190 \u4f7f\u7528\u5b89\u5168\u7684\u7a7a\u6570\u7ec4\n    } else {\n        argv = v\n    }\n    sysargs(c, argv)  \/\/ \u2190 \u4f20\u5165\u5b89\u5168\u7684 argv\n}\n<\/code><\/pre>\n<p><code>csharedEmptyArgv<\/code> \u662f\u4e00\u4e2a 3 \u5143\u7d20\u7684 <code>*byte<\/code> \u6570\u7ec4\uff0c\u6240\u6709\u5143\u7d20\u4e3a\u96f6\u503c\u3002\u8fd9\u6837\u5373\u4f7f <code>sysargs<\/code> \u5c1d\u8bd5\u8bbf\u95ee <code>argv[0]<\/code> \u7b49\uff0c\u4e5f\u4e0d\u4f1a\u89e3\u5f15\u7528\u7a7a\u6307\u9488\u3002<\/p>\n<hr \/>\n<h2>\u516b\u3001\u4fee\u6539 6\uff1aphysPageSize \u515c\u5e95<\/h2>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/os_linux.go<\/code><\/p>\n<pre><code class=\"language-go line-numbers\">func osinit() {\n    ncpu = getproccount()\n    physHugePageSize = getHugePageSize()\n    if physPageSize == 0 {        \/\/ \u2190 \u65b0\u589e\uff1aOHOS \u53ef\u80fd\u8fd4\u56de 0\n        physPageSize = 4096\n    }\n    ...\n}\n<\/code><\/pre>\n<p>OHOS \u7684 <code>\/proc\/self\/auxv<\/code> \u53ef\u80fd\u4e0d\u5305\u542b <code>AT_PAGESZ<\/code> \u6761\u76ee\uff0c\u5bfc\u81f4 <code>physPageSize<\/code> \u4e3a 0\u3002Go memory allocator \u5728 <code>physPageSize=0<\/code> \u65f6\u4f1a\u5d29\u6e83\u3002\u8bbe\u7f6e\u9ed8\u8ba4\u503c 4096\uff08\u6807\u51c6 ARM64 \u9875\u5927\u5c0f\uff09\u4f5c\u4e3a\u515c\u5e95\u3002<\/p>\n<hr \/>\n<h2>\u4e5d\u3001\u4fee\u6539 7\uff1a\u8c03\u8bd5\u65e5\u5fd7<\/h2>\n<p><strong>\u6587\u4ef6<\/strong>: <code>src\/runtime\/proc.go<\/code>\u3001<code>src\/runtime\/mgc.go<\/code><\/p>\n<p>\u5728 <code>runtime.main<\/code>\u3001<code>gcenable<\/code>\u3001<code>schedinit<\/code> \u7b49\u5173\u952e\u51fd\u6570\u4e2d\u6dfb\u52a0\u4e86 <code>print()<\/code> \u8c03\u8bd5\u65e5\u5fd7\uff1a<\/p>\n<pre><code class=\"language-go line-numbers\">func main() {\n    print(\"runtime.main: entered\\n\")\n    ...\n    print(\"runtime.main: mainStarted, about to newm(sysmon)\\n\")\n    ...\n    print(\"runtime.main: gcenable done\\n\")\n    ...\n}\n\nfunc gcenable() {\n    print(\"gcenable: entered\\n\")\n    ...\n}\n<\/code><\/pre>\n<p>\u8fd9\u4e9b\u65e5\u5fd7\u5728 OHOS VPN \u6c99\u76d2\u4e2d\u901a\u8fc7 <code>dup2<\/code> \u91cd\u5b9a\u5411\u5230\u8c03\u8bd5\u6587\u4ef6\uff0c\u5e2e\u52a9\u5b9a\u4f4d Go runtime \u521d\u59cb\u5316\u5d29\u6e83\u7684\u786e\u5207\u4f4d\u7f6e\u3002\u751f\u4ea7\u73af\u5883\u4e2d\u53ef\u4ee5\u79fb\u9664\u3002<\/p>\n<hr \/>\n<h2>\u5341\u3001\u5b8c\u6574\u4fee\u6539\u6587\u4ef6\u6e05\u5355<\/h2>\n<table>\n<thead>\n<tr>\n<th>#<\/th>\n<th>\u6587\u4ef6<\/th>\n<th>\u4fee\u6539\u7c7b\u578b<\/th>\n<th>\u6838\u5fc3\u6539\u52a8<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td><code>src\/runtime\/tls_arm64.h<\/code><\/td>\n<td>\u5b8f\u5b9a\u4e49<\/td>\n<td>\u65b0\u589e <code>TLSG_IS_VARIABLE<\/code>\u3001<code>MUSL_TLS<\/code><\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td><code>src\/runtime\/tls_arm64.s<\/code><\/td>\n<td>\u6c47\u7f16\u91cd\u5199<\/td>\n<td>load_g\/save_g \u4e24\u7ea7\u95f4\u63a5\u5bfb\u5740\uff1b\u65b0\u589e getTLSg\uff1btls_g \u6539 NOPTR DATA\uff1b\u65b0\u589e tls_g2<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td><code>src\/runtime\/asm_arm64.s<\/code><\/td>\n<td>\u6c47\u7f16\u4fee\u6539<\/td>\n<td>\u786c\u7f16\u7801 MRS \u6307\u4ee4\uff1bcgo_init \u4f20 tls_g2 \u53c2\u6570\uff1b\u79fb\u9664 GOOS_android \u6761\u4ef6<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td><code>src\/runtime\/race_arm64.s<\/code><\/td>\n<td>\u6c47\u7f16\u4fee\u6539<\/td>\n<td>load_g \u5b8f\u589e\u52a0 MUSL_TLS \u6761\u4ef6\u5206\u652f\uff1btls_g GLOBL \u4ec5 darwin\/windows \u7528 TLSBSS<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td><code>src\/runtime\/sys_linux_arm64.s<\/code><\/td>\n<td>\u6c47\u7f16\u4fee\u6539<\/td>\n<td>clone \u589e\u52a0 tls \u53c2\u6570(x3)\uff1b\u5b50\u7ebf\u7a0b\u8c03\u7528 save_g\uff1b\u8fd4\u56de\u503c\u504f\u79fb\u8c03\u6574<\/td>\n<\/tr>\n<tr>\n<td>6<\/td>\n<td><code>src\/runtime\/os_linux.go<\/code><\/td>\n<td>Go \u4fee\u6539<\/td>\n<td>CLONE_SETTLS\uff1bcocoAllocateTLS\uff1bclone \u7b7e\u540d\u589e\u52a0 tls\uff1bnewosproc0 \u9002\u914d\uff1bphysPageSize \u515c\u5e95<\/td>\n<\/tr>\n<tr>\n<td>7<\/td>\n<td><code>src\/runtime\/proc.go<\/code><\/td>\n<td>Go \u4fee\u6539<\/td>\n<td>\u8c03\u8bd5 print \u65e5\u5fd7<\/td>\n<\/tr>\n<tr>\n<td>8<\/td>\n<td><code>src\/runtime\/mgc.go<\/code><\/td>\n<td>Go \u4fee\u6539<\/td>\n<td>\u8c03\u8bd5 print \u65e5\u5fd7<\/td>\n<\/tr>\n<tr>\n<td>9<\/td>\n<td><code>src\/runtime\/runtime1.go<\/code><\/td>\n<td>Go \u4fee\u6539<\/td>\n<td>c-shared argv \u7a7a\u6307\u9488\u9632\u62a4<\/td>\n<\/tr>\n<tr>\n<td>10<\/td>\n<td><code>src\/runtime\/cgo\/gcc_fatalf.c<\/code><\/td>\n<td>C \u91cd\u5199<\/td>\n<td>fprintf(stderr) \u2192 dlopen OH_Log_Print<\/td>\n<\/tr>\n<tr>\n<td>11<\/td>\n<td><code>src\/runtime\/cgo\/gcc_libinit.c<\/code><\/td>\n<td>C \u4fee\u6539<\/td>\n<td>fprintf + abort \u2192 fatalf()<\/td>\n<\/tr>\n<tr>\n<td>12<\/td>\n<td><code>src\/runtime\/cgo\/gcc_linux_arm64.c<\/code><\/td>\n<td>C \u91cd\u5199<\/td>\n<td>inittls \u5b8c\u5168\u91cd\u5199\uff08TSD \u63a2\u6d4b\u3001g-slot \u5206\u914d\u3001\u4e24\u7ea7\u6307\u9488\u94fe\uff09\uff1bx_cgo_init \u589e\u52a0 tls_g2 \u53c2\u6570\uff1bthreadentry TLS \u4fee\u590d<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>\u5341\u4e00\u3001\u4f9d\u8d56\u5173\u7cfb\u56fe<\/h2>\n<p>12 \u4e2a\u4fee\u6539\u4e4b\u95f4\u5b58\u5728\u4e25\u683c\u7684\u4f9d\u8d56\u5173\u7cfb\uff0c\u4e0d\u80fd\u5355\u72ec\u4f7f\u7528\uff1a<\/p>\n<pre><code class=\"line-numbers\">                    tls_arm64.h (MUSL_TLS, TLSG_IS_VARIABLE)\n                         \u2502\n          \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n          \u2502              \u2502                  \u2502\n          \u25bc              \u25bc                  \u25bc\n    tls_arm64.s    race_arm64.s      asm_arm64.s\n  (load_g\/save_g   (load_g \u5b8f       (rt0_go MRS\n   \u4e24\u7ea7\u95f4\u63a5)        MUSL_TLS \u5206\u652f)    cgo_init tls_g2)\n          \u2502              \u2502                  \u2502\n          \u2502              \u2502                  \u25bc\n          \u2502              \u2502           gcc_linux_arm64.c\n          \u2502              \u2502          (inittls \u63a2\u6d4b+\u8bbe\u7f6e\n          \u2502              \u2502           x_cgo_init tls_g2\n          \u2502              \u2502           threadentry TLS)\n          \u2502              \u2502                  \u2502\n          \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                  \u2502\n                 \u2502                          \u2502\n                 \u25bc                          \u2502\n          sys_linux_arm64.s                  \u2502\n        (clone + CLONE_SETTLS               \u2502\n         \u5b50\u7ebf\u7a0b save_g)                      \u2502\n                 \u2502                          \u2502\n                 \u25bc                          \u2502\n          os_linux.go                        \u2502\n        (cocoAllocateTLS                    \u2502\n         newosproc clone+tls)               \u2502\n                 \u2502                          \u2502\n                 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                            \u2502\n                            \u25bc\n                   gcc_fatalf.c \u2500\u2500\u2192 gcc_libinit.c\n                  (hilog \u66ff\u4ee3 fprintf)  (\u8c03\u7528 fatalf)\n                            \u2502\n                   runtime1.go (argv \u9632\u62a4)\n                   proc.go \/ mgc.go (\u8c03\u8bd5\u65e5\u5fd7)\n                   os_linux.go (physPageSize)\n<\/code><\/pre>\n<p>\u6838\u5fc3\u94fe\u8def\uff1a<code>tls_arm64.h<\/code> \u5b9a\u4e49\u5b8f \u2192 <code>tls_arm64.s<\/code> \u5b9e\u73b0\u4e24\u7ea7\u5bfb\u5740 \u2192 <code>gcc_linux_arm64.c<\/code> \u7684 <code>inittls<\/code> \u8bbe\u7f6e\u504f\u79fb\u91cf\u548c g-slot \u2192 <code>sys_linux_arm64.s<\/code> + <code>os_linux.go<\/code> \u786e\u4fdd\u65b0\u7ebf\u7a0b\u4e5f\u6709\u6b63\u786e\u7684 TLS\u3002\u4efb\u4f55\u4e00\u73af\u7f3a\u5931\u90fd\u4f1a\u5bfc\u81f4\u5d29\u6e83\u3002<\/p>\n<hr \/>\n<h2>\u5341\u4e8c\u3001\u7f16\u8bd1\u4e0e\u9a8c\u8bc1<\/h2>\n<h3>12.1 \u7f16\u8bd1\u547d\u4ee4<\/h3>\n<pre><code class=\"language-powershell line-numbers\">$goRoot = \"C:\\Users\\mateng\\go-ohos\"   # \u5b9a\u5236 Go\uff0c\u4e0d\u662f\u6807\u51c6 Go\uff01\n$ndkShort = \"D:\\DevTools\\Huawei\\DEVECO~1\\sdk\\default\\OPENHA~1\\native\"\n\n$env:GOROOT = $goRoot\n$env:CGO_ENABLED = \"1\"\n$env:GOOS = \"linux\"\n$env:GOARCH = \"arm64\"\n$env:CC = \"$ndkShort\\llvm\\bin\\clang.exe\"\n$env:CGO_CFLAGS = \"--target=aarch64-linux-ohos --sysroot=$ndkShort\\sysroot -D__OHOS__=1 -D__MUSL__ -fPIC -Wno-error\"\n$env:CGO_LDFLAGS = \"-target aarch64-linux-ohos -Wno-error --sysroot=$ndkShort\\sysroot -lace_napi.z -lc -ldl\"\n$env:CGO_CFLAGS_ALLOW = \".*\"\n$env:CGO_LDFLAGS_ALLOW = \".*\"\n\ngo build -a -tags=\"with_gvisor,ohos\" -buildmode=c-shared `\n  -ldflags=\"-extldflags '--sysroot=$ndkShort\\sysroot --target=aarch64-linux-ohos -Wl,--dynamic-list=dynamic_list.txt napi_reg.o'\" `\n  -o libcocoproxy.so\n<\/code><\/pre>\n<h3>12.2 \u5fc5\u9700\u7684\u540e\u7eed\u6b65\u9aa4<\/h3>\n<ol>\n<li><strong>patch-so.ps1<\/strong>\uff1a\u5c06 <code>_rt0_arm64_linux_lib<\/code> \u9996\u6307\u4ee4\u6539\u4e3a RET\uff0c\u5c06 <code>g_rt0_go_offset<\/code> \u5360\u4f4d\u7b26\u66ff\u6362\u4e3a\u5b9e\u9645\u5730\u5740<\/li>\n<li><strong>\u590d\u5236 .so<\/strong>\uff1a\u5230 <code>entry\/libs\/arm64-v8a\/<\/code> \u548c <code>entry\/src\/main\/cpp\/libs\/arm64-v8a\/<\/code><\/li>\n<li><strong>DevEco Studio<\/strong>\uff1a\u6784\u5efa HAP \u5e76\u90e8\u7f72<\/li>\n<\/ol>\n<h3>12.3 \u9a8c\u8bc1\u65b9\u6cd5<\/h3>\n<pre><code class=\"language-bash line-numbers\"># \u6293\u53d6\u8bbe\u5907\u65e5\u5fd7\uff0c\u786e\u8ba4 NAPI \u6a21\u5757\u52a0\u8f7d\u6210\u529f\nhdc shell hilog | grep -i \"cocoproxy\\|napi\\|runtime\\.main\"\n\n# \u671f\u671b\u770b\u5230:\n#   runtime.main: entered\n#   runtime.main: gcenable done\n#   inittls: tls_g=112 tsd_off=...\n#   [NAPI] startTun called\n<\/code><\/pre>\n<hr \/>\n<h2>\u5341\u4e09\u3001\u5bf9 Go \u5b98\u65b9\u7684\u5f71\u54cd\u4e0e\u5c55\u671b<\/h2>\n<p>\u8fd9\u4e9b\u4fee\u6539\u672c\u8d28\u4e0a\u662f\u8ba9 Go runtime \u652f\u6301\u4e00\u79cd\u65b0\u7684 TLS \u6a21\u578b\u2014\u2014musl emulated TLS\u3002\u76ee\u524d\u7684\u5b9e\u73b0\u662f\u901a\u8fc7\u786c\u7f16\u7801 <code>MUSL_TLS<\/code> \u5b8f\u5728 Linux \u5e73\u53f0\u5f3a\u5236\u542f\u7528\uff0c\u8fd9\u4e0d\u9002\u5408\u5408\u5165 Go \u5b98\u65b9\u6e90\u7801\u3002<\/p>\n<p>\u66f4\u5408\u7406\u7684\u505a\u6cd5\u662f\u5728\u6784\u5efa\u65f6\u81ea\u52a8\u68c0\u6d4b\u76ee\u6807 libc \u7c7b\u578b\uff1a<\/p>\n<pre><code class=\"language-go line-numbers\">\/\/ \u7406\u60f3\u65b9\u6848\uff08\u672a\u5b9e\u73b0\uff09\n\/\/ +build musl\n\n\/\/ \u6216\u901a\u8fc7 CGO_CFLAGS \u4e2d\u7684 -D__MUSL__ \u81ea\u52a8\u5224\u65ad\n<\/code><\/pre>\n<p>\u76ee\u524d Go \u793e\u533a\u5bf9 musl Linux \u7684\u652f\u6301\u4e3b\u8981\u901a\u8fc7 Alpine Linux \u5bb9\u5668\u6d4b\u8bd5\uff0c\u4f46\u8fd9\u4e9b\u73af\u5883\u901a\u5e38\u4f7f\u7528 glibc \u517c\u5bb9\u5c42\u6216\u6807\u51c6 musl TLS\uff08\u975e emulated\uff09\uff0c\u4e0e HarmonyOS \u7684 musl \u5b9e\u73b0\u4ecd\u6709\u5dee\u5f02\u3002\u968f\u7740 HarmonyOS \u751f\u6001\u53d1\u5c55\uff0cGo \u5b98\u65b9\u53ef\u80fd\u9700\u8981\u6b63\u5f0f\u8003\u8651 OHOS \u76ee\u6807\u5e73\u53f0\u7684\u652f\u6301\u3002<\/p>\n<hr \/>\n<h2>\u5341\u56db\u3001\u7ed3\u8bed<\/h2>\n<p>\u4e3a HarmonyOS \u5b9a\u5236 Go \u5de5\u5177\u94fe\u662f\u4e00\u9879\u6df1\u5165\u64cd\u4f5c\u7cfb\u7edf\u5e95\u5c42\u7684\u5de5\u4f5c\u300212 \u4e2a\u6587\u4ef6\u7684\u4fee\u6539\u770b\u4f3c\u4e0d\u591a\uff0c\u4f46\u6bcf\u4e00\u4e2a\u90fd\u7ecf\u5386\u4e86\u53cd\u590d\u7684\u5d29\u6e83\u2192\u5206\u6790\u2192\u4fee\u590d\u5faa\u73af\u3002\u6700\u5173\u952e\u7684\u6d1e\u5bdf\u662f\uff1a<strong>musl emulated TLS \u7684\u5b58\u50a8\u6a21\u578b\u4e0e glibc \u6709\u672c\u8d28\u5dee\u5f02\uff0cGo runtime \u7684\u4e00\u7ea7\u95f4\u63a5\u5bfb\u5740\u5047\u8bbe\u5728 musl \u4e0b\u5b8c\u5168\u4e0d\u6210\u7acb<\/strong>\u3002<\/p>\n<p>\u8fd9\u4e2a\u95ee\u9898\u7684\u9690\u853d\u6027\u5728\u4e8e\uff1a\u5b83\u53ea\u5728\u8fd0\u884c\u65f6\u5d29\u6e83\uff0c\u7f16\u8bd1\u5b8c\u5168\u6b63\u5e38\uff1b\u53ea\u5728\u7279\u5b9a\u73af\u5883\uff08VPN \u6c99\u76d2 + musl\uff09\u4e0b\u89e6\u53d1\uff0c\u6807\u51c6 Linux \u548c Android \u4e0a\u90fd\u6b63\u5e38\u3002\u8c03\u8bd5\u624b\u6bb5\u6781\u5176\u6709\u9650\u2014\u2014\u6ca1\u6709 stderr\u3001\u6ca1\u6709 coredump\u3001VPN \u6c99\u76d2\u4e2d\u751a\u81f3 <code>mprotect<\/code> \u90fd\u88ab\u7981\u7528\u3002\u6700\u7ec8\u80fd\u89e3\u51b3\uff0c\u9760\u7684\u662f\u5bf9 ARM64 \u6c47\u7f16\u548c TLS \u673a\u5236\u7684\u6df1\u5165\u7406\u89e3\uff0c\u4ee5\u53ca\u5927\u91cf\u7684\u8bd5\u9519\u548c\u65e5\u5fd7\u5206\u6790\u3002<\/p>\n<p>\u5e0c\u671b\u8fd9\u7bc7\u6587\u7ae0\u80fd\u5e2e\u52a9\u5176\u4ed6\u5728 HarmonyOS \u4e0a\u4f7f\u7528 Go \u7684\u5f00\u53d1\u8005\u5c11\u8d70\u5f2f\u8def\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4e3a HarmonyOS \u5b9a\u5236 Go \u5de5\u5177\u94fe\uff1a\u5f81\u670d musl emulated TLS \u8fd9\u4e24\u5468\u79fb\u690d\u81ea\u5df1\u4e00\u4e2a\u5b89\u5353\u7248 &hellip; <a href=\"https:\/\/cocozq.com\/?p=3063\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;\u4e3a HarmonyOS \u5b9a\u5236 Go \u5de5\u5177\u94fe\uff1a\u5f81\u670d musl emulated TLS&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-3063","post","type-post","status-publish","format-standard","hentry","category-22","hfeed"],"_links":{"self":[{"href":"https:\/\/cocozq.com\/index.php?rest_route=\/wp\/v2\/posts\/3063","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cocozq.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cocozq.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cocozq.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cocozq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3063"}],"version-history":[{"count":2,"href":"https:\/\/cocozq.com\/index.php?rest_route=\/wp\/v2\/posts\/3063\/revisions"}],"predecessor-version":[{"id":3065,"href":"https:\/\/cocozq.com\/index.php?rest_route=\/wp\/v2\/posts\/3063\/revisions\/3065"}],"wp:attachment":[{"href":"https:\/\/cocozq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cocozq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cocozq.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}