找回密码
 注册
关于网站域名变更的通知
查看: 429|回复: 1
打印 上一主题 下一主题

这是一个诡异的时间问题追查

[复制链接]
  • TA的每日心情

    2019-11-20 15:22
  • 签到天数: 2 天

    [LV.1]初来乍到

    跳转到指定楼层
    1#
    发表于 2020-3-9 10:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

    EDA365欢迎您登录!

    您需要 登录 才可以下载或查看,没有帐号?注册

    x

    : x( }- W; s" [  `1 `# x问题引入:
    3 ~! L, j' I& a( }# @& `问题是我们重装了一台电脑之后,发现apache
    . O7 k: u6 G; }# }的日志里突然增加了很多服务时间超长的请求,如下面两条:
    9 P( R: B% a: j9 Q** - - 4913229 11227 [29/Mar/2012:09:59:58 +0800] "GET*****
    4 w% P$ N# u  `+ @" G" I3 K7 k** - - 4793564 9846 [29/Mar/2012:09:59:58 +0800] "GET *****
    / \* n) n& h8 H# D9 g$ P! h请求服务时间都在4s以上!这绝对无法忍受啊!
    " ^, v/ E6 D/ R# p9 L9 s " {* d& e+ j& G& m+ J3 E8 F  V6 K
    分析过程:% y0 A* |) l( F- V9 V2 n+ Z3 _" g
    1 ~+ I/ d2 `! r* U% f  h
    但是,当我们:7 s: A. {) `  o# E! Y3 E: n% B$ a
    * 手动访问这台服务器之后,发现基本上请求都是正常响应的;8 B# g! i  a" |! h% |  p% e  x
    * 从前端反向代理的日志来看,服务时间也是正常的;
    , o1 Q! Y, A; s8 B: w1 M- R那这样推断,真相只有一个,那就是apache的日志时间记录有问题!
    ! e* b6 m1 E1 I ' P4 y0 t5 n# ?3 b% q7 b1 e
    什么问题呢?不清楚,但是apache
    ' L  ~0 ~$ E9 {) x, ~* [* b的时间记录不外乎是在收到请求时记个时间,请求处理完成之后再记一个时间,既然是时?
    * L( F" K( M- I0 e4 q$ L涞奈侍猓敲淳涂纯聪低呈奔浒桑幼罴虻サ?date 开始,多执行几次:1 B! y* E- j. J( g$ p
    apache2 # date1 r- G: n/ F) P5 ^
    Wed Mar 28 17:25:08 CST 2012
    * X' V8 V+ E# b# q2 n6 capache2 # date  m, b& M5 ~& K5 e' H# n  ]3 Z
    Wed Mar 28 17:25:04 CST 2012  时间减少了?4 |* M: y. r5 L& |% t$ E
    apache2 # date
      j, r6 f5 X4 }2 S' G0 O! V; gWed Mar 28 17:25:06 CST 2012
    : ?' N0 a" V) japache2 # date3 B+ `$ G7 j* S1 q/ S
    Wed Mar 28 17:25:12 CST 2012# n/ d0 U2 o8 q8 x# Z0 r
    apache2 # date% T! T; P* W# C+ _- K, N- X  y
    Wed Mar 28 17:25:13 CST 2012* s0 b" Q1 S$ e4 e
    apache2 # date
    " E& m( t. f! ?. K: sWed Mar 28 17:25:09 CST 2012 时间减少了?
    $ m) L/ e8 [- sapache2 # date# a( r9 n8 m5 U- T: d& q/ v
    Wed Mar 28 17:25:09 CST 20129 }2 H- t4 t# l+ r% g' W
    apache2 # date
    ! i9 Q' {0 y6 Q' R7 G  A! [Wed Mar 28 17:25:15 CST 2012+ }" w/ K, [- j6 w! Q9 _
    那么第一个怀疑就是系统里有进程在自己不断的调时间,比如ntpdate, ntpd
    7 x, b+ h3 ?& @; U& o+ q,那么我们首先把 ntpd给停掉;然后系统也没有任何地方会调用ntpdate;
    ; k1 y1 m0 t+ p继续观察,发现停掉ntpd后,现象依旧!$ {2 |8 N" H* s( @8 O* @: M+ p
    还有什么可能呢? date
      n- F: k6 @/ x! n程序是从内核里面读取时间还是说需要读取硬件时间?到底是怎么计算的呢?4 ~$ ~/ |: K1 s! W  m
    请教下同事们,据说 sys_time 是读的kernel里的时间,而 sys_gettimeofday! P# q0 `2 g4 @3 _+ `- Q( [' i+ m
    是需要读硬件时钟的。
    3 x0 `: i' X6 y7 |' y+ e那么就测试一把吧:
    6 H& r5 z& I, n- J先写个程序调用 time(), 然后打印结果,结果是这样的:
    6 Z/ G5 x# \( b. M2 G9 Q/ ]1332986690
      Z" G( W* Q3 G9 Y6 Y/ }0 }0 C1332986692
    + Z! H. g/ Q3 h, q% L+ {+ M# Y1332986693
    $ W: D  l# [, H3 \. h+ p1332986693
    # U% Q% }  ]6 I: W! |# [+ j1332986694
    7 N4 T& J' Z4 Z+ ^' b1332986694
    2 n% j$ ^' Q6 {- d0 T, Z1332986695
    # s2 j1 K1 W4 N1 h) k6 u+ u13329866959 c- t: H/ I# R8 e2 Z
    1332986696) v. Z; {( {+ p2 M! u  M# v2 E
    1332986696
    / O! U3 L" L. m) ^1332986697, e) X8 Q. ^3 y( V2 k
    1332986697" W( G" w2 p( M9 z
    1332986698" O; ]& ]! F: r( \
    1332986698' p5 i* P  s3 ], [" a
    1332986699) e1 Q+ a) _8 u2 W; C
    确实没有问题了!看来有可能是硬件问题了,再看看clock_gettime 的调用:
    ( K2 ?2 L( r4 m5 E/ a{, B& J( u( e5 A& ]: O0 X8 Z
            struct timespec ts;                              
    8 S- Q& n$ N' ~        int ret = 0;                                      : H" O% v* x$ _3 B" o8 I
            ret = clock_gettime(CLOCK_REALTIME, ts);          2 ?7 E& _8 U% a  G
            printf("ret: %d, time: %d %d", ts.tv_sec, ts.tv_ns
    3 ~* O' w* `/ o) v3 E: K}                                                         
    0 b( L  E* ^" t) g编译:        gcc -g -o clock_gettime getdate.c -lrt            
    0 U' R; S2 |8 o, s: T3 E                                                          ; K0 G8 A8 A: S3 C* u  t& p
    ~ # ./clock_gettime                                    
    - X) I' N' x8 N4 d1 R# ?# ^ret: 1332991087, time: 594076000 -1
    , M9 N3 X& u0 o5 S5 r) |: F$ Kret: 1332991088, time: 379009000 -1
    & U4 n& ^0 w0 K/ e3 P& N+ F" _; nret: 1332991089, time: 68561000 -1
    5 ?& {3 N5 b! U2 B4 X& Gret: 1332991089, time: 714013000 -1
    6 ?/ u8 ?$ I" Cret: 1332991086, time: 511250000 -1 时间在跳
    & E0 Q( ]2 @1 U' i  e$ \ret: 1332991091, time: 945626000 -1
    % y" P' O, M, [ret: 1332991092, time: 650479000 -1$ V9 ^" k3 l+ A( W/ E  {
    ret: 1332991088, time: 734780000 -1, `- ]5 U8 J8 p( Z$ J, E4 L* h. o" Y
    ret: 1332991094, time: 506114000 -1时间在跳                    
    & i( ^9 G' S% Q3 Z9 I8 H看来果然有可能是硬件问题!
    # i. C. A. U& \+ X' i0 C3 T那么,检查一下,直接调用一下 hwclock --show ,看看是不是可以验证这个问题:3 @# _+ F+ p3 P1 m: i
    ~ # hwclock --show                               3 O; ?) e+ z( ^
    Thu 29 Mar 2012 10:22:21 AM CST  -0.948923 seconds  
    - R1 h) i, h+ |9 R3 n; H1 _ ~ # hwclock --show                               8 z( g* S. U3 M) Y  ~
    Thu 29 Mar 2012 10:22:22 AM CST  -0.188950 seconds  
    9 @+ t  I4 w4 X, I, {, { ~ # hwclock --show                              
    ; q4 G: ]2 O1 g" k3 t% F& ZThu 29 Mar 2012 10:22:23 AM CST  -0.244766 seconds  
    + P+ J0 \* q& V( m7 K ~ # hwclock --show                               7 K3 n1 r- a9 |2 F7 O
    Thu 29 Mar 2012 10:22:24 AM CST  -0.336868 seconds  % x( n7 ~0 w: r- W9 m
    ~ # hwclock --show                               1 W$ G# Z. d$ B0 \/ I/ X
    Thu 29 Mar 2012 10:22:25 AM CST  4.237159 seconds   0 C1 F) _) H# ]) r1 q4 V& x
    ~ # hwclock --show                              
    / y6 U/ v8 l7 ^5 XThu 29 Mar 2012 10:22:26 AM CST  4.238672 seconds   " f, i7 o& P# l8 M% B1 j. J
    ~ # hwclock --show                               0 u; V9 x8 I# }0 q
    Thu 29 Mar 2012 10:22:27 AM CST  -0.379418 seconds  # Z( W6 ^( o! Y* J5 L: C
    时间居然都是正确的!显然问题没有那么简单。。。那到底是怎么回事??还是从date
    5 b2 Z/ [% n# Z5 N" N: k& \! V开始查起吧:
    3 O. m  j3 ~. V0 Adate是一个glibc里面的程序,那它的时间源是从哪里来的?查看一下glibc
    0 S. R, \+ K8 f7 i% b2 Y6 K+ c. m" h的源码,它的时间从这里来:
    / [1 ?, ^* h+ V2 S// glibc coreutils gettime.c! t8 G7 q- T4 I, t7 I
    /* Get the system time into *TS.  */
    ; p+ t0 t: s0 h5 p! [void
    4 }% J" W# `5 a2 p: Y$ J2 d9 _gettime (struct timespec *ts)
    $ s$ e7 E- W( O) v4 `+ C! G{
    : t- ]6 \( W' }+ w' `#if HAVE_NANOTIME  P8 F1 h0 K0 l1 Z' e& }
      nanotime (ts);- p/ M& J/ K+ j! h
    #else
    " ^4 P. l9 u! s% U4 ] / y- [& d- S' H( ~' x& C
    # if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
      Z) y: ^  C0 {' w1 G  if (clock_gettime (CLOCK_REALTIME, ts) == 0)0 f' K( F( e; U% A. C; m
        return;* y: ], I' h& W0 l4 Q
    # endif
    8 w( ?" T" C0 g7 \6 i6 x 9 H' J! M1 j0 s2 `- p$ S7 S% A4 v
    # if HAVE_GETTIMEOFDAY8 q! r$ }8 m8 r  w0 v
      {
    6 l: Z- P: m. D1 D7 k) O; j    struct timeval tv;
    - N& \' T5 q3 n4 [7 E" C    gettimeofday (&tv, NULL);
    ! n& j0 P. @% e" G! Z0 e+ E    ts->tv_sec = tv.tv_sec;
      c5 ~3 M, V, I+ B    ts->tv_nsec = tv.tv_usec * 1000;
    . B* i- B; n5 Q" A  }
    5 w$ F! l$ y( s; t' P! ~# else
    / S& {8 @. ]: T$ b- H& G& o3 Y/ H  ts->tv_sec = time (NULL);
    $ F1 S* b( z& Y0 b, C0 F0 G  ts->tv_nsec = 0;3 d, ]* ?. O- b: Z0 d; T' q
    # endif
    ; }+ J7 O* i$ N4 F) U! C( D( @
    2 b- d! |' V6 l" C8 T/ x#endif9 _3 X. V5 p& c8 o% p
    }/ _3 d- u" H" o
    按照 nanotime, clock_gettime, gettimeofday的顺序去读取,我们这个系统中就是 ; H" Y/ c/ E, u& D0 E4 V! D
    clock_gettime,从上面的小程序中也可以看到clock_gettime的时间是有问题的,那么
    9 W6 r, Z7 H9 s# kclock_gettime的时间源是怎么来的呢?* O  E! {8 V+ j% B
    // linux kernel 2.6.18 arch/x86_64/kernel/time.c
    ) N$ k& X) i  z8 v* X# `$ Svoid do_gettimeofday(struct timeval *tv)  N6 g$ w' }6 K0 [/ A) I
    {' v. v" J; h% ]7 d. g9 d
    unsigned long seq, t;6 z+ n3 Z$ h, ~1 c* b% o0 N
    unsigned int sec, usec;
    * u4 r4 g& U, w5 E7 v" [
    # X: t( `' v6 g) b9 Tdo {* n" c' H( d& e) m$ ^# @
    seq = read_seqbegin(&xtime_lock);
    * C. V9 F0 K" @( k6 [  A : q$ ?+ N' C. H: J9 D4 R2 p- [
    sec = xtime.tv_sec;
    3 F. p) W* w4 O+ ^. B* `, \9 v3 J4 t. l8 xusec = xtime.tv_nsec / NSEC_PER_USEC;. I: S  f1 J( n# ~3 T
    t = (jiffies - wall_jiffies) * USEC_PER_TICK +
    5 Q+ D4 n, u$ A3 A7 T$ }: l- [do_gettimeoffset();
    3 B$ J+ ]5 ?2 w  G( B. M; D8 k4 {usec += t;' Z; }4 z# k! @! Q5 ?" F3 z/ f
    + y5 r: W6 w* N1 i4 a
    } while (read_seqretry(&xtime_lock, seq));# H6 o: D8 [& c$ ]3 L

    ; T! \- E; t; X: @* ]1 ~tv->tv_sec = sec + usec / USEC_PER_SEC;
    " u5 I6 p+ F. m4 H. L3 E' L+ Ttv->tv_usec = usec % USEC_PER_SEC;
    , c" A6 r/ B1 S: z. _" z}+ D" y! ]6 r6 U, S2 |2 I2 |
    反正就是一通计算,其中比较重要的是 do_gettimeoffset9 I" |/ ^" R* j& n! G5 O: g$ a) f
    ,这个函数的目的是计算上一次更新 xtime
    ( ^) F- w) }# q5 G/ N/ N% s7 S到当前执行这一段时间的偏移量,然后用这个偏移量去加到 xtime
    : g9 M& Q* o% k0 l$ d! g0 g上去,就是当前的时间(因为xtime的精度不够,clock_gettime
    . h9 p5 ~( [6 X) |的精度要求更高,所以必须计算一个偏移量)。
    0 d8 X$ X( {3 A  ~那么,这个 do_gettimeoffset又是从哪来的?同样的文件里面有:6 ?0 L, p; k4 @5 Q' j6 h3 P
    static inline unsigned int do_gettimeoffset_tsc(void)
    + N/ F2 T, a! M2 o7 T! B: Z: `{
    1 k$ N0 o( H" G0 n1 v* i; m- wunsigned long t;
    $ g5 z0 ~& C" w1 R. u% S8 Uunsigned long x;3 N% ~5 W. s- V% _9 h
    t = get_cycles_sync();1 `2 A; Q( M$ Y$ g/ ~3 k
    if (t < vxtime.last_tsc) 0 O6 Q+ M5 l+ P  ]( W, S* ~7 s7 a
    t = vxtime.last_tsc; /* hack */
    ( t5 |* T* W5 g1 E0 [x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE;
    2 k2 d  P- n0 r) Lreturn x;
    ' _1 u2 ^1 ]+ v2 X" [" }}% H& h  R7 \5 L1 B6 b0 j4 w

    6 Q  v, [% Z" U- O) Z' r! X2 _: H- h# Fstatic inline unsigned int do_gettimeoffset_hpet(void)
    8 z) H( i# @0 d# ^{
    ' e) I+ {$ L! C* H, e/* cap counter read to one tick to avoid inconsistencies */
    5 |1 K' w- M4 c8 ]: P* g) Punsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
    4 N, |/ j1 c& f5 o& B$ c7 h2 e$ _return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;+ q2 N) x0 P6 J$ E  t7 l+ p
    }
    ) w/ v- E# [+ x
    6 E) R( {6 N8 M$ cunsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
    + w% C7 ^8 L# A: V% U* o% r5 U也就是说,go_gettimeoffset 是从 tsc寄存器从拿到的,这又是神马玩意呢?
    " ~3 K6 R; Z4 }% d) d+ a1 k参考一下下面的几篇文章【1】【2】【3】,基本就明白了:
    4 n6 I1 a9 k' r# {tsc是一个cpu内的寄存器,用来累加从系统启动到目前,所有的时钟周期数,全称是 - j. e0 R" J8 z: q
    Timestamp Counter;
    ) F# P5 O* y2 h" c而且,最重要的是我们发现了一个重要的线索,那就是:# ^1 m  r* D% l& @# _, {/ P
    在多核cpu的架构中,tsc寄存器是很有可能不一致的,特别是在intel的比较老的多核CPU" p) p& P7 `$ M. [- c
    中!坑爹....; C, Q9 }- d' K5 Y; U5 N
    很多文章提到过这个问题,比如【1】【2】【4】,显然如果不同cpu
    9 l& D( B  W- G. e5 i读到的值不同的话,多次执行,显然时间是不一致的。
    & E3 g; q: l3 a  m6 y看起来就是这个问题了,那么就来验证一把:( ]' M) Q7 g/ S: T# _& a
    #include<stdlib.h>
    ( Y$ C" ]" x+ ^0 V#include<stdio.h>: G& F  ^; `# ?" N0 u) I7 @$ F
    #include<sys/types.h>
    8 D/ \- W5 o! Y; }4 r" I' J) d#include<sys/sysinfo.h>
    $ I; h: {! W: X+ v$ h9 G#include<unistd.h>
    5 o3 `' w0 x' x' v2 X#include<time.h>. Q- P. n$ Y& g, Q; t) a% x$ b

    6 O2 [; Q( K$ r8 \1 i$ B. k  G#define __USE_GNU
    ; p/ e& I4 `9 d# \! p#include<sched.h>( d4 |! d8 I+ q/ g/ T3 `6 w
    #include<ctype.h>7 H' ~- X2 |/ H+ B7 o
    #include<string.h>3 A( q) T# k0 X. ~, Z9 i3 m& B# I

    4 g6 j* l! N& J9 u, O! Q1 w! i $ p. W% Q# y0 z
      r; [  i9 P. }6 _" l& k
    int main(int argc, char **argv){
    8 L1 F& \3 X5 L: y6 A
    $ M1 F$ y5 {( s3 U7 L        cpu_set_t cs;
    ! z9 L$ v+ s1 [6 q, A1 [        CPU_ZERO(&cs);: y, O; M* k# ~) u  W8 @) i- ?
            CPU_SET(0, &cs);8 }) C2 V7 c: `5 S5 J7 {9 d& c2 |
    # k2 D" C3 f0 t: P! c2 l# j4 ]
            sched_setaffinity(0, sizeof(cpu_set_t), &cs);8 j- _8 `! E  Q  w+ ?- g

    0 T; p8 Q. _1 l' h) c: ]: f        struct timespec ts;9 X- k. }6 m1 J( Y% x
            int ret = 0;
    % A0 a9 {* C1 W" `8 m1 V2 @        ret = clock_gettime(CLOCK_REALTIME, &ts);  g! V3 Z. f5 x$ B# o
            printf("ret: %d, time: %lld %lld", ret,  ts.tv_sec, ts.tv_nsec);, A3 b- L" h  c, B& a
    * l6 y8 z$ Q+ K+ e* d) A& g
    }
    + I& G7 B3 i( y" ?$ h1 K6 I
    7 H  z7 v+ K/ E  j  ^- X, \" r; Bgcc -g -o cpu0_clock_gettime cpu_getdate.c -lrt. D4 w4 u3 s  o# b/ G0 ?

    , V$ Q. b- i$ u5 L8 Jret: 0, time: 1332992815 537481000
    : r6 Y+ E3 O7 }% j7 hret: 0, time: 1332992816 506704000
    / ~  q2 }# ~8 T1 H6 wret: 0, time: 1332992817 99100005 `# X8 I& r0 F* f  ^2 b' m
    ret: 0, time: 1332992817 480431000
    7 n: \. [- e7 z) X( {! r9 {ret: 0, time: 1332992817 936965000# i! u, s! D' ~4 }$ M! M6 o5 T4 Q0 k
    ret: 0, time: 1332992818 416634000
    4 T4 _* w* i2 Y/ V2 h' y; mret: 0, time: 1332992818 8503190008 v+ D5 a9 B# `4 x3 ~$ _) a1 y
    ret: 0, time: 1332992819 3050750001 w  D/ o  I+ y1 J' M9 e. j
    ret: 0, time: 1332992819 7291080002 \" F/ N, s* [
    ret: 0, time: 1332992820 164726000
    3 v, d# O9 {' ^5 U: sret: 0, time: 1332992820 577573000  C, d& T; Z2 e6 \
    ret: 0, time: 1332992820 985025000
    1 b/ f/ A/ Q' D* O  z& Uret: 0, time: 1332992821 394070000; ], p' U. _/ H( y. ]3 U3 G
    ret: 0, time: 1332992821 816708000) n7 i4 T# G4 |
    ret: 0, time: 1332992822 216811000
    $ L3 ]! V8 m7 z4 |0 e% \7 C  ]ret: 0, time: 1332992822 616901000
    + ]6 G0 l7 M6 f5 r/ D( Gret: 0, time: 1332992823 18564000w1 |. |& c7 h4 u$ t5 R& R1 E' s1 ~0 _
    ret: 0, time: 1332992823 727585000. j: {2 t7 j8 q& J" O) a" f
    通过把程序的调度固定在某一个具体的cpu中,那么clock_gettime的结果也是正确的!
    0 h. J. U7 n: I% F/ L6 g- ~3 ~经过几次测试,很容易找到两个cpu时间不一致的情况,具体这个例子来说就是 cpu0和
    ; _5 U: W5 U  D$ R8 K6 H% bcpu5,把上面的程序修改一下,可以看到结果基本上每次都会跳一把。
    0 `# X% N/ S+ T! I. E; L/ ]) L问题解决:% S6 h4 X* ]  i
    那么,tsc在多核cpu中的值不同,应该怎么解决呢? 如 【4】所示,在高版本的linux
    ; m' a+ i, f+ A6 X0 b& y内核中,有人提交了补丁,可以在内核启动时检查并且同步一把,那么升级一下内核到 2" h/ y, \* l9 ]* m" i: j
    .6.38。
    6 c) s! Q& L( T# i重新启动到新内核之后,问题解决!
    4 K) T* n8 @- W( u总结一下:
    + d, e( d3 i: r1. apache的时间统计方式,没具体看实现,但是显然前后的两个时间可能是在不同的cpu
    ' }8 F) r1 U, L( D! `5 n% A  s核上计算出来的。4 u3 p! K" q- X& m
    2. tsc的值,并不能保证是同步的,特别是在某些Intel cpu" K" Y  M9 M) O; F' N8 g
    的情况下;但是新的内核会做一些检查和resync的工作;
    5 B( I, v5 I/ @# p- d1 Q1 P3. time()调用直接读取内核的xtime值,不会触及硬件;但是 gettimeofday(),
    6 }: q! n1 W7 v0 w1 B* c2 Dclock_gettime() 在 x86_64下都会读取tsc值;1 i. J7 t9 T4 s5 w: V# i% z
    4. hwclock读的硬件时钟显然不是 tsc,应该是实时时钟RTC;
    6 G  W% W/ ^) Z【1】 http://en.wikipedia.org/wiki/Time_Stamp_Counter
    8 I7 f  q: b9 I' ^* c/ w0 u" p3 L. F- w【2】 http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html
    - y* |" I2 b" N+ P. o: E【3】http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=driver&Number=
    8 U- {. R/ L* d6 }# z8 _% Z385219&page=0&view=collapsed&sb=5&o=all&fpart , linux时钟中断机制,Copyright % O& i8 d  T$ m; `5 ^6 e- ?6 o
    2003 by 詹荣开
    % s' m0 {0 ~* ?# M【4】http://lwn.net/Articles/211051/ x86: unify/rewrite SMP TSC sync code  

    该用户从未签到

    2#
    发表于 2020-3-9 17:20 | 只看该作者
    时间问题追查,牛逼了
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-25 21:21 , Processed in 0.156250 second(s), 23 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表