??xml version="1.0" encoding="utf-8" standalone="yes"?>久久亚洲高清观看,日日噜噜夜夜狠狠久久丁香五月,国产精品久久久天天影视香蕉 http://www.shnenglu.com/martin/thinkingzh-cnTue, 06 May 2025 15:59:10 GMTTue, 06 May 2025 15:59:10 GMT60Linux操作pȝ中中断上下文中的互斥http://www.shnenglu.com/martin/archive/2013/07/08/201611.htmlmartin_yahoomartin_yahooMon, 08 Jul 2013 06:01:00 GMThttp://www.shnenglu.com/martin/archive/2013/07/08/201611.htmlhttp://www.shnenglu.com/martin/comments/201611.htmlhttp://www.shnenglu.com/martin/archive/2013/07/08/201611.html#Feedback0http://www.shnenglu.com/martin/comments/commentRss/201611.htmlhttp://www.shnenglu.com/martin/services/trackbacks/201611.html在中断中没有q程上下文,而具有中断上下文Q因此在中断上下文中不能发生睡眠Q也是不能发生q程切换?br />q就军_了在在中断上下文中不能采用同步原语(信号量,程、同步变量等Q和长期互斥原语Q这?x)导致进E睡眠)Q?而只能采用短期互斥原语(例如自旋锁)?br />
曄Q中断处理程序ƈ不具有自q栈。相反,它们׃n所中断q程的内核栈。内核栈的大是两页Q具体地_(d)?2位体pȝ构上?KB,?4位体pȝ构上?6KB.
现在。中断处理程序有了自q栈,每个处理器一个,大小Zc这个栈qZ断栈Q尽中断栈的大是原先׃n栈的一半,但^均可用栈I间大得多,因ؓ(f)中断处理
E序把这一整页占ؓ(f)己有?br />
UPQ单CPUpȝ)上的中断处理
互斥
如果一个中断处理程序的代码讉K或者更C由非中断的代码(通常UCؓ(f)基准代码Q用的同一数据l构Q那么就?x)出现竞争条件?br />q运的是Q得到允许的以内核态执行的q程?x)?f)时禁止中断。因此,只要基准代码要更C个与中断处理E序׃n的数据结构,那么?br />首先止中断Q执行(f)界段Q然后再重新允许中断。禁止和允许中断的动作就实现了互斥?br />在采取中断互斥时Q必M用函数显C地把编码写入算法中?br />
MPQ多CPUpȝQ上
在MPpȝ上,中断可以在Q何处理器上出现。从最低限度上来说Q每个进E会(x)接收旉中断Q但也可能接收I/O中断。在MPpȝ上,例程
SPLQ禁止中断)所提供的保护ƈ不充分,因ؓ(f)它们执行影响执行它们的处理器上的中断优先U。中断可能会(x)在另一个处理器上出玎ͼ如果讑֤驱动E序
正在别处q行Q那么会(x)造成一个竞争条件。因Z断处理程序代表另一个进入内核的入口炏V?br />
当基准驱动程序代码和中断处理E序之间׃n数据l构ӞUP可以通过屏蔽中断来防止出现竞争条件的技术,在多U程MP内核中还不充分?br />临界D要在一个处理器上执行,执行屏蔽中断例程只会(x)屏蔽在那个处理器上出现的中断。如果在别的处理器上出现中断Q那么立卛_?x)?br />两个处理器同时访问、而且可能更新临界资源。既然这些(f)界段需要短期互斥,那么可以使用自旋锁来Ҏ(gu)据进行保护?br />
如果不考虑中断处理E序和基准代码之间的互斥Q则Linux中的中断处理E序是无重入的。当一个给定的中断处理E序正在执行Ӟ相应的中断线
在所有处理器上都?x)被屏蔽掉,以防止同一中断U上接收另一个新的中断。通常情况下,所有的其他中断都是打开的,所以这些不同中断线上的其他中断
都能处理Q但当前中断UL被禁止的。由此可以看出,同一个中断处理程序绝不会(x)被同时调用以处理嵌套的中断。这极大地简化了中断E序的编写?/div>

martin_yahoo 2013-07-08 14:01 发表评论
]]>unix cȝl中的进E同步方式代码示?/title><link>http://www.shnenglu.com/martin/archive/2013/06/20/201176.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Thu, 20 Jun 2013 07:02:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2013/06/20/201176.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/201176.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2013/06/20/201176.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/201176.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/201176.html</trackback:ping><description><![CDATA[MP(多CPUQ同步原语代码示?br />                   ----引自《现代体pȝ构上的UNIXpȝ?br /><br />Z便于对示例的展开Q我们首先假定一个场景:(x)<br />内核中把到的错误信息记录到一个磁盘文件中的情形。出错信息通过内存中的一个队列来传递给日志q程Qlogging process)的?br />当出C个错误时Q就在队列中加入一,q且通过调用函数l(f)og_error 通知日志q程。出错日志进E接着把队列中的项写到盘上?br />q就使得到错误的进E不必等候I/O完成或者或得ؓ(f)了向文g执行I/O而可能需要的M锁,q且避免了Q何可能的上锁ơ序问题?br /><br />代码1Q?采用事g计数的出错日志通知机制<br /><br />                                                日志q程<br />log_error(error)                    |<br />{                                         |       for(next=1; ; next++) {<br />    lock(&err_queue);             |           await(&err_event, next);<br />    把出错信息加入到队列           |          lock(&err_queue);<br />    unlock(&err_queue);          |          从队列中删除?br />    advance(&err_event);        |          unlock(&err_queue);<br />}                                         |          write error to disk<br />                                           |       }<br /><br />队列本n׃个自旋锁来保护。在本例中,事g计数只用于同步的目的Qƈ不提供互斥?br />在试用事件计数的时候,advance操作?x)永久性地改变事g计数的状态。advance和await操作的相Ҏ(gu)序没有关pR?br /><br />代码2Q?采用同步变量的出错日志通知机制<br />                                                 日志q程<br />log_error(error)                            |<br />{                                                 |        for(;;){<br />   lock(&err_queue);                      |              lock(&err_queue);<br />   把出错信息加入到队列                    |              if (queue_empty){<br />   SV_SIGNAL(&err_syncvar, 0);      |                  SV_WAIT(&err_syncvar, PRI, &err_queue);<br />   unlock(&err_queue);                   |                  lock(&err_queue);<br />}                                                 |              }<br />                                                   |              从队列中删除?br />                                                   |              unlock(&err_queue);<br />                                                   |              把错误写入磁?br />                                                   |        }<br /><br />因ؓ(f)同步变量自n没有保留状态,所以当日志q程试队列的状态ƈ军_是等待一还是从队列中删除一的时候,必须占有自旋锁。类似地Qlog_error?br />发送信h也必d有自旋锁。注QSV_WAIT释放自旋锁Qƈ且阻塞日志进E?SV_SIGNAL到后从阻塞处l箋执行?br /><br />代码3Q?采用程的出错日志通知机制<br />                                                                 日志q程<br />log_error(error)                                  |       for(;;){<br />{                                                       |           mon_enter(&err_mon);<br />   mon_enter(&err_mon);                     |           if (queue empty)<br />   把出错信息加入到队列                          |               mon_wait(&err_mon, NEWENTRY);<br />                                                         |<br />   mon_signal(&err_mon, NEWENTRY);  |           从队列中删除?br />   mon_exit(&err_mon);                       |           mon_exit(&err_mon);<br />}                                                       |           把错误写入磁?br />                                                         |       }<br />                                    <br />代码4Q?采用信号量的出错日志通知机制<br />                                                日志q程<br />log_error(error)                      |       for(;;){<br />{                                          |           P(&err_sema);<br />    lock(&err_queue);               |           lock(&err_queue);<br />    把出错信息加入到队列            |           从队列中删除?br />    unlock(err_queue);              |           unlock(&err_queue);<br />    V(&err_sema);                   |           把错误写入磁?br />}                                          |       }<img src ="http://www.shnenglu.com/martin/aggbug/201176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2013-06-20 15:02 <a href="http://www.shnenglu.com/martin/archive/2013/06/20/201176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>unix cȝl中的进E同步方式ȝhttp://www.shnenglu.com/martin/archive/2013/06/20/201174.htmlmartin_yahoomartin_yahooThu, 20 Jun 2013 05:49:00 GMThttp://www.shnenglu.com/martin/archive/2013/06/20/201174.htmlhttp://www.shnenglu.com/martin/comments/201174.htmlhttp://www.shnenglu.com/martin/archive/2013/06/20/201174.html#Feedback2http://www.shnenglu.com/martin/comments/commentRss/201174.htmlhttp://www.shnenglu.com/martin/services/trackbacks/201174.htmlh同步关系的一lƈ发进E称为合作进E,合作q程间互相发送的信号UCؓ(f)消息或事件?如果我们对一个消息或事g赋以唯一的消息名Q则我们
可用q程 wait (消息?  表示q程{待合作q程发来的消息,而用q程 signal (消息? 表示向合作进E发送消息?br />(引自癑ֺ癄Q?br />
q程间的同步方式Q?br />Z实现q程互斥地进入自q临界区,操作pȝ中设|专门的同步机制来协调各q程间的q行。所有的同步机制都应遵@下书四条准则Q?br />1Q空闲让q?br />2Q忙则等?br />3Q有限等?br />4Q让权原则。当q程不能q入自己的(f)界区Ӟ应立即释攑֤理机Q以免进E陷?#8220;忙等”状态?br />
1.单CPU (UP)机器利用sleep/wakeup函数对实现同步机制?br />函数sleep是一个内部的内核例程Q它挂v调用它的q程Q直到指定的事g发生为止。这是一个以内核态运行的q程自愿控制权,允许自己被抢占?br />函数wakeup用于发出一个特定事件已l出现的信号Q它使得所有等待该事g的进E被唤醒Qƈ攑֛到运行队列中。事件用一个整数值来表示Q它往往
是该事g相关的内核数据结构的地址?br />
void lock_object( char *flag_ptr)
{
    lock(&object_locking);        //自旋?br />     while (*flag_ptr)
           sleep(flag_ptr);
     *flag_ptr = 1;
    unlock(&object_locking);
}

void unlock_object( char *flag_ptr)
{
    lock( &object_locking );
    *flag_ptr = 0;
    wakeup( flag_ptr);
    unlock( &object_locking );
}

应ؓ(f)wakeup操作没有记忆Q所以wakeup函数必须唤醒在同一事g上睡眠的所有进E。在多CPUpȝ上,即MP上sleep/wakeup机制不v作用?br />
2.SVR4.2 MP 提供了单独的执行q程同步的原语:(x)同步变量?br />因ؓ(f)同步变量不包含状态,所以可以把它们x是sleep/wakeup的一UMP变Ş。相反,所需的Q何状态信息都保存在外部标志或者计数器中?br />同步变量的设计要同自旋锁配合工作?br />
同步变量被声明ؓ(f)sv_tcdQ采用下面的函数可以l它分配I间和进行初始化Q?br />sv_t *SV_ALLOC( int slpflag);
slpflag指定Q如果需要ؓ(f)同步变量分配内存Q那么是否能dq程?br />
回收同步变量可以调用
void SV_DEALLOC( sv_t *svp );

内核希望单独{候的每一个事仉用一个不同的同步变量来表C,q就好比配合sleep如何使用唯一的事件参数?br />void SV_WAIT( sv_t *svp, int pri, lock_t *lockp );

要触发在同步变量上的事gQ可以用下面的函数Q?br />void SV_SIGNAL( sv_t *svp, int flags);
SV_SIGNAL与wakeup的相g处在于,如果没有正在睡眠的进E,那么对q去曄执行q的操作没有记忆Q调用什么也不做?br />SV_SIGNAL只唤醒一个进E。如果要唤醒在事件上睡眠的所有进E,可以用同步变量的下列函数来实玎ͼ(x)
void SV_BROADCAST( sv_t *svp, int flags);

如果在事件被触发之前出现了一个UNIX信号Q那么下面的SV_WAIT变Ş?x)唤醒进E:(x)
bool_t SV_WAIT_SIG( sv_t *svp, int pri, lock_t *lkp );
q回的代码表明发生了什么样的事Ӟ(x)如果出现了一个UNIX信号Q那么它q回FALSE,如果出现了SV_SIGNAL或SV_BROADCAST,那么它返回TRUE.

3.采用信号量的同步
信号量的值初始化?,可以用于进E同步,q样允许通过使用P操作让一个进E等待某个事件发生。既然信号量被初始化?Q那么进E将立即d?br />另一个进E用V操作能够发出信号Q表明事件已l结束。V操作D正等待事件的q程被唤醒,ql进行。因为即使在信号量上没有dq程Q?br />V操作也会(x)l信号量?Q所以在前一个进E能够执行P操作之前出发事g?x)导致进El进行,不必{待。这是一U受Ƣ迎的情形,因ؓ(f)它不需要额外的
协调工作Q就能够处理在等候事件的q程同发信号表明该事件完成的q程之间本来有的竞争条件?br />
q程1                                        q程2
p(s)       /*{待事g*/                    .
                                                  .
                                                  .
                                                V(s) /*触发事g*/


4.利用程q行同步
程Z(f)界资源以?qing)访问或者修改该资源的所有(f)界段提供了互斥机Ӟ它还提供了在使用程的诸q程之间q行同步的手Dc一个管E可以想成是一个装?br />资源的隔间。进E要讉K资源Q它必须首先q入隔间。通过一ơ只允许一个进E进入隔_(d)做C互斥。如果在程已经投入使用的时候,别的q程试图q?br />入它Q那׃(x)被阻塞,直到使用程的进E退出管Eؓ(f)止,或者在与管E关联的事g上等待。每个管E都可能有一个或者更多的事gQ若q进E能够在q些?br />件上{待。进E被dq些事g上,直到在管E内执行的其他进E触发事件ؓ(f)止。根据定义,触发操作只能从管E内部完成?br />

5.利用事g计数q行同步
事g计数是一个非递减的正整数Q在q个数g定义?U操作。操作advance(E)事件计数E?,q叫做出发事件?br />操作await(E,V)致调用q程被阻塞,指导事g计数E的D到V为止。如果在调用await的时候,事g计数的值大于或{于VQ那么进El执行,而不?x)阻塞?br />因ؓ(f)事g是以前触发的。事件计数的当前值可以用read(E)来读取。在创徏事g计数的时候,它被初始化ؓ(f)0Q而且在数g永远不会(x)减少。假定保存事件计数?br />得存储器位置_大,于是事g计数在其整个生命期中Q一直都不会(x)溢出Q通常一?2位的无符h数就够了Q?br />
有关代码CZQ请参见后面的随W?img src ="http://www.shnenglu.com/martin/aggbug/201174.html" width = "1" height = "1" />

martin_yahoo 2013-06-20 13:49 发表评论
]]>
MP操作pȝ内核中自旋锁(spinlock)的实?/title><link>http://www.shnenglu.com/martin/archive/2013/06/08/200878.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Sat, 08 Jun 2013 09:04:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2013/06/08/200878.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/200878.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2013/06/08/200878.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/200878.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/200878.html</trackback:ping><description><![CDATA[在多CPUpȝQ即MPpȝ中,存在ȝ仲裁?br /><br />1. 原子操作<br />从CPU或者I/O讑֤C存储器的单次L者写操作为原子操作?br />q样的操作一旦开始,׃能被pȝ上来自CPU或者I/O讑֤的Q何其他存储操作所中断Q或者受C们的q扰?br /><br />原子变量<br /><br />2. 自旋?Q自旋锁用于短期互斥Q?br />自旋锁得名于q样一个事实,一个进E在{候另一个进E正在用的锁时?x)处于忙{待Qbusy-wait,在一个@环中自旋Q状态?br />typedef int lock_t;<br />void initlock( volatile lock_t * lock_status)<br />{<br />   *lock_status = 0;<br />}<br /><br />int<br />test_and_set(volatile int *addr)<br />{<br />     int old_value;<br />     old_value = swap_atomic(addr, 1);<br />     if (old_value == 0)<br />          return 0;<br />     return 1;<br />} <br /><br />void lock(volatile lock_t *lock_status)<br />{<br />    while (test_and_set( lock_status) == 1)            //被锁定时Q进E在此自旋?br />       ;<br /> }<br />// test_and_set 如果前面的状态不?p?Q否则返?. <br />//如果锁的状态已l是1Q锁已经被占用)Q那么test_and_set函数q回1Qƈ且处理器在@环中自旋Q直到该锁被释放为止。只要把锁的状态设|ؓ(f)0Q就可以释放锁了?br /><br />void <br />unlock(volatile lock_t * lock_status)<br />{<br />   *lock_status =0;<br />}<br /><br />减少寚w的争用可以采用两U办法:(x)<br />W一、内栔R对不同的临界资源使用不同的自旋锁Q防止处理器在没有竞争条件威胁的时候被另一个处理器挂v?br />W二、增强lock和unlock函数Q在上锁的时候屏蔽中断?img src ="http://www.shnenglu.com/martin/aggbug/200878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2013-06-08 17:04 <a href="http://www.shnenglu.com/martin/archive/2013/06/08/200878.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何避免在应用中可能出现的死?/title><link>http://www.shnenglu.com/martin/archive/2013/06/08/200875.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Sat, 08 Jun 2013 06:54:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2013/06/08/200875.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/200875.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2013/06/08/200875.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/200875.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/200875.html</trackback:ping><description><![CDATA[在^时的应用设计中,׃出现多线E(q程Q的q发应用Q以?qing)分布式应用Q比较容易出现死锁现象?br /><br />下面来看一个简单的实例Q?br />有两个独立的链表Q假定用两个独立的锁来保护他们Q以便能够独立的讉K。再假定某个操作要求遍历一个列表所索到的元素必M两个列表中断开q接Q?br />而且必须以一?span style="color: red;">原子操作</span>来完成?br /><br />U程1                                                   |           U程2<br />lock(&lock_a);                                      |        lock(&lock_b);<br />find element to unlink on list a               |        find element to unlink on list b<br />lock(&lock_b);                                      |        lock(&lock_a);<br />unlink element from both lists                |        unlink element from both lists<br />unlock(&lock_b);                                   |        unlock(&lock_a);<br />unlock(&lock_a);                                   |        unlock(&lock_b);<br /><br />可能出现死锁的情c?br />q要求在消除一个元素是必须同时拥有两个列表的锁。对W一个线E要先或得锁lock_a, 然后要或得锁lock_b.<br />W?个线E正好相反,它先或得锁lock_b,然后再获取锁lock_a.<br />如果某一时刻Q第一个线E执行到?find element to unlink on list a, 而第二个U程此时执行Cfind element to unlink on list b, 则这两个U程发生死锁?br />q种死锁UCؓ(f)AB-BA死锁?nbsp;  Q注Q死锁的发生是跟两个U程的执行时序相关的Q例如,W一个线E执行完了所有的q部分代码,U程2才开始执行此D代码,则不?x)发生死锁。)<br /><br />如果某个锁不是递归锁,例如lock_a, 而线E?在应用中对它q行多个调用Q而没有调用解锁操作,也会(x)发生死锁?br />代码CZ如下Q?br />lock(&lock_a);<br />other logic code<br />lock(&lock_a);<br />other logic code<br />unlock(&lock_a);<br />unlock(&lock_a);<br /><br /><span style="color: #0000ff;">防止死锁的办?</span> Z防止发生q类死锁Q所有线E必M相同的次序获得嵌套锁Q即以相同的ơ序获得且同时占有锁?br />可以把上面的代码Ҏ(gu)如下代码来避免死锁:(x)<br />lock(&lock_a);<br />lock(&lock_b);<br />find element to unlink on list a or b<br />unlink element from both lists<br />unlock(&lock_b);<br />unlock(&lock_a);<br /><br />当涉?qing)?个或者更多锁的时候也是如此:(x)只要各线E在获得和释N的时候保持相同的ơ序Q那么就不会(x)出现死锁?br /><img src ="http://www.shnenglu.com/martin/aggbug/200875.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2013-06-08 14:54 <a href="http://www.shnenglu.com/martin/archive/2013/06/08/200875.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用的扩?/title><link>http://www.shnenglu.com/martin/archive/2009/03/20/martin_21.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Fri, 20 Mar 2009 03:41:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2009/03/20/martin_21.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/77288.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2009/03/20/martin_21.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/77288.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/77288.html</trackback:ping><description><![CDATA[实体Q语a内徏的数据类型,开发者定义的cdҎ(gu){)的定义与声明Q实体和指针跟程序设计带来了不同影响Q?br>对于实体或定义,~译器要知道实体真实的物理内存布局Q因此让~译器知道这些信息,q且在程序编译完毕后不能更改Q要x改必重新编译程序.因此如果在系l设计者程序库中运用了inline函数Qƈ且如果应用开发者在应用中用了这个inline函数Q则当后来要对inlineq行修改Ӟ有可能要D应用被重新编译.<br>对于指针Q它的大在特定的机器上是固定的Q在32位机器上Q它的大是32位;?4位机器上Q它的大是64位)Q因此可以改变它的|而不需要重新编译应用,可以改变应用的功能Q?br><br>在面向对象中Q可以通过虚函数指针来延迟特定函数的决{,卌用子cȝ函数Q?br>在C语言中,我们可以通过函数指针来对函数的功能进行推q决{.<br>在C++中,我们也可以通过函数指针Q函数对象)、对象指针来推迟决策Q从而ɽE序的功能更有弹性。例如,在设计模式中的strategy模式中,是通过在contex中包含一个指向strategy的指针来实现的。我们可以定义一个抽象的strategy接口Q然后由各个具体的strategy实现q些接口Q从而在保证应用架构几乎不做M调整下,实现不同的功能。当然在q种实现方式中,我们应该加入strategy的决议者,由它来裁决采用哪一U策略方式。决议者可以采用配|文件、应用的输入{作为决议的依据?br><br>熟?zhn)symbian的hQ很快就?x)发玎ͼ?x)它与symbian中的ECOM架构很相伹{它要求各种strategy的实现方式被包含在共享的DLL中,q由RLibrary::Loard()调用动态蝲?<br>使用定义抽象接口Q然后在各DLL中定义具体的实现Qƈ且动态蝲入,我们可以比较Ҏ(gu)地实现所谓的插g(plugin)。插件的载入取决于配|,或相应的输入?br><br>下面l出在linux和windows上从动态库中查扑֒载入的例?<br>#ifdef WIN32<br>        HINSTANCE hDll;<br>        if(!(hDll = LoadLibrary(VOCALSIP_DLLPATH))) <br>        adapter.m_initFunc = (INIT_PROTOSTACK_FUNC)GetProcAddress( hDll, "InitVocalSipStack");<br>        adapter.m_createFunc = (CREATE_CHANNEL_FUNC)GetProcAddress( hDll, "CreateVocalSipGCChannel");<br>        adapter.m_cleanupFunc = (CLEANUP_PROTOSTACK_FUNC)GetProcAddress( hDll, "CleanupVocalSipStack");<br>#else<br>        void* h_dl = dlopen(VOCALSIP_DLLPATH,RTLD_NOW | RTLD_GLOBAL);<br>        adapter.m_initFunc = (INIT_PROTOSTACK_FUNC)dlsym( h_dl, "InitVocalSipStack");<br>        adapter.m_createFunc = (CREATE_CHANNEL_FUNC)dlsym( h_dl, "CreateVocalSipGCChannel");<br>        adapter.m_cleanupFunc = (CLEANUP_PROTOSTACK_FUNC)dlsym( h_dl, "CleanupVocalSipStack");<br>#endif<br><br> <img src ="http://www.shnenglu.com/martin/aggbug/77288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2009-03-20 11:41 <a href="http://www.shnenglu.com/martin/archive/2009/03/20/martin_21.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mutex与semaphore的区?/title><link>http://www.shnenglu.com/martin/archive/2009/03/18/hello.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Wed, 18 Mar 2009 07:37:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2009/03/18/hello.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/77016.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2009/03/18/hello.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/77016.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/77016.html</trackback:ping><description><![CDATA[Q互?mutext)和旗?semaphore)之间有什么不同?Q这L(fng)问题短而有力,但要回答却相当困难.即有经验的实时操作pȝ(RTOS)用户在区别如何正用mutex和semaphore时也存在着困难Q?br>但这一点很不幸而且很危险,因ؓ(f)无Qq两U原生RTOS中的哪一U被错误使用Q都?x)导致嵌入式pȝ出现意想不到的错误,特别是这些系lؓ(f)有关生命安全的品时.<br>有关mutex和semaphore的荒诞说法是它们是相似的Q甚x可以互换的.正确的事实是管mutex和semaphore在它们的执行上有怼之处Q但是我们还是应该在使用它们时加以区别对待.<br>最普遍Q但也是不正)的答案是Qmutex和semphore非常怼Q它们只有一个区别,那就是semaphores的计数可以超q?. 差不多所有的工程师都能正的理解Qmutex是一个二q制标志Q可以通过它来保执行在代码关键?critical section of code)互相排斥,从而对׃n资源加一保护Q但当他们被要求q一步回{如何用"计算Ҏ(gu)semaphore"的方式时Q大部分工程师的回答如同教U书书一般的L---semaphore用于保护多重同类资源Q?br>通过cL办法Q我们很Ҏ(gu)解释Z?多重资源Q场景是有缺L(fng).如果你认Z个mutex是由操作pȝ拥有的关键值的话,我们可以很容易地个别的mutex比喻是城市咖啡店中一间ʎ室的钥匙Q如果你想用ʎ室,却找不到钥匙Q你必d一个队列中{候.同样圎ͼmutex则协串行化多Q务,以取得全域资源的׃nQƈ且ؓ(f){待队列中的d分配一个静候其循序渐进的位|.<br>但这U简单的资源保护协议q不使用于两间相同ʎ室的情况Q如果把一个semaphore概括Z个mutexQ其能保护两个或更多相同的资源Q那么在我们的比MQ它?yu)p是放着两把相同钥匙的蓝子,你可以用M一把打开M一扇ʎ室的门.<br>因此Qsemaphore本nq不能解军_个相同资源的问题Q咖啡店中的客h可能只知道有一把钥匙,但ƈ不知道哪间ʎ室可用.如果你试图以此方式用semaphoreQ你会(x)发现需要更多的状态信?--它们通常是由不同的mutex所保护的共享资源.<br>正确使用semaphore是ؓ(f)了信号从一Q务传臛_一Q务.mutex意味着取得与释放,使用受保护共享资源的每一ơQ务都是以q样的顺序进行.相比之下Q用semaphore的Q务通常不是发送信P是q入{待状态,不可能同时发生.<br>例如QQ?可能包含E序代码Q当按下Q电(sh)源"(power)按钮Ӟ卛_提出(如发送信h增量)一个特别的semaphore; d2则依据相同的semaphore而用于唤醒显C器. 在这U情况下Q其中一Q务是信号的生产者,另一Q务是信号的消费者.<br><br>用一个例子来做ȝQ首先展C如何用mutexQ?br><font face=Courier size=2><strong>/* Task 1 */<br>mutexWait(mutex_mens_room);<br>// Safely use shared resource<br>mutexRelease(mutex_mens_room);<br><br>/* Task 2 */<br>mutexWait(mutex_mens_room);<br>// Safely use shared resource<br>mutexRelease(mutex_mens_room);<br><br>相应圎ͼ你L采用下列Ҏ(gu)使用semaphore:<br>/* Task 1 - Producer */<br>semPost(sem_power_btn); // Send the signal<br><br>/* Task 2 - Consumer */<br>semPend(sem_power_btn); // Wait for signal<br><br></strong>重要的是Qsemaphores可以被interrupt service routine(ISR)中断服务E序用来向task发送信P发送一个semaphore是一个非d的RTOS行ؓ(f)Qƈ且ISR安全Q因U技术排除了在taskU别的ؓ(f)了是中断不能而引L(fng)错误的可能性,从ISR中发Zh一U嵌入式Y件更加可靠的设计方式.<br><br><a >http://www.embedded.com/columns/guest/210605040?printable=true</a><br><a >http://www.eettaiwan.com/ART_8800557420_676964_NT_a22f6436.HTM</a><br><br></font> <img src ="http://www.shnenglu.com/martin/aggbug/77016.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2009-03-18 15:37 <a href="http://www.shnenglu.com/martin/archive/2009/03/18/hello.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用pȝ中的定时器设?/title><link>http://www.shnenglu.com/martin/archive/2009/03/17/martin_2.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Tue, 17 Mar 2009 09:34:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2009/03/17/martin_2.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/76878.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2009/03/17/martin_2.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/76878.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/76878.html</trackback:ping><description><![CDATA[     摘要: 前一D|_(d)读symbian文档资料Q和Darwin,ICE{开源代码,l常到定时器和定时器事Ӟ故对定时器的实现q行了一些整理,作ؓ(f)MW记Q以防以后忘讎ͼ  <a href='http://www.shnenglu.com/martin/archive/2009/03/17/martin_2.html'>阅读全文</a><img src ="http://www.shnenglu.com/martin/aggbug/76878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2009-03-17 17:34 <a href="http://www.shnenglu.com/martin/archive/2009/03/17/martin_2.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>U程间数据传?/title><link>http://www.shnenglu.com/martin/archive/2009/03/11/martin_1.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Wed, 11 Mar 2009 04:30:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2009/03/11/martin_1.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/76204.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2009/03/11/martin_1.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/76204.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/76204.html</trackback:ping><description><![CDATA[  <p><span>在以前的</span>multi-process<span>E序?/span>,process<span>之间通过׃n内存、操作系l提供的消息对列Q命名管道等不同方式q行数据传递。ؓ(f)了减内存,以及(qing)q程切换时引发的上下文切换的开销Q现在的pȝ一般采?/span>multi-thread <span>工作方式?/span></p> <p><span>?/span>process<span>都有各自独立的地址I间Qƈ且是专有的,因此一?/span>process<span>不能通过指针讉K另一?/span>process<span>中的地址I间。而属于同一</span>process<span>的各</span>thread<span>Q它们共享同一</span>process<span>的地址I间Q因此一?/span>thread<span>可以通过指针讉K另一?/span>thread<span>中的地址。这h们可以在应用中自己定义消息队列,q对消息队列的访问进行管理,化程序ƈ提高性能?/span></p> <p> </p> <p><span>?/span>multi-thread<span>应用中,我们可以使用消息对列来在不同</span>thread<span>之间q行消息传递,q低各</span>thread<span>之间的藕合?/span></p> <p><span>它们之间的关pd下:(x)</span></p> <p><span>生者:(x)向消息队列中放数据的U程?/span></p> <p><span>消费者:(x)从消息队列中取出数据的线E?/span></p> <p> <br> <span>生?/span> ----> <span>消息队列</span> -----><span>消费?/span></p> <p> </p> <p><span>如果应用规定消息队列的最大长度。在寚w列进行控制时Q应该当消息队列满时Q可能要让生产者进行等待,直到消息队列中有新的位置可以攑օ新的消息。当消息队列为空Ӟ应该让消费者进行等待,知道有新的消息被加到消息队列中?/span></p> <p> </p> <p><span>在该模型中有两点需要注意:(x)</span></p> <p><span><span>1Q?/span></span><span>不同生者,消费者同时ƈ发操作消息队列时Q对各操作的串行化。这个问题可以通过寚w列的操作q行加锁来实现。它的实现可以参考另一随W?/span>C++<span>同步锁管理的一U方法》?/span></p> <p><span><span>2Q?/span></span><span>在消息队列ؓ(f)I或满时Q应用程序的处理?/span></p> <p><span>q可以在</span>C++<span>中采?/span>Monitor.<span>?/span>Monitor<span>中对某种条gq行监控?/span></p> <p>Monitor <span>对象可以采取的动作:(x)</span></p> <p>(1)<span>、等待操?/span> wait(long timeout = INFINITE), <span>~省情况下无限等待下厅R?/span></p> <p>(2)<span>、发信号操作</span> signal(long count = 1), <span>~省情况下激zM个正在消息队列上q行{代的线E?/span></p> <p> </p> <p><span>对于</span>Monitor<span>的实玎ͼ可以很简单地用下列两U方式实玎ͼ(x)</span></p> <p><span><span>1?/span></span><span>采用</span>ACE<span>中的</span>ACE_Event, ACE_Thread_Semphore<span>实现?/span></p> <p><span><span>2?/span></span><span>采用</span><span> </span>ICE<span>?/span>Cond<span>实现Q?/span><span> </span><span>?/span>Linux<span>上,</span>Cond<span>实际上是通过</span>pthread_cond_t<span>来实现的?/span></p> <p> </p> <img src ="http://www.shnenglu.com/martin/aggbug/76204.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2009-03-11 12:30 <a href="http://www.shnenglu.com/martin/archive/2009/03/11/martin_1.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针的代码实?/title><link>http://www.shnenglu.com/martin/archive/2009/03/09/frank123.html</link><dc:creator>martin_yahoo</dc:creator><author>martin_yahoo</author><pubDate>Mon, 09 Mar 2009 08:07:00 GMT</pubDate><guid>http://www.shnenglu.com/martin/archive/2009/03/09/frank123.html</guid><wfw:comment>http://www.shnenglu.com/martin/comments/75988.html</wfw:comment><comments>http://www.shnenglu.com/martin/archive/2009/03/09/frank123.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.shnenglu.com/martin/comments/commentRss/75988.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/martin/services/trackbacks/75988.html</trackback:ping><description><![CDATA[<p>前段旉Q写了一点关于智能指针的东西Q有读者反映没有代码比较难懂.现给出源码,q稍微加以解?<br><br>指针cȝ到的基类的定?<br>template<typename T><br>class HandleBase<br>{<br>public:</p> <p>    typedef T element_type;</p> <p>    T* get() const<br>    {<br>        return _ptr;<br>    }<br>   <br>   //重蝲->操作W,q回所指对象的指针.</p> <p>    T* operator->() const<br>    {<br>        if(!_ptr)<br>        {<br>            //<br>            // We don't throw directly NullHandleException here to<br>            // keep the code size of this method to a minimun (the<br>            // assembly code for throwing an exception is much bigger<br>            // than just a function call). This maximises the chances<br>            // of inlining by compiler optimization.<br>            //<br>            throwNullHandleException(__FILE__, __LINE__);<br>        }</p> <p>        return _ptr;<br>    }<br><br>//  通过指针获取所指对象的引用.</p> <p>    T& operator*() const<br>    {<br>        if(!_ptr)<br>        {<br>            //<br>            // We don't throw directly NullHandleException here to<br>            // keep the code size of this method to a minimun (the<br>            // assembly code for throwing an exception is much bigger<br>            // than just a function call). This maximises the chances<br>            // of inlining by compiler optimization.<br>            //<br>            throwNullHandleException(__FILE__, __LINE__);<br>        }</p> <p>        return *_ptr;<br>    }</p> <p>    operator bool() const<br>    {<br>        return _ptr ? true : false;<br>    }</p> <p>    void swap(HandleBase& other)<br>    {<br>        std::swap(_ptr, other._ptr);<br>    }</p> <p>    T* _ptr;</p> <p>private:</p> <p>    void throwNullHandleException(const char *, int) const;<br>};</p> <p>......</p> <p><br>// 指针cd?/p> <p>template<typename T><br>class Handle : public HandleBase<T><br>{<br>public:</p> <p>    Handle(T* p = 0)               //指针的构造函?br>    {<br>        this->_ptr = p;</p> <p>        if(this->_ptr)<br>        {<br>            this->_ptr->__incRef();         //在构造函C增加所指对象的引用计数<br>        }<br>    }</p> <p>    template<typename Y>                  //拯构造函?br>    Handle(const Handle<Y>& r)<br>    {<br>        this->_ptr = r._ptr;</p> <p>        if(this->_ptr)<br>        {<br>            this->_ptr->__incRef();   //在构造函C增加所指对象的引用计数<br>        }<br>    }</p> <p>    Handle(const Handle& r)         //拯构造函?br>    {<br>        this->_ptr = r._ptr;</p> <p>        if(this->_ptr)<br>        {<br>            this->_ptr->__incRef();    //在构造函C增加所指对象的引用计数<br>        }<br>    }</p> <p>    ~Handle()<br>    {<br>        if(this->_ptr)<br>        {<br>            this->_ptr->__decRef();      //在析构函C减少所指对象的引用计数<br>        }<br>    }<br><br>// 重蝲=操作W? 要注意所有权 (卻I对原实例的处?.</p> <p>    Handle& operator=(T* p)         <br>    {<br>        if(this->_ptr != p)<br>        {<br>            if(p)<br>            {<br>                p->__incRef();      //增加新指对象的引用计?br>            }</p> <p>            T* ptr = this->_ptr;<br>            this->_ptr = p;</p> <p>            if(ptr)<br>            {<br>                ptr->__decRef();   //减少原来所指对象的引用计数<br>            }<br>        }<br>        return *this;<br>    }</p> <p>    template<typename Y><br>    Handle& operator=(const Handle<Y>& r)<br>    {<br>        if(this->_ptr != r._ptr)<br>        {<br>            if(r._ptr)<br>            {<br>                r._ptr->__incRef();   //增加新指对象的引用计?br>            }</p> <p>            T* ptr = this->_ptr;<br>            this->_ptr = r._ptr;</p> <p>            if(ptr)<br>            {<br>                ptr->__decRef();      //减少原来所指对象的引用计数<br>            }<br>        }<br>        return *this;<br>    }</p> <p>    Handle& operator=(const Handle& r)<br>    {<br>        if(this->_ptr != r._ptr)<br>        {<br>            if(r._ptr)<br>            {<br>                r._ptr->__incRef();            //增加新指对象的引用计?br>            }</p> <p>            T* ptr = this->_ptr;<br>            this->_ptr = r._ptr;</p> <p>            if(ptr)<br>            {<br>                ptr->__decRef();            //减少原来所指对象的引用计数<br>            }<br>        }<br>        return *this;<br>    }</p> <p> 跟智能指针配合用的对象Q要能够跟指针智能配合用,q些对象应该是从下列cȝzcȝ实例Q?br>class SimpleShared<br>{<br>public:</p> <p>    SimpleShared();<br>    SimpleShared(const SimpleShared&);</p> <p>    virtual ~SimpleShared()<br>    {<br>    }</p> <p>    SimpleShared& operator=(const SimpleShared&)<br>    {<br>        return *this;<br>    }</p> <p>    void __incRef()<br>    {<br>        assert(_ref >= 0);<br>        ++_ref;<br>    }</p> <p>    void __decRef()<br>    {<br>        assert(_ref > 0);<br>        if(--_ref == 0)               // 如果引用计数?,则摧毁对象本w.<br>        {<br>            if(!_noDelete)<br>            {<br>                _noDelete = true;<br>                delete this;<br>            }<br>        }<br>    }</p> <p>    int __getRef() const<br>    {<br>        return _ref;<br>    }</p> <p>    void __setNoDelete(bool b)<br>    {<br>        _noDelete = b;<br>    }</p> <p>private:</p> <p>    int _ref;<br>    bool _noDelete;<br>};</p> <p>class Shared<br>{<br>public:</p> <p>    Shared();<br>    Shared(const Shared&);</p> <p>    virtual ~Shared()<br>    {<br>    }</p> <p>    Shared& operator=(const Shared&)<br>    {<br>        return *this;<br>    }</p> <p>    virtual void __incRef();<br>    virtual void __decRef();<br>    virtual int __getRef() const;<br>    virtual void __setNoDelete(bool);</p> <p>protected:</p> <p>#if defined(_WIN32)<br>    LONG _ref;<br>#elif defined(ICE_HAS_ATOMIC_FUNCTIONS)<br>    volatile int _ref;<br>#else<br>    int _ref;<br>    Mutex _mutex;<br>#endif<br>    bool _noDelete;<br>};<br><br></p> <img src ="http://www.shnenglu.com/martin/aggbug/75988.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/martin/" target="_blank">martin_yahoo</a> 2009-03-09 16:07 <a href="http://www.shnenglu.com/martin/archive/2009/03/09/frank123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.gmlu.cn" target="_blank">þþƷĻ̾</a>| <a href="http://www.hoay.com.cn" target="_blank">ƷƵþþ</a>| <a href="http://www.funziot.cn" target="_blank">ҹƵþþþһ </a>| <a href="http://www.s36mbtm.cn" target="_blank">þˬˬAVƬ</a>| <a href="http://www.shisanshui.cn" target="_blank">þ޾Ʒһ</a>| <a href="http://www.zequndesign.com.cn" target="_blank">Ʒһþ</a>| <a href="http://www.yx177.cn" target="_blank">þþþAVרJN </a>| <a href="http://www.huameizc.cn" target="_blank">ۺϾþþ</a>| <a href="http://www.g24w.cn" target="_blank">ƬҹƬþ</a>| <a href="http://www.yangyongfu.com.cn" target="_blank">޾ƷҹVAþó</a>| <a href="http://www.rentieyou.cn" target="_blank">aaaƷþþùƬ</a>| <a href="http://www.cngit13.cn" target="_blank">þþþƷþþþþ</a>| <a href="http://www.gzlinquan.cn" target="_blank">þþþ뾫Ʒ</a>| <a href="http://www.fjprxr.cn" target="_blank">Ʒ99þþþ</a>| <a href="http://www.6nz.com.cn" target="_blank">޼VëƬþþƷ </a>| <a href="http://www.philadelphiausa.cn" target="_blank">þۺϳDž</a>| <a href="http://www.youxi011.cn" target="_blank">þùӾƷŮ</a>| <a href="http://www.z9559.cn" target="_blank">ƷһþþƷɬ</a>| <a href="http://www.cube4you.cn" target="_blank">þþƷ69Ʒ</a>| <a href="http://www.baiduotui.cn" target="_blank">޹˾þһþ</a>| <a href="http://www.cixivip.cn" target="_blank">þþƷۺɫ </a>| <a href="http://www.wkbxdlr.cn" target="_blank">ձƷþþĻ</a>| <a href="http://www.vfpo.cn" target="_blank">պþ</a>| <a href="http://www.ichz.cn" target="_blank">þĻƷһ</a>| <a href="http://www.hfoa.com.cn" target="_blank">996þùƷ߹ۿ</a>| <a href="http://www.andz77.cn" target="_blank">avպƷþþþþa</a>| <a href="http://www.xh68.cn" target="_blank">þòӰ</a>| <a href="http://www.v0008.cn" target="_blank">91Ʒɫ۾þ</a>| <a href="http://www.dlucai.cn" target="_blank">Ʒþþþþ޾Ʒ</a>| <a href="http://www.dq97.cn" target="_blank">þþþseɫ͵͵޾Ʒav</a>| <a href="http://www.npoq.cn" target="_blank">Ƶþ</a>| <a href="http://www.sj0524.cn" target="_blank">97þþƷˬ</a>| <a href="http://www.txt115.cn" target="_blank">þùƷӰԺ</a>| <a href="http://www.wyj442.cn" target="_blank">ҹavþþþ</a>| <a href="http://www.gaguni.cn" target="_blank">޾Ʒרþͬ</a>| <a href="http://www.zqdiary.cn" target="_blank">ľƷþþþùַ </a>| <a href="http://www.metropolojinjianghotel.cn" target="_blank">Ʒ˿þþþþò</a>| <a href="http://www.ab1987.cn" target="_blank">þþþþþĻ</a>| <a href="http://www.lyfulinmen.com.cn" target="_blank">˾þþƷһ</a>| <a href="http://www.liuyunying.cn" target="_blank">þþþþþþþþѾƷ </a>| <a href="http://www.xopa.cn" target="_blank">ھƷþþþþ鶹 </a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>