<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Unix / Linux on kamuszhou&#39;s blog</title>
    <link>https://ykyi.net/categories/unix-/-linux/</link>
    <description>Recent content in Unix / Linux on kamuszhou&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Fri, 23 Nov 2018 08:45:32 +0000</lastBuildDate>
    <atom:link href="https://ykyi.net/categories/unix-/-linux/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>netstat -s统计输出的所有字段详细解释</title>
      <link>https://ykyi.net/?p=1557/</link>
      <pubDate>Fri, 23 Nov 2018 08:45:32 +0000</pubDate>
      <guid>https://ykyi.net/?p=1557/</guid>
      <description>&lt;p&gt;今天工作上碰到一个问题需要知道udp的丢包数据。实际上我不相信能简单地得到udp的丢包精确数据。理由是，网卡负载太高时有些包连网卡都没收到，根本不可能来得及汇报给内核。另外，如果是路由器把udp丢了，那udp的目的端机器当然更不可能感知到有丢包了。&lt;/p&gt;
&lt;p&gt;这时，同事说netstat -us (–statistic)可以看到udp的丢包。这里的u选项指的是只展示udp相关的统计，s选项自然表示的是统计了。如果不用u选项，则出显示所有统计数据。下面是我的机器上的输出。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;Ip:
    203440255187 total packets received
    0 forwarded
    0 incoming packets discarded
    201612429535 incoming packets delivered
    1064529177 requests sent out
    15 fragments dropped after timeout
    3058122492 reassemblies required
    1230296840 packets reassembled ok
    15 packet reassembles failed
Icmp:
    14869220 ICMP messages received
    3965512 input ICMP message failed.
    ICMP input histogram:
        destination unreachable: 6054246
        timeout in transit: 687
        echo requests: 8570532
        echo replies: 243755
    12913011 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 4097869
        time exceeded: 5
        echo request: 244605
        echo replies: 8570532
IcmpMsg:
        InType0: 243755
        InType3: 6054246
        InType8: 8570532
        InType11: 687
        OutType0: 8570532
        OutType3: 4097869
        OutType8: 244605
        OutType11: 5
Tcp:
    111681768 active connections openings
    4186820 passive connection openings
    24951865 failed connection attempts
    55064041 connection resets received
    275 connections established
    1033901799 segments received
    1776166765 segments send out
    12156205 segments retransmited
    6705 bad segments received.
    106348033 resets sent
Udp:
    198894689917 packets received
    472986510 packets to unknown port received.
    1146976531 packet receive errors
    116750744 packets sent
    110301286 receive buffer errors
    0 send buffer errors
UdpLite:
TcpExt:
    423 invalid SYN cookies received
    693 packets pruned from receive queue because of socket buffer overrun
    19 packets pruned from receive queue
    11309370 TCP sockets finished time wait in fast timer
    106 packets rejects in established connections because of timestamp
    10210477 delayed acks sent
    20811 delayed acks further delayed because of locked socket
    Quick ack mode was activated 8856 times
    17118697 packets directly queued to recvmsg prequeue.
    301717551 bytes directly in process context from backlog
    152118951904 bytes directly received in process context from prequeue
    104771733 packet headers predicted
    15179703 packets header predicted and directly queued to user
    218747377 acknowledgments not containing data payload received
    102637644 predicted acknowledgments
    7293 times recovered from packet loss by selective acknowledgements
    Detected reordering 40 times using FACK
    Detected reordering 27 times using SACK
    Detected reordering 1088 times using time stamp
    476 congestion windows fully recovered without slow start
    5287 congestion windows partially recovered using Hoe heuristic
    236 congestion windows recovered without slow start by DSACK
    151673 congestion windows recovered without slow start after partial ack
    1 timeouts after reno fast retransmit
    4 timeouts after SACK recovery
    10540 timeouts in loss state
    7232 fast retransmits
    649 forward retransmits
    1871 retransmits in slow start
    11612658 other TCP timeouts
    TCPLossProbes: 93185
    TCPLossProbeRecovery: 14667
    2431 packets collapsed in receive queue due to low socket buffer
    8814 DSACKs sent for old packets
    3350 DSACKs received
    1 DSACKs for out of order packets received
    90851 connections reset due to unexpected data
    214 connections reset due to early user close
    352 connections aborted due to timeout
    TCPDSACKIgnoredNoUndo: 1571
    TCPSpuriousRTOs: 7
    TCPSackShifted: 94
    TCPSackMerged: 131
    TCPSackShiftFallback: 21183
    TCPTimeWaitOverflow: 1876775
    TCPRcvCoalesce: 15711184
    TCPOFOQueue: 3194
    TCPChallengeACK: 2337394
    TCPSYNChallenge: 13608
    TCPSpuriousRtxHostQueues: 1982796
IpExt:
    InBcastPkts: 46443933
    InOctets: 44312451521655
    OutOctets: 1915626725817
    InBcastOctets: 6827280595
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;喂，要是转载文章。麻烦贴一下出处 ykyi.net 采集爬虫把链接也抓走&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>服务器端的tcp有大量TIME_WAIT怎么办</title>
      <link>https://ykyi.net/?p=1409/</link>
      <pubDate>Fri, 20 Oct 2017 06:03:06 +0000</pubDate>
      <guid>https://ykyi.net/?p=1409/</guid>
      <description>&lt;p&gt;公司的群里讨论tcp的TIME_WAIT的问题。TIME_WAIT这个状态可是面试时经常问的知识点啊。&lt;br&gt;
讨论的问题是：有一个服务器，它对外网提供服务，同时它作为客户端连接很多后端的其它服务器。这位同事连后端其它服务器时用了短tcp连接。结果出现了大量的tcp TIME_WAIT状态，吞吐量上不去，怎么办？&lt;/p&gt;
&lt;p&gt;先说结论：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果该服务器要处理外网IP的入流量，那最好的办法应该是用tcp长链接改造它与后端服务器的连接。如果用中间件，比如上zeromq那更省心了。&lt;/li&gt;
&lt;li&gt;如果不想做改动，并且在应用层确认已经交互已经完成，则可以用shutdown()直接发RST结束tcp会话，而不走正常的4次挥手。查阅shutdown系统调用的文档获知如何发RST。&lt;/li&gt;
&lt;li&gt;如果该服务器不需要处理处网IP请求的话，那么，启用port reuse 即打开net.ipv4.tcp_tw_reuse不会有太大问题(如果处理外网请求就有问题，和NAT相关，见&lt;a href=&#34;https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux&#34;&gt;https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux&lt;/a&gt;)，或者更好的，把/proc/sys/net/ipv4/tcp_fin_timeout改小，改成1或者2。让TIME_WAIT只保持很短的时间。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;首先，需要知道一个tcp会话由 src_ip, src_port, dest_ip, dest_port 四元组确定。&lt;br&gt;
我们公司的IDC环境中， 上述的服务器作为客户端再发起tcp连接联后端服务器，则 src_ip 固定了， dest_ip是后端服务器的ip, port是后端服务器监听端口。这样只有 src_port 是可变化的，但port只有16个bits还不能用well-known ports，这样就更少了。&lt;/p&gt;
&lt;p&gt;再说，主动关闭时，tcp连接需要进入TIME_WAIT状态，保持两倍MSL时长，是为了处理两种情况：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;让当前这个会话的迷路包在网路中消失。这样不会干扰到新建的会话。&lt;/li&gt;
&lt;li&gt;确保主动关闭方的FIN-ACK包，如果丢失的话，还能重发。&lt;br&gt;
1981年的TCP RFC上把MSL设成两分钟，https://tools.ietf.org/html/rfc793&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Maximum Segment Lifetime, the time a TCP segment can exist in&lt;br&gt;
the internetwork system. Arbitrarily defined to be 2 minutes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;MSL设置这么长，因为以前的网络环境差啊。不过现在因为移动互联网，比较差的网络状态也是非常常见的。但RFC允许实现方减少MSL值。事实上linux的MSL写死在代码中为1分钟并且不可在运行期配置。&lt;br&gt;
如果tcp连接的双方都在性能高速稳定的内网中，这个MSL就太长了。&lt;/p&gt;
&lt;p&gt;调试时，还发现如果port用完了，connect的时候内核代码会用自旋锁忙等检查port资源。有linux内核开发基础的开发者都知道spin_lock的时候是不会让出cpu的，于是cpu全被spin_lock吃掉了。一直要等到有port被释放。再后来又发现，如果scoket没有设定SO_REUSEADDR选项，则connect()系统调用会返回EADDRINUSE。&lt;/p&gt;
&lt;p&gt;tcp的连接双方都是确定且长期的，用什么tcp短连接呢？？改造吧~~~&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux 如何知道有哪些硬件，该装哪个驱动</title>
      <link>https://ykyi.net/?p=1255/</link>
      <pubDate>Wed, 23 Jul 2014 03:12:12 +0000</pubDate>
      <guid>https://ykyi.net/?p=1255/</guid>
      <description>&lt;p&gt;Linux 如何知道有哪些硬件，该装哪个驱动&lt;/p&gt;
&lt;p&gt;公司明文不准安装虚拟机了，被查到就是死罪。于是我在自己的笔记本上安装了Debian Linux。&lt;/p&gt;
&lt;p&gt;结果无线网卡识别不了~~&lt;/p&gt;
&lt;p&gt;次奥~&lt;/p&gt;
&lt;p&gt;怎么破呢？&lt;/p&gt;
&lt;p&gt;这么破:&lt;/p&gt;
&lt;pre style=&#34;margin-top: 0px; margin-bottom: 10px; padding: 5px; border: 0px; font-size: 13px; vertical-align: baseline; overflow: auto; width: auto; max-height: 600px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; background-color: rgb(238, 238, 238); word-wrap: normal; line-height: 20px;&#34;&gt;&lt;code style=&#34;margin: 0px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; color: rgb(34, 34, 34); white-space: inherit;&#34;&gt;# lspci
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&#34;margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15.333333015441895px; vertical-align: baseline; clear: both; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; line-height: 20px;&#34;&gt;
  该命令列出了所有PCI总线上的硬件设备，稍微看看就能看到自己的无线网卡了。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>怎么知道gcc搜索头文件的路径</title>
      <link>https://ykyi.net/?p=1187/</link>
      <pubDate>Thu, 13 Feb 2014 08:02:43 +0000</pubDate>
      <guid>https://ykyi.net/?p=1187/</guid>
      <description>&lt;p&gt;&lt;font size=&#34;3&#34;&gt;每个C/C++程序员都知道，对于#include directive，一般，以双引号引用的头文件是程序号自定义的头文件。而用尖括号引用的头文件是系统的头文件或其它库文件。&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size=&#34;3&#34;&gt;更详细的，编译器先在当前目录找用双引号&amp;quot;&amp;ldquo;引用的头文件，如果找不到再到系统目录找这个头文件。而对于尖括号引用的头文件，编译器就只在系统文件中搜索了。&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size=&#34;3&#34;&gt;那么，到底是在哪些目录中搜索头文件呢？&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size=&#34;3&#34;&gt;可以用cpp查看，如下：&lt;/font&gt;&lt;/p&gt;
&lt;pre class=&#34;brush:other&#34;&gt;root@vicarious:/home/kamus/projs/horoscope/boost# cpp -v
Using built-in specs.
COLLECT_GCC=cpp
Target: x86_64-linux-gnu
Thread model: posix
gcc version 4.7.2 (Debian 4.7.2-5)
COLLECT_GCC_OPTIONS=&amp;#39;-E&amp;#39; &amp;#39;-v&amp;#39; &amp;#39;-mtune=generic&amp;#39; &amp;#39;-march=x86-64&amp;#39;
 /usr/lib/gcc/x86_64-linux-gnu/4.7/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu - -mtune=generic -march=x86-64
ignoring nonexistent directory &#34;/usr/local/include/x86_64-linux-gnu&#34;
ignoring nonexistent directory &#34;/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/include&#34;
#include &#34;...&#34; search starts here:
#include &amp;lt;...&amp;gt; search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.7/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:16px;&#34;&gt;一般编写makefile时给gcc指定 -I选项，-I的参数代表的目录是搜索系统头文件时使用的目录。可以试试# cpp -I/tmp -v &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:16px;&#34;&gt;/tmp目录会被添加为搜索系统头文件时的第一个目录。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:16px;&#34;&gt;如果想要添加搜索双引号&amp;quot;&amp;ldquo;引用的头文件使用的目录呢，用 &lt;strong&gt;-iquote&lt;/strong&gt; 选项指定更多的目录。&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux的环境变量LD_DEBUG调试so的加载</title>
      <link>https://ykyi.net/?p=1185/</link>
      <pubDate>Wed, 12 Feb 2014 07:20:25 +0000</pubDate>
      <guid>https://ykyi.net/?p=1185/</guid>
      <description>&lt;p&gt;&lt;em style=&#34;line-height: 1.6em;&#34;&gt;一个稍微有经验的&lt;/em&gt;&lt;em style=&#34;line-height: 1.6em;&#34;&gt;Linux&lt;/em&gt;&lt;em style=&#34;line-height: 1.6em;&#34;&gt;程序员都知道使用&lt;/em&gt;&lt;em style=&#34;line-height: 1.6em;&#34;&gt;LD_LIBRARY_PATH&lt;/em&gt;&lt;span style=&#34;line-height: 1.6em;&#34;&gt; 来临时设置加载器搜索动态链接库so的路径顺序。但另一个不为人知的环境变量是LD_DEBUG。这个变量可以提供非常详细的加载动态链接库的信息。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;可以把LD_DEBUG设成以下值：&lt;/p&gt;
&lt;p&gt;export LD_DEBUG=files     # 显示库的依赖性和加载的顺序&lt;/p&gt;
&lt;p&gt;export LD_DEBUG=bindings  # 符号绑定&lt;/p&gt;
&lt;p&gt;export LD_DEBUG=libs   # 显示加载器查找库时使用的路径的顺序&lt;/p&gt;
&lt;p&gt;export LD_DEBUG=versions  # 版本依赖性&lt;/p&gt;
&lt;p&gt;export LD_DEBUG=help  # LD_DEBUG的帮助信息&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;试一下把LD_DEBUG设成以上值之一，再随便运行一个程序试试。&lt;/p&gt;
&lt;p&gt;一个试验：&lt;/p&gt;
&lt;pre class=&#34;brush:other&#34;&gt;root@vicarious:/home/kamus/projs/horoscope/bins# export LD_DEBUG=libs

root@vicarious:/home/kamus/projs/horoscope/bins# vim my.conf

     24360:   find library=libm.so.6 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libm.so.6

     24360:

     24360:   find library=libtinfo.so.5 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libtinfo.so.5

     24360:

     24360:   find library=libselinux.so.1 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libselinux.so.1

     24360:

     24360:   find library=libacl.so.1 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libacl.so.1

     24360:

     24360:   find library=libgpm.so.2 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/usr/lib/x86_64-linux-gnu/libgpm.so.2

     24360:

     24360:   find library=libc.so.6 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libc.so.6

     24360:

     24360:   find library=libdl.so.2 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libdl.so.2

     24360:

     24360:   find library=libattr.so.1 [0]; searching

     24360:   search cache=/etc/ld.so.cache

     24360:     trying file=/lib/x86_64-linux-gnu/libattr.so.1&lt;/pre&gt;
&lt;p&gt;copyright ykyi.net&lt;/p&gt;</description>
    </item>
    <item>
      <title>configure –prefix 和 make install DESTDIR= 还有make install prefix 什么区别</title>
      <link>https://ykyi.net/?p=1116/</link>
      <pubDate>Mon, 06 Jan 2014 02:19:04 +0000</pubDate>
      <guid>https://ykyi.net/?p=1116/</guid>
      <description>&lt;p&gt;./configure –prefix=*&lt;/p&gt;
&lt;p&gt;确定了程序会被包装到哪里，以及，程序将在什么位置搜寻运行需要用到的相关的文件。如果你在一台机器上编译，然后仍然在这台机器上运行，那使用configure –prefix就是你想要的了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;make install DESTDIR=*&lt;/p&gt;
&lt;p&gt;把程序安装到一个临时用的目录，这个目录不是程序以后将要运行的目录。例如，这个功能被deb包的打包人员使用。打包人员使用此功能时，并不真正把程序安装到–prefix指定的目录下。因为他可能已经安装了不同的版本，他不想搞乱他的环境，或者他没有boot权限，没有办法把程序安装到/bin,/sbin之类目录。 –prefix=/usr，让程序运行时认为被安装在/usr，然后make install DESTDIR=debian/tmp则实际把程序安装到debian/tmp。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;make install prefix=/foo/bar/baz&lt;/p&gt;
&lt;p&gt;和 make install DESTDIR的区别在于，前者不会创建prefix后面指定的所有目录层级，而DESTDIR会。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;p&gt;./configure –prefix=usr/local &amp;amp;&amp;amp; make &amp;amp;&amp;amp; sudo make install prefix=/usr/local/stow/foo 会把程序安装在/usr/local/stow/bin目录下。&lt;/p&gt;
&lt;p&gt;而: make install DESTDIR=/usr/local/stow/foo，则把程序安装在/usr/local/stow/foo/usr/local/bin下面。&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;color: rgb(0, 0, 0); font-family: Verdana, Geneva, sans-serif; font-size: 16px; line-height: 22px; background-color: rgb(244, 244, 244);&#34;&gt;copyright ykyi.net&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>为什么dump生成core文件大小是0</title>
      <link>https://ykyi.net/?p=1099/</link>
      <pubDate>Wed, 25 Dec 2013 05:17:38 +0000</pubDate>
      <guid>https://ykyi.net/?p=1099/</guid>
      <description>&lt;p&gt;今天程序崩溃了，但是生成的core文件大小是0.&lt;/p&gt;
&lt;p&gt;用ulimit -c 查看生成core文件的大小限制是无限unlimited.&lt;/p&gt;
&lt;p&gt;也不是磁盘大小和写入权限的问题。&lt;/p&gt;
&lt;p&gt;但究竟是什么问题呢？&lt;/p&gt;
&lt;p&gt;捣了半天终于搞明白，原来是文件系统造成的。&lt;/p&gt;
&lt;p&gt;我是在vmware的虚拟机的debian linux上运行程序，文件系统用的是从host机windows 7挂载到/mnt/hgfs的windows的NTFS文件系统。&lt;/p&gt;
&lt;p&gt;后来我把程序转移动linux自己的文件系统，崩溃的时候就生成正常的core dump文件了。&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;color: rgb(0, 0, 0); font-family: Verdana, Geneva, sans-serif; font-size: 16px; line-height: 22px; background-color: rgb(244, 244, 244);&#34;&gt;copyright ykyi.net&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>如何从windows远程调试linux程序。</title>
      <link>https://ykyi.net/?p=1059/</link>
      <pubDate>Wed, 04 Dec 2013 03:29:06 +0000</pubDate>
      <guid>https://ykyi.net/?p=1059/</guid>
      <description>&lt;p class=&#34;p0&#34; data-mce-style=&#34;margin-top: 0pt; margin-bottom: 0pt; padding: 0px; border: 0px; font-size: 12px; font-family: Verdana, Geneva, sans-serif; vertical-align: baseline; line-height: 12pt; color: #000000; background-color: #f4f4f4;&#34; style=&#34;unicode-bidi: embed; margin: 0pt 0px; padding: 0px; border: 0px; font-family: Verdana, Geneva, sans-serif; vertical-align: baseline; line-height: 12pt; color: rgb(0, 0, 0); background-color: rgb(244, 244, 244);&#34;&gt;
  &lt;span data-mce-style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; font-size: 16px; vertical-align: baseline;&#34; style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; font-size: 16px; vertical-align: baseline;&#34;&gt;用gdb在远程linux机器上调试程序实在太不方便了。于是想到用eclipse的GUI调试。下面介绍&lt;span data-mce-style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; font-size: 16px; vertical-align: baseline;&#34; style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; vertical-align: baseline;&#34;&gt;如何从windows&lt;span data-mce-style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; font-size: 16px; vertical-align: baseline;&#34; style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; vertical-align: baseline;&#34;&gt;远程调试&lt;/span&gt;&lt;span data-mce-style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; font-size: 16px; vertical-align: baseline;&#34; style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; vertical-align: baseline;&#34;&gt;linux&lt;/span&gt;&lt;span data-mce-style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; font-size: 16px; vertical-align: baseline;&#34; style=&#34;margin: 0px; padding: 0px; border: 0px; font-weight: inherit; font-style: inherit; vertical-align: baseline;&#34;&gt;程序。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>packet captured和packet received by filter到底有什么区别</title>
      <link>https://ykyi.net/?p=1047/</link>
      <pubDate>Fri, 22 Nov 2013 05:22:58 +0000</pubDate>
      <guid>https://ykyi.net/?p=1047/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    我用的是linux.&amp;nbsp;结论是 packet received by filter是tcpdump从内核中拿到的且匹配命令上行指定的过滤条件的包， packet captured是经由pcap_loop, 或&amp;nbsp;&lt;span style=&#34;font-size: 13px;&#34;&gt;pcap_dispatch 或 pcap_next，把包交给回调处理过的包的数量。这两个数字的差值是tcpdump抓到的，还来不及处理的包。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;span style=&#34;font-size: 13px;&#34;&gt;下面是讨论的一些细节:&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    /////////////
  &lt;/p&gt;
  &lt;p&gt;
    tcpdump的最后输出.&amp;nbsp;592个包captured,&amp;nbsp;&amp;nbsp;1184个包received&amp;nbsp;by&amp;nbsp;filter。。这个差值是不是表示有多少包tcpdump没来得及处理.
  &lt;/p&gt;
  &lt;p&gt;
    man&amp;nbsp;tcpdump上写得好复杂，received&amp;nbsp;by&amp;nbsp;filter的数字取决于OS&amp;#8230;&amp;nbsp;1.&amp;nbsp;包匹配不匹配命令行上指定的filter都算，如果匹配，有没有被tcpdump读出都算..&amp;nbsp;&amp;nbsp;&amp;nbsp;2.&amp;nbsp;只有匹配命令行上指定的filter的包才算，有没有被tcpdump读出都算.&amp;nbsp;&amp;nbsp;&amp;nbsp;3.&amp;nbsp;只有匹配filter才算，只有被tcpdump读出才算.
  &lt;/p&gt;
  &lt;p&gt;
    我的理解是：如果是第3种，那captured的数字和received&amp;nbsp;by&amp;nbsp;filter的数字就是一样的。&amp;nbsp;第2种的差值表示tcpdump来不及处理的包数量，理想状态上差值能为0.&amp;nbsp;&amp;nbsp;&amp;nbsp;第1种情况，基本上总是有差值。
  &lt;/p&gt;
  &lt;p&gt;
    我猜测我用的linux上应该是第2种情况.&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    wangbin579()&amp;nbsp;10:18:54&amp;nbsp;&lt;br /&gt; 应该是匹配的才算received&amp;nbsp;by&amp;nbsp;filter，但奇怪的是，为啥你的系统，captured怎么少？&lt;br /&gt; wangbin579()&amp;nbsp;10:19:30&amp;nbsp;&lt;br /&gt; [root@hz0-12-157&amp;nbsp;~]#&amp;nbsp;tcpdump&amp;nbsp;-i&amp;nbsp;any&amp;nbsp;tcp&amp;nbsp;and&amp;nbsp;port&amp;nbsp;36524&amp;nbsp;or&amp;nbsp;3306&amp;nbsp;-w&amp;nbsp;all.pcap&lt;br /&gt; tcpdump:&amp;nbsp;listening&amp;nbsp;on&amp;nbsp;any,&amp;nbsp;link-type&amp;nbsp;LINUX_SLL&amp;nbsp;(Linux&amp;nbsp;cooked),&amp;nbsp;capture&amp;nbsp;size&amp;nbsp;65535&amp;nbsp;bytes&lt;br /&gt; 10757&amp;nbsp;packets&amp;nbsp;captured&lt;br /&gt; 11171&amp;nbsp;packets&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter&lt;br /&gt; 334&amp;nbsp;packets&amp;nbsp;dropped&amp;nbsp;by&amp;nbsp;kernel&lt;br /&gt; wangbin579()&amp;nbsp;10:20:07&amp;nbsp;&lt;br /&gt; 我们这边系统，基本可以认为packets&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter=packets&amp;nbsp;captured&amp;nbsp;+&amp;nbsp;packets&amp;nbsp;dropped&amp;nbsp;by&amp;nbsp;kernel
  &lt;/p&gt;
  &lt;p&gt;
    siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:23:38&amp;nbsp;&lt;br /&gt; /home&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;25&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-14656.png&#34; width=&#34;25&#34; /&gt;mus/tmp&amp;nbsp;#&amp;nbsp;time&amp;nbsp;time&amp;nbsp;tcpdump&amp;nbsp;-i&amp;nbsp;tunl0:1&amp;nbsp;&amp;nbsp;-w&amp;nbsp;tmp&lt;br /&gt; tcpdump:&amp;nbsp;listening&amp;nbsp;on&amp;nbsp;tunl0:1,&amp;nbsp;link-type&amp;nbsp;RAW&amp;nbsp;(Raw&amp;nbsp;IP),&amp;nbsp;capture&amp;nbsp;size&amp;nbsp;96&amp;nbsp;bytes&lt;br /&gt; 19508&amp;nbsp;packets&amp;nbsp;captured&lt;br /&gt; 39021&amp;nbsp;packets&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter&lt;br /&gt; 0&amp;nbsp;packets&amp;nbsp;dropped&amp;nbsp;by&amp;nbsp;kernel&lt;br /&gt; 0.01user&amp;nbsp;0.02system&amp;nbsp;0:17.04elapsed&amp;nbsp;0%CPU&amp;nbsp;(0avgtext+0avgdata&amp;nbsp;0maxresident)k&lt;br /&gt; 0inputs+0outputs&amp;nbsp;(0major+506minor)pagefaults&amp;nbsp;0swaps
  &lt;/p&gt;
  &lt;p&gt;
    real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m17.139s&lt;br /&gt; user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m0.012s&lt;br /&gt; sys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m0.028s&lt;br /&gt; wangbin579()&amp;nbsp;10:26:03&amp;nbsp;&lt;br /&gt; 如果是差是丢包，那么通过查看抓包文件，应该能看出很多不完整的session&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:28:46&amp;nbsp;&lt;br /&gt; 我觉得差值是来不及写入磁盘的包.&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:29:04&amp;nbsp;&lt;br /&gt; 再研究看看了。。谢谢啦/..&lt;br /&gt; wangbin579()&amp;nbsp;10:30:03&amp;nbsp;&lt;br /&gt; packets&amp;nbsp;captured是pcap_loop所设置的回调函数所调用的，一旦调用回调函数，就用统计&lt;br /&gt; wangbin579()&amp;nbsp;10:30:37&amp;nbsp;&lt;br /&gt; 有可能内核态部分和用户态部分，速度上不匹配，有延迟导致的？&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:32:33&amp;nbsp;&lt;br /&gt; 我现在理解,&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter是pcap库从内核中拿到的又匹配命令行上filter的包的数量，&amp;nbsp;packets&amp;nbsp;captured是经由pcap_loop,&amp;nbsp;pcap_dispatch之类通过callback交付出去的包数量.&amp;nbsp;差值就是还没来得及处理的.&lt;br /&gt; wangbin579()&amp;nbsp;10:32:48&amp;nbsp;&lt;br /&gt; 17s，每秒也就2000多个，不算多，用户态程序应该来得及处理
  &lt;/p&gt;
  &lt;p&gt;
    wangbin579()&amp;nbsp;10:33:58&amp;nbsp;&lt;br /&gt; 我这边系统很破，处理速度也比这个快，也没有来不及处理&lt;br /&gt; wangbin579()&amp;nbsp;10:34:45&amp;nbsp;&lt;br /&gt; 看看我的：&lt;br /&gt; wangbin579()&amp;nbsp;10:34:47&amp;nbsp;&lt;br /&gt; [root@hz0-12-157&amp;nbsp;~]#&amp;nbsp;time&amp;nbsp;tcpdump&amp;nbsp;-i&amp;nbsp;any&amp;nbsp;tcp&amp;nbsp;and&amp;nbsp;port&amp;nbsp;36524&amp;nbsp;or&amp;nbsp;3306&amp;nbsp;-w&amp;nbsp;3306.pcap&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt; tcpdump:&amp;nbsp;listening&amp;nbsp;on&amp;nbsp;any,&amp;nbsp;link-type&amp;nbsp;LINUX_SLL&amp;nbsp;(Linux&amp;nbsp;cooked),&amp;nbsp;capture&amp;nbsp;size&amp;nbsp;65535&amp;nbsp;bytes&lt;br /&gt; 294663&amp;nbsp;packets&amp;nbsp;captured&lt;br /&gt; 295432&amp;nbsp;packets&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter&lt;br /&gt; 693&amp;nbsp;packets&amp;nbsp;dropped&amp;nbsp;by&amp;nbsp;kernel
  &lt;/p&gt;
  &lt;p&gt;
    real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m17.676s&lt;br /&gt; user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m0.897s&lt;br /&gt; sys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m3.502s&lt;br /&gt; wangbin579()&amp;nbsp;10:35:52&amp;nbsp;&lt;br /&gt; 量比你大7倍多，也没有出现来不及处理啊，当然我的是物理机，3G内存，&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:36:59&amp;nbsp;&lt;br /&gt; 呃&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;25&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-30198.png&#34; width=&#34;25&#34; /&gt;&amp;nbsp;那你觉得这个差值不是来不及处理的包么？。我觉得应该还是来不及处理的。我在想，可能是写到的磁盘文件系统是NFS之类的&amp;nbsp;&amp;#8230;.我继续排查一下。&lt;br /&gt; wangbin579()&amp;nbsp;10:37:43&amp;nbsp;&lt;br /&gt; 有可能，我的是写入本地磁盘。&lt;br /&gt; wangbin579()&amp;nbsp;10:37:58&amp;nbsp;&lt;br /&gt; 你这种情况，我还是第一次碰到&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:39:05&amp;nbsp;&lt;br /&gt; 我先去运维那边了解下情况&amp;#8230;多谢啦&amp;nbsp;&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;25&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-16870.png&#34; width=&#34;25&#34; /&gt;&lt;br /&gt; wangbin579()&amp;nbsp;10:39:18&amp;nbsp;&lt;br /&gt; 算涨见识了，还以为一般dropped&amp;nbsp;by&amp;nbsp;kernel为0就代表不丢包呢，居然还有你这种情况。&lt;br /&gt; 你可以看看抓包文件，session是不是很多不完整，如果不完整，你的推测是对的&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:39:58&amp;nbsp;&lt;br /&gt; 嗯。呵呵~~&amp;nbsp;做IT，每天都会碰到挑战宇宙规律的现象。&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:40:07&amp;nbsp;&lt;br /&gt; &lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;25&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-6803.png&#34; width=&#34;25&#34; /&gt;&lt;br /&gt; мe(～&amp;nbsp;o&amp;nbsp;мe(632813052)&amp;nbsp;10:41:09&amp;nbsp;&lt;br /&gt; 呵呵&lt;br /&gt; wangbin579()&amp;nbsp;10:41:24&amp;nbsp;&lt;br /&gt; 其实，网络方面的问题，最复杂了。&lt;br /&gt; 我现在已经陷入到网络的汪洋大海之中了，各种各样的问题都会有，而且没有尽头。&lt;br /&gt; 早知道如此，3年前我就不搞这一块了&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:42:30&amp;nbsp;&lt;br /&gt; 同感。写一点点代码，都非常难以调试。各种认为理所当然的假设，通通是bug的温床
  &lt;/p&gt;
  &lt;p&gt;
    @wangbin579&amp;nbsp;&amp;nbsp;麻烦你在tcpdump前加个time，。。把输出贴出来。我好像看出问题来了。
  &lt;/p&gt;
  &lt;p&gt;
    [root@hz0-12-157&amp;nbsp;~]#&amp;nbsp;time&amp;nbsp;tcpdump&amp;nbsp;-i&amp;nbsp;any&amp;nbsp;tcp&amp;nbsp;and&amp;nbsp;port&amp;nbsp;36524&amp;nbsp;or&amp;nbsp;3306&amp;nbsp;-w&amp;nbsp;3306.pcap&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt; tcpdump:&amp;nbsp;listening&amp;nbsp;on&amp;nbsp;any,&amp;nbsp;link-type&amp;nbsp;LINUX_SLL&amp;nbsp;(Linux&amp;nbsp;cooked),&amp;nbsp;capture&amp;nbsp;size&amp;nbsp;65535&amp;nbsp;bytes&lt;br /&gt; 294663&amp;nbsp;packets&amp;nbsp;captured&lt;br /&gt; 295432&amp;nbsp;packets&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter&lt;br /&gt; 693&amp;nbsp;packets&amp;nbsp;dropped&amp;nbsp;by&amp;nbsp;kernel
  &lt;/p&gt;
  &lt;p&gt;
    real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m17.676s&lt;br /&gt; user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m0.897s&lt;br /&gt; sys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m3.502s&lt;br /&gt; wangbin579()&amp;nbsp;10:56:03&amp;nbsp;&lt;br /&gt; 不是加了time了吗？&lt;br /&gt; wangbin579()&amp;nbsp;10:57:15&amp;nbsp;&lt;br /&gt; [root@hz0-12-157&amp;nbsp;~]#&amp;nbsp;time&amp;nbsp;time&amp;nbsp;tcpdump&amp;nbsp;-i&amp;nbsp;any&amp;nbsp;tcp&amp;nbsp;and&amp;nbsp;port&amp;nbsp;36524&amp;nbsp;or&amp;nbsp;3306&amp;nbsp;-w&amp;nbsp;3306.pcap&lt;br /&gt; tcpdump:&amp;nbsp;listening&amp;nbsp;on&amp;nbsp;any,&amp;nbsp;link-type&amp;nbsp;LINUX_SLL&amp;nbsp;(Linux&amp;nbsp;cooked),&amp;nbsp;capture&amp;nbsp;size&amp;nbsp;65535&amp;nbsp;bytes&lt;br /&gt; ^C202061&amp;nbsp;packets&amp;nbsp;captured&lt;br /&gt; 202523&amp;nbsp;packets&amp;nbsp;received&amp;nbsp;by&amp;nbsp;filter&lt;br /&gt; 369&amp;nbsp;packets&amp;nbsp;dropped&amp;nbsp;by&amp;nbsp;kernel&lt;br /&gt; 0.66user&amp;nbsp;2.50system&amp;nbsp;0:11.99elapsed&amp;nbsp;26%CPU&amp;nbsp;(0avgtext+0avgdata&amp;nbsp;24208maxresident)k&lt;br /&gt; 0inputs+105656outputs&amp;nbsp;(0major+660minor)pagefaults&amp;nbsp;0swaps
  &lt;/p&gt;
  &lt;p&gt;
    real&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m11.999s&lt;br /&gt; user&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m0.661s&lt;br /&gt; sys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0m2.506s&lt;br /&gt; wangbin579()&amp;nbsp;10:57:26&amp;nbsp;&lt;br /&gt; 加两个，结果如上&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;10:59:29&amp;nbsp;&lt;br /&gt; 问题找到的。我这边运行的tcpdump，根本就没有抢到cpu时间来处理.&lt;br /&gt; wangbin579()&amp;nbsp;11:00:05&amp;nbsp;&lt;br /&gt; &lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;25&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-21252.png&#34; width=&#34;25&#34; /&gt;&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;11:00:06&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    Real&amp;nbsp;&amp;nbsp;0m3.914s
  &lt;/p&gt;
  &lt;p&gt;
    User&amp;nbsp;&amp;nbsp;0m0.008s
  &lt;/p&gt;
  &lt;p&gt;
    Sys&amp;nbsp;&amp;nbsp;&amp;nbsp;0m0.000s
  &lt;/p&gt;
  &lt;p&gt;
    跑了4秒钟，用户空间才抢到0.008秒，内核态几乎是0&amp;nbsp;&amp;#8230;.&lt;br /&gt; siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;11:00:25&amp;nbsp;&lt;br /&gt; 那个差值确实是没有来得及处理的包的数量。&lt;br /&gt; wangbin579()&amp;nbsp;11:00:41&amp;nbsp;&lt;br /&gt; 奥，那你系统这么繁忙啊
  &lt;/p&gt;
  &lt;p&gt;
    siu&amp;sup1;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;&amp;ordm;()&amp;nbsp;11:02:22&amp;nbsp;&lt;br /&gt; 所以，解决了一个问题又会有新的颠覆宇宙规律的问题&amp;#8230;系统负载很高，但cpu使用率很低。。
  &lt;/p&gt;
  &lt;p&gt;
    &lt;span style=&#34;color: rgb(0, 0, 0); font-family: Verdana, Geneva, sans-serif; font-size: 16px; line-height: 22px;&#34;&gt;copyright ykyi.net&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>tcpcopy在视频广告组的二次开发</title>
      <link>https://ykyi.net/?p=1022/</link>
      <pubDate>Wed, 16 Oct 2013 09:01:05 +0000</pubDate>
      <guid>https://ykyi.net/?p=1022/</guid>
      <description>&lt;ol&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;流量筛选中的 “只导入某频道的流量”功能已经实现了。&lt;/p&gt;
&lt;p&gt;技术层面上，实际上是通过指定正则式的方法匹配HTTP请求中的GET方法中的URL来达到过滤的目的。&lt;/p&gt;
&lt;p&gt;所以，也可以用ty，ad_type, pf, coverid, oadid, v，plugin等出现在GET方法中的参数编写正则式来过滤流量。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;流量筛选中的“地域纬度筛选”暂时没有实现。&lt;/p&gt;
&lt;p&gt;因为地域纬度的信息不是以参数形式出现在GET方法的URL中，需要通过IP地址或者cookie的中QQ号信息来判断。&lt;/p&gt;
&lt;p&gt;还没最终决定是否实现这个功能。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;tcpcopy官方版本主要的应用场景是复制实时流量。所以部署的时候至少两台机器，一台线上机，另一台测试用机。为了方便压力测试，还引入了至少三台机器的高级模式。&lt;/p&gt;
&lt;p&gt;部署起来比较麻烦。&lt;/p&gt;
&lt;p&gt;如果“视频CPM广告的模拟投放，以及订单效果预估“只是从磁盘中读入以往的流量，针对这种场景，可以探索tcpcopy的单机离线模式，做到方便部署和使用。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;部分同学有一个误解.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;ldquo;将线上的实际访问流量，复制一份保存到本地服务器，用于后续使用&amp;rdquo;&lt;/p&gt;
&lt;p&gt;目前，tcpcopy的官方的版本没有把流量保存下来的功能，保存流量这个目前是用tcpdump的-w选项来做的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;另外，技术上，tcpdump只能在IP层和TCP层指定过滤条件，不能用业务的逻辑过滤流量。第1点提到的流量筛选工作在tcpcopy读入实时流量时，或者从tcpdump存下的文件中读入流量时，在应用层指定过滤条件。&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;color: rgb(0, 0, 0); font-family: Verdana, Geneva, sans-serif; font-size: 16px; line-height: 22px;&#34;&gt;copyright ykyi.net&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux抓包技术简介</title>
      <link>https://ykyi.net/?p=1006/</link>
      <pubDate>Tue, 10 Sep 2013 05:05:03 +0000</pubDate>
      <guid>https://ykyi.net/?p=1006/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    Linux抓包技术简介
  &lt;/p&gt;
  &lt;p&gt;
    Author: zausiu@gmail.com
  &lt;/p&gt;
  &lt;p&gt;
    1.&amp;nbsp;简介
  &lt;/p&gt;
  &lt;p&gt;
    大多数应用常景下，我们在IP层上用AF_INET或AF_INET6作为socket的第一个参数，SOCK_STREAM或SOCK_DGRAM作为socket的第二个参数创建最为常见的IPv4或IPv6的TCP或UDP套接字。这样的套接字满足了绝大多数网络应用常景。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    本文简单介绍三种Linux平台下抓包，截获包的技术。它们提供一些更酷的功能。每种技术的水都很深，作者个人水平有限，按照自己的理解做一般的介绍。仅仅旨在起到科谱的作用。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    2.&amp;nbsp;RAW&amp;nbsp;SOCKET
  &lt;/p&gt;
  &lt;p&gt;
    参数SOCK_RAW可以作为socket函数的第二个参数传入，这样创建的套接字称为原始套接字。设置Socket的第一个参数可以让指定原始套接字开在数据链路层上或者网络层。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    下面的语句创建在数据链路层上的原始socket。
  &lt;/p&gt;
  &lt;p&gt;
    Socket(AF_PACKET,&amp;nbsp;SOCK_RAW,&amp;nbsp;htons(ETH_P_ALL));&amp;nbsp;&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    在负载不大的情况下，读这个socket可以拿到本机收到的所有数据包。写入这个socket需要程序员负责填充各种包头的数据。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    Socket(AF_INET,&amp;nbsp;SOCK_RAW,&amp;nbsp;xxxxx协议号)；
  &lt;/p&gt;
  &lt;p&gt;
    在IP层上创建IPv4的RAW&amp;nbsp;socket，可以拿到各种经由IPv4的数据包，比如ICMP包，IGMP包等。Steven的&lt;Unix网络编程&gt;第三版第28.4节，第二段：&amp;ldquo;系统收到的UDP包和TCP包不会传给原始套接字&amp;rdquo;。但读tcpcopy的源代码时，确实用了原始套接字在网络层读UDP和TCP包。难道书上写的过时了。见代码，来自tcpcopy：
  &lt;/p&gt;
  &lt;p&gt;
    #if&amp;nbsp;(TCPCOPY_UDP)
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fd&amp;nbsp;=&amp;nbsp;socket(AF_INET,&amp;nbsp;SOCK_RAW,&amp;nbsp;IPPROTO_UDP);
  &lt;/p&gt;
  &lt;p&gt;
    #else
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fd&amp;nbsp;=&amp;nbsp;socket(AF_INET,&amp;nbsp;SOCK_RAW,&amp;nbsp;IPPROTO_TCP);
  &lt;/p&gt;
  &lt;p&gt;
    #endif
  &lt;/p&gt;
  &lt;p&gt;
    另外，在IP层上创建的原始套接字有一个选项：IP_HDRINCL，它被开启时，则内核帮助填充IP包头。Linux默认没有开启这个选项。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    3.&amp;nbsp;NF_Queue
  &lt;/p&gt;
  &lt;p&gt;
    NF_Queue是用户空间的一个库，需要内核模块NETFILTER_NETLINK_QUEUE的支持。官方网址：&lt;a href=&#34;http://www.netfilter.org/&#34;&gt;http://www.netfilter.org&lt;/a&gt;。通过这个库可以在数据包被发往用户空间处理前截获数据包，或者在数据包被发往网卡前截获数据库。截获后，可以修改数据包的内容，并决定是否丢充这个数据库。
  &lt;/p&gt;
  &lt;p&gt;
    NF_Queue可以用来编写防火墙等安全软件。
  &lt;/p&gt;
  &lt;p&gt;
    Tcpcopy使用NF_Queue丢弃测试中的程序回复给真实客户程序的数据包，使测试中程序回复的报文不影响真实客户程序。
  &lt;/p&gt;
  &lt;p&gt;
    另一个提供类似功能的库是IP_Queue，它已经被废弃。NF_Queue可以完全取代IP_Queue。我们用的tlinux，内核中built-in了NF_Queue模块。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    4.&amp;nbsp;libpcap
  &lt;/p&gt;
  &lt;p&gt;
    大名鼎鼎的Libpcap是一个古老的可以工作在所有Unix-like平台上的抓包库，比linux年纪更大。Tcpdump的广泛使用让libpcap成为事实上的行业标准。它可以很方便的编写抓取数据链路层上的数据包，并可以设置过滤条件在内核级别只复制关心的数据包，而数据链路层上的原始套接字会尽最大努力复制所有的包，所以libpcap的工作效率高。而且，pcap使用方便。下面是一个很简单的使用pcap抓到发往80端口的tcp包并打印源IP，目的IP，和目的端口号的程序。非常短，很容易看，起到介绍libpcap的作用。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;int&amp;nbsp;main(int&amp;nbsp;argc,&amp;nbsp;char&amp;nbsp;*argv[])
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;{
  &lt;/p&gt;
  &lt;p&gt;
    pcap_t&amp;nbsp;*handle; //&amp;nbsp;pcap用的句柄，和其它各种句柄一样。
  &lt;/p&gt;
  &lt;p&gt;
    char&amp;nbsp;*dev; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;网络接口名，如eth0,&amp;nbsp;eth1,&amp;nbsp;tunl0&amp;nbsp;之类
  &lt;/p&gt;
  &lt;p&gt;
    char&amp;nbsp;errbuf[PCAP_ERRBUF_SIZE]; //&amp;nbsp;存描述出错原因的缓冲
  &lt;/p&gt;
  &lt;p&gt;
    struct&amp;nbsp;bpf_program&amp;nbsp;fp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;pcap用来过滤数据包用
  &lt;/p&gt;
  &lt;p&gt;
    char&amp;nbsp;filter_exp[]&amp;nbsp;=&amp;nbsp;&#34;tcp&amp;nbsp;and&amp;nbsp;dst&amp;nbsp;port&amp;nbsp;80&#34;;&amp;nbsp;//&amp;nbsp;过滤字符串，和tcpdump的写法一样
  &lt;/p&gt;
  &lt;p&gt;
    struct&amp;nbsp;pcap_pkthdr&amp;nbsp;header;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;pcap自己用的包头
  &lt;/p&gt;
  &lt;p&gt;
    const&amp;nbsp;u_char&amp;nbsp;*packet; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;pcap包头后的数据，即抓到的数据
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    int&amp;nbsp;len_of_iphdr;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;ip头的长度
  &lt;/p&gt;
  &lt;p&gt;
    struct&amp;nbsp;in_addr&amp;nbsp;src_ip;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;源IP地址
  &lt;/p&gt;
  &lt;p&gt;
    struct&amp;nbsp;in_addr&amp;nbsp;dst_ip;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;目的IP
  &lt;/p&gt;
  &lt;p&gt;
    const&amp;nbsp;u_char&amp;nbsp;*ip_hdr_addr; //&amp;nbsp;IP头的首地址
  &lt;/p&gt;
  &lt;p&gt;
    const&amp;nbsp;u_char&amp;nbsp;*tcp_hdr_addr;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;tcp头的首地址
  &lt;/p&gt;
  &lt;p&gt;
    struct&amp;nbsp;tcphdr&amp;nbsp;*tcp_hdr;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;tcp头结构体
  &lt;/p&gt;
  &lt;p&gt;
    u_short&amp;nbsp;dst_port;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;目的端口
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    //&amp;nbsp;如果命令行指定网卡名
  &lt;/p&gt;
  &lt;p&gt;
    if&amp;nbsp;(argv[1])
  &lt;/p&gt;
  &lt;p&gt;
    dev&amp;nbsp;=&amp;nbsp;argv[1];&amp;nbsp;//就用指定的网卡
  &lt;/p&gt;
  &lt;p&gt;
    else
  &lt;/p&gt;
  &lt;p&gt;
    dev&amp;nbsp;=&amp;nbsp;&#34;eth0&#34;;&amp;nbsp;//否则用eth0
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    }
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;用pcap打开这个网卡
  &lt;/p&gt;
  &lt;p&gt;
    handle&amp;nbsp;=&amp;nbsp;pcap_open_live(dev,&amp;nbsp;BUFSIZ,&amp;nbsp;0,&amp;nbsp;1000,&amp;nbsp;errbuf);
  &lt;/p&gt;
  &lt;p&gt;
    if&amp;nbsp;(handle&amp;nbsp;==&amp;nbsp;NULL)&amp;nbsp;{&amp;nbsp;&amp;nbsp;//&amp;nbsp;打开网卡出错
  &lt;/p&gt;
  &lt;p&gt;
    fprintf(stderr,&amp;nbsp;&#34;Couldn&#39;t&amp;nbsp;open&amp;nbsp;device&amp;nbsp;%s:&amp;nbsp;%s\n&#34;,&amp;nbsp;dev,&amp;nbsp;errbuf);
  &lt;/p&gt;
  &lt;p&gt;
    return(2);
  &lt;/p&gt;
  &lt;p&gt;
    }
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;编译过滤文件
  &lt;/p&gt;
  &lt;p&gt;
    if&amp;nbsp;(pcap_compile(handle,&amp;nbsp;&amp;fp,&amp;nbsp;filter_exp,&amp;nbsp;0,&amp;nbsp;net)&amp;nbsp;==&amp;nbsp;-1)&amp;nbsp;{
  &lt;/p&gt;
  &lt;p&gt;
    fprintf(stderr,&amp;nbsp;&#34;Couldn&#39;t&amp;nbsp;parse&amp;nbsp;filter&amp;nbsp;%s:&amp;nbsp;%s\n&#34;,&amp;nbsp;filter_exp,&amp;nbsp;pcap_geterr(handle));
  &lt;/p&gt;
  &lt;p&gt;
    return(2);
  &lt;/p&gt;
  &lt;p&gt;
    }
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;设置过滤条件
  &lt;/p&gt;
  &lt;p&gt;
    if&amp;nbsp;(pcap_setfilter(handle,&amp;nbsp;&amp;fp)&amp;nbsp;==&amp;nbsp;-1)&amp;nbsp;{
  &lt;/p&gt;
  &lt;p&gt;
    fprintf(stderr,&amp;nbsp;&#34;Couldn&#39;t&amp;nbsp;install&amp;nbsp;filter&amp;nbsp;%s:&amp;nbsp;%s\n&#34;,&amp;nbsp;filter_exp,&amp;nbsp;pcap_geterr(handle));
  &lt;/p&gt;
  &lt;p&gt;
    return(2);
  &lt;/p&gt;
  &lt;p&gt;
    }
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;抓包
  &lt;/p&gt;
  &lt;p&gt;
    packet&amp;nbsp;=&amp;nbsp;pcap_next(handle,&amp;nbsp;&amp;header);
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    //&amp;nbsp;至此packet指向抓到的一个目标端口号是80的数据链路层的包
  &lt;/p&gt;
  &lt;p&gt;
    //&amp;nbsp;它的包结构是&amp;nbsp;14字节以太网包头&amp;nbsp;+&amp;nbsp;可变IPv4包头&amp;nbsp;+&amp;nbsp;TCP包头
  &lt;/p&gt;
  &lt;p&gt;
    ip_hdr_addr&amp;nbsp;=&amp;nbsp;(u_char*)(packet&amp;nbsp;+&amp;nbsp;sizeof(struct&amp;nbsp;ethernet_hdr));
  &lt;/p&gt;
  &lt;p&gt;
    src_ip.s_addr&amp;nbsp;=&amp;nbsp;((struct&amp;nbsp;iphdr*)ip_hdr_addr)-&gt;saddr;
  &lt;/p&gt;
  &lt;p&gt;
    dst_ip.s_addr&amp;nbsp;=&amp;nbsp;((struct&amp;nbsp;iphdr*)ip_hdr_addr)-&gt;daddr;
  &lt;/p&gt;
  &lt;p&gt;
    len_of_iphdr&amp;nbsp;=&amp;nbsp;((struct&amp;nbsp;iphdr*)ip_hdr_addr)-&gt;ihl&amp;nbsp;*&amp;nbsp;4;
  &lt;/p&gt;
  &lt;p&gt;
    tcp_hdr_addr&amp;nbsp;=&amp;nbsp;ip_hdr_addr&amp;nbsp;+&amp;nbsp;len_of_iphdr;
  &lt;/p&gt;
  &lt;p&gt;
    tcp_hdr&amp;nbsp;=&amp;nbsp;(struct&amp;nbsp;tcphdr*)tcp_hdr_addr;
  &lt;/p&gt;
  &lt;p&gt;
    dst_port&amp;nbsp;=&amp;nbsp;tcp_hdr-&gt;dest;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    //&amp;nbsp;经过上面的各种指针偏移，下面打印源IP和目标IP和目标端口.
  &lt;/p&gt;
  &lt;p&gt;
    printf(&#34;src&amp;nbsp;addr&amp;nbsp;%s\n&#34;,&amp;nbsp;inet_ntoa(src_ip));
  &lt;/p&gt;
  &lt;p&gt;
    printf(&#34;dst&amp;nbsp;addr&amp;nbsp;%s\n&#34;,&amp;nbsp;inet_ntoa(dst_ip));
  &lt;/p&gt;
  &lt;p&gt;
    printf(&#34;dst_port&amp;nbsp;%d\n&#34;,&amp;nbsp;ntohs(dst_port));
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    /*&amp;nbsp;And&amp;nbsp;close&amp;nbsp;the&amp;nbsp;session&amp;nbsp;*/
  &lt;/p&gt;
  &lt;p&gt;
    pcap_close(handle);
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    return(0);
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;}
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    5.&amp;nbsp;总结
  &lt;/p&gt;
  &lt;p&gt;
    本文只是一个非常简单的介绍。如需要进阶学习，Stevens的网络编译有更详细地关于Raw&amp;nbsp;Socket的内容，研究NF_Queue技术则需要读源代码和收集散在社区各个角落的资料了，而讲libpcap有两篇很好的文章：
  &lt;/p&gt;
  &lt;p&gt;
    &#34;&lt;a href=&#34;http://recursos.aldabaknocking.com/libpcapHakin9LuisMartinGarcia.pdf&#34;&gt;Programming&amp;nbsp;with&amp;nbsp;Libpcap&amp;nbsp;&amp;ndash;&amp;nbsp;Sniffing&amp;nbsp;the&amp;nbsp;network&amp;nbsp;from&amp;nbsp;our&amp;nbsp;own&amp;nbsp;application&amp;nbsp;&lt;/a&gt;&#34;用Libpcap编程，在我们的程序中嗅探网络。非常漂亮的pdf文档。
  &lt;/p&gt;
  &lt;p&gt;
    &lt;a href=&#34;http://recursos.aldabaknocking.com/libpcapHakin9LuisMartinGarcia.pdf&#34;&gt;http://recursos.aldabaknocking.com/libpcapHakin9LuisMartinGarcia.pdf&lt;/a&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;a href=&#34;http://yuba.stanford.edu/~casado/pcap/section1.html&#34;&gt;The&amp;nbsp;Sniffer&amp;rsquo;s&amp;nbsp;Guide&amp;nbsp;to&amp;nbsp;Raw&amp;nbsp;Traffic&lt;/a&gt;&amp;nbsp;嗅探器教程。斯坦福大学的Geek于大概2001年写的。
  &lt;/p&gt;
  &lt;p&gt;
    &lt;a href=&#34;http://yuba.stanford.edu/~casado/pcap/section1.html&#34;&gt;http://yuba.stanford.edu/~casado/pcap/section1.html&lt;/a&gt;
  &lt;/p&gt;
  &lt;p&gt;
    copyright ykyi.net
  &lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>Linux是从什么时候开始支持线程的.</title>
      <link>https://ykyi.net/?p=1003/</link>
      <pubDate>Mon, 09 Sep 2013 04:57:26 +0000</pubDate>
      <guid>https://ykyi.net/?p=1003/</guid>
      <description>&lt;p&gt;几天前和同事吃饭，谈论到一个问题：linux从什么时候开始支持线程。他说linux中的线程出现的很晚，直到2.2.x才有。&lt;/p&gt;
&lt;p&gt;我觉得不对啊，怎么会那么晚。然后它用手机搜索了一下，linux对POSIX线程库的支持确实很晚，直到2.6.x才有。&lt;/p&gt;
&lt;p&gt;但我觉得POSIX线程库只不过是用户空间用来创建线程的接口，并不能证明那么晚linux才支持线程。&lt;/p&gt;
&lt;p&gt;后来用PC的时候搜索了一下，在The Linux Document Project的官方网站找到了答案：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.tldp.org/FAQ/Threads-FAQ/Support.html&#34;&gt;http://www.tldp.org/FAQ/Threads-FAQ/Support.html&lt;/a&gt;&lt;/p&gt;
&lt;p style=&#34;color: rgb(0, 0, 0); font-family: Simsun; font-size: medium; line-height: normal;&#34;&gt;
  &lt;font size=&#34;+3&#34;&gt;Does Linux support threads?&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;Yes. As of 1.3.56, Linux has supported kernel-space multithreading. There also have been user-space thread libraries around as early as 1.0.9. There is on-going effort to refine and make the kernel more reentrant. With the introduction of 2.1.x, the memory space is being revised so that the kernel can access the user memory more quickly.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tcpcopy初体验.</title>
      <link>https://ykyi.net/?p=984/</link>
      <pubDate>Mon, 26 Aug 2013 03:28:13 +0000</pubDate>
      <guid>https://ykyi.net/?p=984/</guid>
      <description>&lt;p&gt;Tcpcopy 初体验&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Tcpcopy是一个模拟真实流量的测试工具。它的工作基本思想是，从已经上线的服务器复制一份真实流量到测试服务器。Tcpcopy的代码开源，代码仓库放在&lt;a href=&#34;https://github.com/wangbin579/tcpcopy&#34;&gt;https://github.com/wangbin579/tcpcopy&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;经过初步学习，已成功在公司的测试机器上部署tcpcopy，并用简单的DEMO程序测试达到预期目的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;**1.**&lt;strong&gt;安装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为作者写的安装介绍只提到最基本的信息，而测试环境各不一样，在我用的测试机的实际安装过程中碰到一些问题。这时问题在这里列出，以供后来者参考，以节省时间。测试机：10.12.194.199 ； 10.12.194.212 ； 10.12.194.214 。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.1&lt;/strong&gt; &lt;strong&gt;需要额外安装的库：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;需要在网站 &lt;a href=&#34;http://www.netfilter.org&#34;&gt;www.netfilter.org&lt;/a&gt; 下载 libmnl， libnfnetlink， libnetfilter_queue 三个工程并安装。 安装顺序为 libmnl， libnfnetlink, libnetfilter_queue，因为第三个依赖第二个，第二个依赖第一个。安装方法是GNU工具的传统三板斧方式： ./configure ; make; make install。这三个工程生成三个.so库放置到/usr/local/lib，而我们用的操作系统环境并没有把该目录列在默认查找库文件的目录列表中，因此要编辑 /etc/ld.so.conf 文件，把目录/usr/local/lib 加入，再运行 ldconfig 更新ld链接程序使用的cache。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.2 IP_Queue****和NFQueue内核模块：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这两个内核模块给在用户空间编写处理内核空间中传递网络数据包提供接口。它们的区别是IP_Queue是旧的实现，仅支持IPv4，NFQueue是新的实现。Tcpcopy工程依赖这两个模块之一。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Tcpcopy官方文档中多次提到tcpcopy在内核版本小于3.5时默认使用IP_Queue，并在使用例子中有一步操作：&lt;/p&gt;
&lt;p&gt;# modprobe ip_queue&lt;/p&gt;
&lt;p&gt;这个操作是确保加载ip_queue模块到内核。&lt;/p&gt;
&lt;p&gt;我们的测试环境的内核版本号是2.6.32，按照官方文档介绍，内核版本小于3.5，于是使用#modprobe ip_queue命令，结果报错显示我们使用的内核没有启用动态模块加载。&lt;/p&gt;
&lt;p&gt;于是再用 # zcat /proc/config.gz 检查当前内核的配置，发现CONFIG_IP_NF_QUEUE is not set, 说明IP_Queue模块没有被buit-in，再查找NFQueue的配置项发现 CONFIG_NETFILTER_NETLINK_QUEUE=y。&lt;/p&gt;
&lt;p&gt;所以，在我们的环境中，应该忽略官方文档中# modprobe ip_queue，我们的内核已经内建了比IPQueue更新的&lt;strong&gt;NFQueue****。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.3&lt;/strong&gt; &lt;strong&gt;编译安装tcpcopy&lt;/strong&gt;**：**&lt;/p&gt;
&lt;p&gt;官方文档中把已经正常运行业务的服务器称为在线服务器(online server)，把运行待测试用的服务器称为目标服务器(target server)。&lt;/p&gt;
&lt;p&gt;在在线服务器端运行配置命令时务必指定 –enable-nfqueue，这是因为我们用的内核中只有NFQueue，如果不指定这个选项，编译出的tcpcopy不会运行成功，会在日志文件中报错：please make sure ip queue is running.&lt;/p&gt;
&lt;p&gt;# ./configure –enable-nfqueue –enable-pcap&lt;/p&gt;</description>
    </item>
    <item>
      <title>virtualBox开机挂载windows分区，并把光盘镜源设为源</title>
      <link>https://ykyi.net/?p=981/</link>
      <pubDate>Wed, 21 Aug 2013 08:33:59 +0000</pubDate>
      <guid>https://ykyi.net/?p=981/</guid>
      <description>&lt;p&gt;virtualBox开机挂载windows分区，并把光盘镜源设为源。&lt;/p&gt;
&lt;p&gt;设置fstab文件。把windows的d,e,f盘分别开机挂载到了/misc/d &lt;span style=&#34;font-size: 13px;&#34;&gt;/misc/e /misc/f&lt;/span&gt; 。/misc是自建的目录，是miscellany的缩写。&lt;/p&gt;
&lt;p&gt;# cat /etc/fstab &lt;/p&gt;
&lt;p&gt;# /etc/fstab: static file system information.&lt;/p&gt;
&lt;h1&gt;&lt;/h1&gt;
&lt;p&gt;# Use &amp;lsquo;blkid&amp;rsquo; to print the universally unique identifier for a&lt;br&gt;
# device; this may be used with UUID= as a more robust way to name devices&lt;br&gt;
# that works even if disks are added and removed. See fstab(5).&lt;/p&gt;
&lt;h1&gt;&lt;/h1&gt;
&lt;p&gt;# &lt;file system&gt; &lt;mount point&gt;   &lt;type&gt;  &lt;options&gt;       &lt;dump&gt;  &lt;pass&gt;&lt;br&gt;
# / was on /dev/sda1 during installation&lt;br&gt;
UUID=590c2b64-87b7-4f92-b32f-7133139be772 /               ext4    errors=remount-ro 0       1&lt;br&gt;
# swap was on /dev/sda5 during installation&lt;br&gt;
UUID=1e4e1188-d057-4210-99e7-6f2d1529db80 none            swap    sw              0       0&lt;br&gt;
/dev/sr0        /media/cdrom0   udf,iso9660 user,noauto     0       0&lt;br&gt;
D_DRIVE         /misc/d         vboxsf      rw,auto         0       0             0&lt;br&gt;
E_DRIVE         /misc/e         vboxsf      rw,auto         0       0             0&lt;br&gt;
F_DRIVE         /misc/f         vboxsf      rw,auto         0       0             0&lt;br&gt;
/misc/d/debian_ios/debian-7.1.0-amd64-DVD-1.iso /misc/a_iso udf,iso9660 user,loop,auto 0 0&lt;br&gt;
/misc/d/debian_ios/debian-7.1.0-amd64-DVD-2.iso /misc/b_iso udf,iso9660 user,loop,auto 0 0&lt;br&gt;
/misc/d/debian_ios/debian-7.1.0-amd64-DVD-3.iso /misc/c_iso udf,iso9660 user,loop,auto 0 0&lt;/p&gt;</description>
    </item>
    <item>
      <title>我的毕业论文.Linux桌面环境下内存去重技术的 研究与实现</title>
      <link>https://ykyi.net/?p=979/</link>
      <pubDate>Tue, 20 Aug 2013 07:00:10 +0000</pubDate>
      <guid>https://ykyi.net/?p=979/</guid>
      <description>&lt;p&gt;把我的毕业论文放上来，直接从word复制，所以图片会丢失。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;http://www.ykyi.net/upload/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;span style=&#34;color:#FF0000;&#34;&gt;在这里可以下载原稿 www.ykyi.net/upload/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;中山大学硕士学位论文&lt;/p&gt;
&lt;p&gt;Linux桌面环境下内存去重技术的. based on KSM&lt;/p&gt;
&lt;p&gt;研究与实现&lt;/p&gt;
&lt;p&gt;Research and Implementation of Memory Deduplication in&lt;/p&gt;
&lt;p&gt;The Linux Desktop Environment&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:188px;&#34;&gt;
      &lt;p&gt;
        学位申请人：
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:160px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    周霄
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:188px;&#34;&gt;
      &lt;p&gt;
        导师姓名及职称：
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:160px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    王常吉副教授
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;div&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;p&gt;
    论文原创性声明
  &lt;/p&gt;
  &lt;p&gt;
    本人郑重声明：所呈交的学位论文，是本人在导师的指导下，独立进行研究工作所取得的成果。除文中已经注明引用的内容外，本论文不包含任何其他个人或集体已经发表或撰写过的作品成果。对本文的研究做出重要贡献的个人和集体，均已在文中以明确方式标明。本人完全意识到本声明的法律结果由本人承担。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    学位论文作者签名：
  &lt;/p&gt;
  &lt;p&gt;
    日期：&amp;nbsp;年&amp;nbsp;&amp;nbsp;月&amp;nbsp;&amp;nbsp;日
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    学位论文使用授权声明
  &lt;/p&gt;
  &lt;p&gt;
    本人完全了解中山大学有关保留、使用学位论文的规定，即：学校有权保留学位论文并向国家主管部门或其指定机构送交论文的电子版和纸质版；有权将学位论文用于非赢利目的的少量复制并允许论文进入学校图书馆、院系资料室被查阅；有权将学位论文的内容编入有关数据库进行检索；可以采用复印、缩印或其他方法保存学位论文；可以为存在馆际合作关系的兄弟高校用户提供文献传递服务和交换服务。
  &lt;/p&gt;
  &lt;p&gt;
    保密论文保密期满后，适用本声明。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    学位论文作者签名：&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;导师签名：
  &lt;/p&gt;
  &lt;p&gt;
    日期：&amp;nbsp;&amp;nbsp;年&amp;nbsp;&amp;nbsp;月&amp;nbsp;&amp;nbsp;日&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;日期：&amp;nbsp;&amp;nbsp;年&amp;nbsp;&amp;nbsp;月&amp;nbsp;&amp;nbsp;日
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;p&gt;
    论文题目：&amp;nbsp;Linux桌面环境下内存去重技术的研究与实现
  &lt;/p&gt;
  &lt;p&gt;
    专业：软件工程&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    硕士生：周霄
  &lt;/p&gt;
  &lt;p&gt;
    指导教师：王常吉&amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    摘&amp;nbsp;&amp;nbsp;要
  &lt;/p&gt;
  &lt;p&gt;
    内存管理是操作系统中至关重要的部分。优秀的操作系统高效地管理有限的内存资源。Linux内核的内核同页合并（KSM）模块是在虚拟化兴起后为节省虚拟机使用的内存而发展的一种节约内存的技术。KSM通过合并相同内容页面的方式显著地降低了多个基于内核虚拟机（KVM）技术的虚拟机同时运行时系统使用的内存。实际上，KSM也能合并一般应用程序中的相同内容页面。但一般应用程序为了使用KSM技术合并内存，需要在源代码级别显式地调用相应的系统调用来告知KSM需要扫描的内存区域。对于一般用户来说，需要修改应用程序的源代码显然是一个太高的门槛。
  &lt;/p&gt;
  &lt;p&gt;
    本论文在认真研究了KSM模块的实现的基础上，增强了KSM的功能。新设计实现的KSM+使得用户可以不必修改应用程序的源代码就能利用KSM+合并相同内容的内存页面。另外原来的KSM算法依赖程序指定的内存区域有大量的重复内存页面，而实际上，一般应用程序并没有大量的重复内存。在重复内存非常少的情况下，对这些程序应用KSM技术非但不能降低内存使用，而且因为运行KSM本身所需内存而增加了内存开销。本论文针对这一点在KSM的算法上做了改进，减少了运行KSM+算法本身所消耗的内存。然后论文用Linux桌面下的常用应用程序验证了KSM+的实际效果，并构造了一个实验比较了KSM和KSM+。最后，为了了解应用程序的重复内存页面的特点，还编写了专门统计重复页面的内核模块，发现应用程序的重复页面的一些规律，为持续改进KSM+提供了依据。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    关键词：KSM，重复内存合并&amp;nbsp;，内存管理
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    Title:&amp;nbsp;Research&amp;nbsp;and&amp;nbsp;Implementation&amp;nbsp;of&amp;nbsp;Memory&amp;nbsp;Deduplication&amp;nbsp;in&amp;nbsp;The&amp;nbsp;Linux&amp;nbsp;Desktop&amp;nbsp;Environment
  &lt;/p&gt;
  &lt;p&gt;
    Major:&amp;nbsp;Software&amp;nbsp;Engineering
  &lt;/p&gt;
  &lt;p&gt;
    Name:&amp;nbsp;Zhou&amp;nbsp;Xiao
  &lt;/p&gt;
  &lt;p&gt;
    Supervisor:&amp;nbsp;Wang&amp;nbsp;Changji
  &lt;/p&gt;
  &lt;p&gt;
    Abstract
  &lt;/p&gt;
  &lt;p&gt;
    Memory&amp;nbsp;management&amp;nbsp;is&amp;nbsp;one&amp;nbsp;of&amp;nbsp;the&amp;nbsp;most&amp;nbsp;important&amp;nbsp;parts&amp;nbsp;of&amp;nbsp;the&amp;nbsp;operating&amp;nbsp;system.&amp;nbsp;KSM&amp;nbsp;(Kernel&amp;nbsp;Samepage&amp;nbsp;Merging)&amp;nbsp;in&amp;nbsp;Linux&amp;nbsp;kernel&amp;nbsp;is&amp;nbsp;a&amp;nbsp;kind&amp;nbsp;of&amp;nbsp;memory&amp;nbsp;saving&amp;nbsp;technology&amp;nbsp;developed&amp;nbsp;after&amp;nbsp;the&amp;nbsp;emerging&amp;nbsp;of&amp;nbsp;virtual&amp;nbsp;machine.&amp;nbsp;KSM&amp;nbsp;can&amp;nbsp;dramatically&amp;nbsp;decrease&amp;nbsp;the&amp;nbsp;memory&amp;nbsp;usage&amp;nbsp;of&amp;nbsp;the&amp;nbsp;hypervisor&amp;nbsp;running&amp;nbsp;several&amp;nbsp;virtual&amp;nbsp;machines.&amp;nbsp;Actually,&amp;nbsp;KSM&amp;nbsp;can&amp;nbsp;also&amp;nbsp;be&amp;nbsp;applied&amp;nbsp;to&amp;nbsp;normal&amp;nbsp;applications.&amp;nbsp;But&amp;nbsp;in&amp;nbsp;order&amp;nbsp;to&amp;nbsp;use&amp;nbsp;the&amp;nbsp;KSM,&amp;nbsp;application&amp;nbsp;must&amp;nbsp;explicitly&amp;nbsp;evoke&amp;nbsp;a&amp;nbsp;system&amp;nbsp;call&amp;nbsp;in&amp;nbsp;source&amp;nbsp;code&amp;nbsp;level&amp;nbsp;to&amp;nbsp;tell&amp;nbsp;KSM&amp;nbsp;the&amp;nbsp;memory&amp;nbsp;area&amp;nbsp;where&amp;nbsp;the&amp;nbsp;KSM&amp;nbsp;will&amp;nbsp;scan.&amp;nbsp;To&amp;nbsp;normal&amp;nbsp;users,&amp;nbsp;modifying&amp;nbsp;the&amp;nbsp;source&amp;nbsp;code&amp;nbsp;is&amp;nbsp;impossible&amp;nbsp;at&amp;nbsp;most&amp;nbsp;of&amp;nbsp;the&amp;nbsp;time.
  &lt;/p&gt;
  &lt;p&gt;
    Base&amp;nbsp;on&amp;nbsp;the&amp;nbsp;full&amp;nbsp;grasp&amp;nbsp;of&amp;nbsp;the&amp;nbsp;implementation&amp;nbsp;of&amp;nbsp;KSM,&amp;nbsp;a&amp;nbsp;new&amp;nbsp;implementation&amp;nbsp;named&amp;nbsp;KSM+&amp;nbsp;is&amp;nbsp;created,&amp;nbsp;which&amp;nbsp;allows&amp;nbsp;users&amp;nbsp;to&amp;nbsp;merge&amp;nbsp;same-content&amp;nbsp;pages&amp;nbsp;on&amp;nbsp;the&amp;nbsp;specified&amp;nbsp;applications&amp;nbsp;without&amp;nbsp;modifying&amp;nbsp;corresponding&amp;nbsp;source&amp;nbsp;code.&amp;nbsp;Moreover,&amp;nbsp;the&amp;nbsp;original&amp;nbsp;KSM&amp;nbsp;algorithm&amp;nbsp;relies&amp;nbsp;heavily&amp;nbsp;on&amp;nbsp;the&amp;nbsp;specified&amp;nbsp;area&amp;nbsp;is&amp;nbsp;rich&amp;nbsp;in&amp;nbsp;same-content&amp;nbsp;pages,&amp;nbsp;while&amp;nbsp;normal&amp;nbsp;applications&amp;nbsp;have&amp;nbsp;much&amp;nbsp;less&amp;nbsp;same-content&amp;nbsp;pages&amp;nbsp;compared&amp;nbsp;to&amp;nbsp;virtual&amp;nbsp;machines.&amp;nbsp;So,&amp;nbsp;when&amp;nbsp;KSM&amp;nbsp;is&amp;nbsp;applied&amp;nbsp;to&amp;nbsp;those&amp;nbsp;applications,&amp;nbsp;it&amp;nbsp;is&amp;nbsp;possible&amp;nbsp;that&amp;nbsp;memory&amp;nbsp;usage&amp;nbsp;will&amp;nbsp;rise&amp;nbsp;rather&amp;nbsp;than&amp;nbsp;decrease.&amp;nbsp;To&amp;nbsp;combat&amp;nbsp;with&amp;nbsp;this&amp;nbsp;situation,&amp;nbsp;KSM+&amp;nbsp;employs&amp;nbsp;a&amp;nbsp;new&amp;nbsp;algorithm&amp;nbsp;to&amp;nbsp;decrease&amp;nbsp;the&amp;nbsp;memory&amp;nbsp;usage&amp;nbsp;for&amp;nbsp;running&amp;nbsp;itself.&amp;nbsp;Several&amp;nbsp;experiments&amp;nbsp;prove&amp;nbsp;that&amp;nbsp;the&amp;nbsp;KSM+&amp;nbsp;can&amp;nbsp;be&amp;nbsp;easily&amp;nbsp;applied&amp;nbsp;to&amp;nbsp;specified&amp;nbsp;applications&amp;nbsp;and&amp;nbsp;memory&amp;nbsp;usage&amp;nbsp;can&amp;nbsp;be&amp;nbsp;reduced.&amp;nbsp;And&amp;nbsp;a&amp;nbsp;case&amp;nbsp;is&amp;nbsp;designed&amp;nbsp;to&amp;nbsp;compare&amp;nbsp;the&amp;nbsp;effect&amp;nbsp;between&amp;nbsp;KSM&amp;nbsp;and&amp;nbsp;KSM+,&amp;nbsp;which&amp;nbsp;shows&amp;nbsp;KSM+&amp;nbsp;behaves&amp;nbsp;better&amp;nbsp;in&amp;nbsp;deduplication&amp;nbsp;when&amp;nbsp;the&amp;nbsp;same-content&amp;nbsp;pages&amp;rsquo;&amp;nbsp;density&amp;nbsp;is&amp;nbsp;very&amp;nbsp;low.&amp;nbsp;At&amp;nbsp;last,&amp;nbsp;in&amp;nbsp;order&amp;nbsp;to&amp;nbsp;inspect&amp;nbsp;the&amp;nbsp;characteristics&amp;nbsp;of&amp;nbsp;same-content&amp;nbsp;pages&amp;nbsp;from&amp;nbsp;normal&amp;nbsp;desktop&amp;nbsp;applications,&amp;nbsp;an&amp;nbsp;ad-hoc&amp;nbsp;kernel&amp;nbsp;module&amp;nbsp;is&amp;nbsp;developed&amp;nbsp;to&amp;nbsp;do&amp;nbsp;the&amp;nbsp;statistics&amp;nbsp;which&amp;nbsp;supplies&amp;nbsp;significant&amp;nbsp;data&amp;nbsp;for&amp;nbsp;the&amp;nbsp;further&amp;nbsp;development&amp;nbsp;of&amp;nbsp;KSM+.
  &lt;/p&gt;
  &lt;p&gt;
    Key&amp;nbsp;Words：&amp;nbsp;KSM,&amp;nbsp;Deduplication,&amp;nbsp;Memory&amp;nbsp;Management
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>epoll学习报告</title>
      <link>https://ykyi.net/?p=976/</link>
      <pubDate>Wed, 07 Aug 2013 12:01:31 +0000</pubDate>
      <guid>https://ykyi.net/?p=976/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    &amp;nbsp;epoll学习报告
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;kamuszhou&amp;nbsp;周霄&amp;nbsp;Jul/26/2013
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    这几天通读了内核中对epoll&amp;nbsp;I/O模型的实现代码，结合网络上很多介绍epoll的文章，对epoll的实现原理已经很熟悉，下面谈谈我的几点体会。下文引用的内核代码来自3.9.6版本的内核，见URL：&lt;a href=&#34;http://lxr.oss.org.cn/source/fs/eventpoll.c&#34;&gt;http://lxr.oss.org.cn/source/fs/eventpoll.c&lt;/a&gt;。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    一.&amp;nbsp;epoll的边沿触发(ET)的效率高于电平(LT)触发的效率
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;首先简单介绍一个背景：epoll实现中，把已经有事件发生的文件用一个双链表链接一起，这个双链表是在struct&amp;nbsp;eventpoll结构中的rdllist域。用户空间调用epoll_wait()，陷入内核后就会立即检查这个双链表，如果链表中非空，就通过文件的poll()函数询问文件有无事件发生。如果有事件发生且是用户关心的，就会向用户空间报告，否则就睡眠。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;epoll的实现代码中实际上只有两行代码与触发方式有关，如下图所示。
  &lt;/p&gt;
  &lt;p&gt;
    &lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;265&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-17809.png&#34; width=&#34;554&#34; /&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;上图所示的代码运行的上下文情况是：用户加入到epoll中的某个文件，只要支持poll()，(可以是socket，FIFO，裸设备，whatever)有关心的事件到达(或可读，或可写，或报错)，内核空间已经把发生的事件复制到了用户空间，但还没有从内核态返回用户空间。在返回用户空间之前代码检查用被epoll监视的这个文件是否是ET触发，如果不是(那就是LT),就把监视的文件重新放回就绪队列，下次epoll_wait()调用的时候会立即重新检查这个文件有否有事件到达。如果这文件的确有事件发生，则epoll_wait()报告给调用者。如果没有，而且其它被监视的文件也没有事件发生，则调用epoll_wait()的task就让出处理器，开始睡觉(TASK_INTERRUPTIBLE)。这段逻辑在static&amp;nbsp;int&amp;nbsp;ep_poll(struct&amp;nbsp;eventpoll&amp;nbsp;*ep,&amp;nbsp;struct&amp;nbsp;epoll_event&amp;nbsp;__user&amp;nbsp;*events,&amp;nbsp;int&amp;nbsp;maxevents,&amp;nbsp;long&amp;nbsp;timeout)中，第1494行。
  &lt;/p&gt;
  &lt;p&gt;
    如果监听的文件开启的是边沿触发(默认)，则不会执行上图中的list_add_tail()逻辑。这就是边沿触发只会向用户报告一次，直到下一个关心事件发生才向用户空间报告的原因。
  &lt;/p&gt;
  &lt;p&gt;
    那么为什么ET触发效率高于LT触发呢？看一个例子，假如客户端监视一个TCP的Socket，服务端这时发来1M数据，客户端的主机网卡驱动缓存足够大，一次性接收到了所有1M数据。下面看两段客户端的接收伪代码(没有写read调用返回时socket被关闭的情况；另socket描述符fd被设为非阻塞)。
  &lt;/p&gt;
  &lt;p&gt;
    &lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;164&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-26818.png&#34; width=&#34;487&#34; /&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;上图的代码使用了LT触发，这段代码依赖epoll_wait()通知还有数据可供读取。所以共调用了1024次epoll_wait()，1024次read()，共2048次系统调用才读完1M数据。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; height=&#34;242&#34; src=&#34;file:///C:\Users\KAMUSZ~1\AppData\Local\Temp\ksohtml\wps_clip_image-31492.png&#34; width=&#34;496&#34; /&gt;
  &lt;/p&gt;
  &lt;p&gt;
    上图使用ET触发，epoll_wait()只报告一次，然后代码循环调用1024次read()读完数据，直到第1025次read()返回-1，出错码为EAGAIN(EAGAIN等于EWOULDBLOCK)，于是代码知道已经接收完数据。一共只使用了1026次系统调用就读完了数据。
  &lt;/p&gt;
  &lt;p&gt;
    总结：即使使用电平触发也不要依赖epoll_wait()通知调用者到达事件，需要循环调用IO函数直到被通知EAGAIN，这样就把epoll_wait()的调用次数降到最低，仅管有可能在下次epoll_wait()时会有可能浪费一次文件的poll()调用，但这个很小的开销可以忽略。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    二.&amp;nbsp;为什么epoll支持嵌套调用
  &lt;/p&gt;
  &lt;p&gt;
    读epoll的实现代码发现，一个epoll的文件描述符epfd可以嵌套的加入另一个epoll。这样有什么用呢？
  &lt;/p&gt;
  &lt;p&gt;
    epoll的实现中&amp;ldquo;平等的&amp;rdquo;对待每个被监视的文件，它们维护在一棵红黑树之中，假如有十万个文件被监视，那么查找某个文件时就要在这十万个文件中查找。即使红黑树的查找效率是log(n)，文件非常大时也是比较消耗时间的。
  &lt;/p&gt;
  &lt;p&gt;
    那么假如有这样一种情况，如果这十万个文件中只有1000个是活跃的，或者说这1000个文件优先级最高。那么则有一种优化方案是，创建两个epoll，第一个epoll（epfd0）监控100000&amp;nbsp;&amp;#8211;&amp;nbsp;1000&amp;nbsp;个文件，第二个epoll&amp;nbsp;(epfd1)&amp;nbsp;监控1000个高优先级文件以及epfd0。这样的好处是，大多数情况下epoll实现只在1001个元素的红黑树中查找，自然效率提高了。
  &lt;/p&gt;
  &lt;p&gt;
    总结：epoll的嵌套调用给开发者提供了一个在高并发环境下的优化方案。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    三.&amp;nbsp;epoll的效率一定比select/poll高吗。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;答案是不一定。
  &lt;/p&gt;
  &lt;p&gt;
    Select的缺点大致有：
  &lt;/p&gt;
  &lt;p&gt;
    1.&amp;nbsp;内核中写死了最多只能监视1024个文件.
  &lt;/p&gt;
  &lt;p&gt;
    2.&amp;nbsp;每次调用select都要把关心的文件描述符和关心的文件件从一个用户空间的长长的数组拷贝到内核空间.
  &lt;/p&gt;
  &lt;p&gt;
    3.&amp;nbsp;select若使得caller进程进入睡眠后，某个文件有事件到达此进程被唤醒，那么所有被监视的文件全部会被调用poll()询问&amp;ldquo;你有没有事件到达&amp;rdquo;，这是一个线性的时间复杂度。
  &lt;/p&gt;
  &lt;p&gt;
    epoll针对select的三个缺点的改进：
  &lt;/p&gt;
  &lt;p&gt;
    1.&amp;nbsp;监视的文件数由取决于系统中有多少低端内存(x86_64架构中的所有内存都是低端内存)。3.9.6版本的内核实现中，对于每个登录用户，最多使用系统中低端内存的4%用来创建监视用的数据结构。见第1951行代码。max_user_watches&amp;nbsp;=&amp;nbsp;(((si.totalram&amp;nbsp;&amp;#8211;&amp;nbsp;si.totalhigh)&amp;nbsp;/&amp;nbsp;25)&amp;nbsp;&lt;&lt;&amp;nbsp;PAGE_SHIFT)&amp;nbsp;/&amp;nbsp;EP_ITEM_COST;
  &lt;/p&gt;
  &lt;p&gt;
    2.&amp;nbsp;用户只需要把关心的文件对应的数据结构在调用epoll_wait()前用epoll_ctl()一次性传入内存，以后调用epoll_wait()时不需要像select一样拷贝大量数据。
  &lt;/p&gt;
  &lt;p&gt;
    3.&amp;nbsp;当调用epoll_wait()的caller进程睡眠时，突然有事件到达，caller进程被唤醒，epoll_wait()返回用户空间，内核并不遍历没有监视的文件，而只报告在一个即短时间内发生的事件。下面更详细的描述这个场景，以监视tcp&amp;nbsp;socket举例，大致是：某进程调用epoll_wait()，此时没有任何它关心的事件发生，于是caller进程进入睡眠。处理器调度了其它进程。数据到达时，当前进程被硬件中断，网卡驱动收到数据包，数据包在中断处理函数中被拷入内核，中断处理函数设置中断下半部(Half&amp;nbsp;Bottom)。下半部被处理器调度，调用epoll实现代码注册的回调函数ep_poll_callback()。ep_poll_callback()函数唤醒之前的caller进程，caller进程重新获得CPU，从epoll实现的ep_poll()函数中恢复执行，在3.9.6内核中的第1564行：&amp;nbsp;if&amp;nbsp;(!schedule_hrtimeout_range(to,&amp;nbsp;slack,&amp;nbsp;HRTIMER_MODE_ABS))。然后，内核代码开始收集已经就绪的文件和发生的事件，发回用户空间。只有从第一次回调函数ep_poll_callback()被驱动的代码调用（caller进程还在睡眠时执行的ep_poll_callback()算第一次）到epoll实现代码走到第586行关闭中断关闭中断的代码&amp;nbsp;spin_lock_irqsave(&amp;ep-&gt;lock,&amp;nbsp;flags);之间发生的事件才会被收集。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对于第3点，这是epoll的优点，但在某种情况下却会是epoll的缺点。网上很多比较poll,&amp;nbsp;select,&amp;nbsp;epoll性能的文章，没来得及仔细看，我个人认为结论是可靠的。结论引入了一个概念active-to-total&amp;nbsp;ratio，设所有被监控的文件数是n，活跃的文件数是m，active-to-total比则是m/n，如果这个比非常高，比如大于0.7，则poll或select的性能要高过epoll，反之则epoll胜出。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对比前文对select的第3个缺点和epoll的改进点3的叙述可以解释这个原因。因为select在返回用户空间前又轮循了所有关心的文件，而这些文件又大部分是有事件发生的，所以select所做的工作并没有浪费，但epoll只收集了一小段时间中发生的事件，于是select较之epoll减少了用户空间和内核空间的频繁切换，从而让select的性能反超epoll。
  &lt;/p&gt;
  &lt;p&gt;
    那么如何改进呢？明白了以上的原因，那么就可以对epoll做出改进，理论上对于active-to-total比较高的应用环境下，可以在epoll的实现中加入与select做法相同逻辑，即退出前询问所有的监控文件，反正active-to-total比很高。或者更好的方案，用一个链表链接活跃的文件，在epoll返回用户空间前遍历这个链表，争取每一个epoll_wait()调用返回尽可能多的事件。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    附：epoll的主要数据结构简介.
  &lt;/p&gt;
  &lt;p&gt;
    epoll接口的主要数据结构有struct&amp;nbsp;eventpoll，struct&amp;nbsp;epitem，struct&amp;nbsp;eppoll_entry。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;在讲述这三个数据结构前先提一下struct&amp;nbsp;file。Unix设计初期希望它的设计遵从&amp;ldquo;一切皆文件&amp;rdquo;的理念。在Linux内核中，每个抽象的文件对应一个内核struct&amp;nbsp;file结构体。Struct&amp;nbsp;file结构体中有一个void&amp;nbsp;*private_data域。不同的文件类型会在private_data域中存放特定的信息。Struct&amp;nbsp;file中另一个域f_op是函数指针的列表，它记录了对应该文件的操作。所有epoll文件的f_op都指向static&amp;nbsp;const&amp;nbsp;struct&amp;nbsp;&lt;a href=&#34;http://lxr.oss.org.cn/ident?i=file_operations&#34;&gt;file_operations&lt;/a&gt;&amp;nbsp;&lt;a href=&#34;http://lxr.oss.org.cn/ident?i=eventpoll_fops&#34;&gt;eventpoll_fops&lt;/a&gt;，因此可以代码判断一个文件是不是epoll如下：
  &lt;/p&gt;
  &lt;p&gt;
    static&amp;nbsp;inline&amp;nbsp;int&amp;nbsp;is_file_epoll(struct&amp;nbsp;file&amp;nbsp;*f)
  &lt;/p&gt;
  &lt;p&gt;
    {
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;f-&gt;f_op&amp;nbsp;==&amp;nbsp;&amp;eventpoll_fops;
  &lt;/p&gt;
  &lt;p&gt;
    }
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;每次成功调用epoll_create时就会创建一个struct&amp;nbsp;file的结构体，和一个struct&amp;nbsp;eventpoll。Struct&amp;nbsp;file中的private_data指向struct&amp;nbsp;eventpoll。eventpoll维护了这个epoll的重要信息。其中比较重要的几个字段有：一个循环列表struct&amp;nbsp;list_head&amp;nbsp;&amp;nbsp;rdllist链接了该epll中已经可以读写或者有出错的文件描述符。一个红黑树的根结点struct&amp;nbsp;rb_root&amp;nbsp;&amp;nbsp;rbr，eventpoll维护了一棵红黑树，树中的结点是struct&amp;nbsp;epitem。
  &lt;/p&gt;
  &lt;p&gt;
    每个被加入到epoll中被关注的文件描述符都对应一个struct&amp;nbsp;epitem结构体。所有加入到同一个epoll中对应的所有epitem都挂在红黑树上。该红黑树的根结构保存在struct&amp;nbsp;eventpoll中。epitem中记录了对应的文件的文件描述符和文件指针。
  &lt;/p&gt;
  &lt;p&gt;
    struct&amp;nbsp;eppoll_entry是用来挂接到设备文件中的结构体。设备驱动在得知自己可读或可写或有错误时通过这个结构体通知有事件发生。每个eppoll_entry都指向一个epitem，一个epitem可能对应多个eppoll_entry。eppoll_entry中的域wait_queue_t&amp;nbsp;&amp;nbsp;wait就是被用来挂接到设备文件中的等待队列。设备文件通过wait可以拿到eppoll_entry，再通过eppoll_entry拿到epitem，再拿到eventpoll。
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>makefile使cpp文件依赖头文件</title>
      <link>https://ykyi.net/?p=974/</link>
      <pubDate>Wed, 07 Aug 2013 12:00:10 +0000</pubDate>
      <guid>https://ykyi.net/?p=974/</guid>
      <description>&lt;p&gt;读代码时发现目前工程中的makefile文件中有一个问题或bug，.即cpp文件没有和该.cpp文件include的头文件建立依赖性。这个危害是，当头文件被修改后，受影响的.cpp文件对应的.o文件不会被重新创建。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;而目前的代码中大量使用C++模板，模板的实现全部写在.h文件中.&lt;/p&gt;
&lt;p&gt;我做了个实验，修改了单件模板的实现文件 SingletonHolder.h。虽然这个修改影响了大量include了SingletonHolder.h的.cpp文件，但它们对应的.o全被没有被重新编译。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;解决方法是用g++编译器提供的 -MM 选项。这个选项会让g++在把.cpp依赖的头文件(除系统头文件)全部列出来。具体的使用方法可以查阅手册。思路是，把cpp文件和头文件的依赖性写入到.d文件，在主makefile文件中include所有的.d文件。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;以tcpd工程为列，修改后的makefile如下(亦见附件)，该makefile可以检查到.cpp依赖的头文件被修改，使得重新生成目标文件。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;include ./makefile.def&lt;/p&gt;
&lt;p&gt;SRCS = $(wildcard *.cpp)&lt;/p&gt;
&lt;p&gt;OBJS = $(patsubst %.cpp,%.o,$(SRCS))&lt;/p&gt;
&lt;p&gt;# 每个.cpp都对应一个.d文件，.d文件由g++ -MM生成，列出了.cpp依赖的头文件.&lt;/p&gt;
&lt;p&gt;DEPENDENCIES = $(subst .cpp,.d,$(SRCS))&lt;/p&gt;
&lt;p&gt;TARGET = tcpd&lt;/p&gt;
&lt;p&gt;OK = [\e[1m\e&lt;a href=&#34;file:///%5Ce%5B1m%5Ce%5b32m&#34;&gt;32m&lt;/a&gt; OK [\e&lt;a href=&#34;file:///%5Ce%5Bm&#34;&gt;m&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;FAILURE = [\e[1m\e&lt;a href=&#34;file:///%5Ce%5B1m%5Ce%5b31m&#34;&gt;31m&lt;/a&gt; FAILURE [\e&lt;a href=&#34;file:///%5Ce%5Bm&#34;&gt;m&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;all:$(TARGET)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;# 使包含.d文件，.d文件指定了.o文件依赖哪些头文件。&lt;/p&gt;
&lt;p&gt;# 如果不是make clean 就include所有的.d文件。&lt;/p&gt;
&lt;p&gt;ifneq &amp;ldquo;$(MAKECMDGOALS)&amp;rdquo; &amp;ldquo;clean&amp;rdquo;&lt;/p&gt;
&lt;p&gt;  -include $(DEPENDENCIES)&lt;/p&gt;
&lt;p&gt;endif&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;# 此函数生成.d文件，参考g++的 -MM -MF -MT选项&lt;/p&gt;
&lt;p&gt;#$(call make-depend,source-file,object-file,depend-file)&lt;/p&gt;
&lt;p&gt;define make-depend&lt;/p&gt;
&lt;p&gt;  g++ -MM -MF $3 -MT $2 $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $1&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux桌面环境下内存去重技术的研究与实现(第二章)</title>
      <link>https://ykyi.net/?p=971/</link>
      <pubDate>Tue, 04 Jun 2013 03:03:51 +0000</pubDate>
      <guid>https://ykyi.net/?p=971/</guid>
      <description>&lt;h1 id=&#34;linux桌面环境下内存去重技术的研究与实现&#34;&gt;Linux桌面环境下内存去重技术的研究与实现&lt;/h1&gt;
&lt;h1 id=&#34;在这里可以下载原稿wwwykyinetuploadresearch_and_implementation_of_memory_deduplication_in_the_linux_desktop_environmentpdf&#34;&gt;&lt;strong style=&#34;font-size: 13px;&#34;&gt;&lt;a href=&#34;http://www.ykyi.net/upload/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;span style=&#34;color: rgb(255, 0, 0);&#34;&gt;在这里可以下载原稿 www.ykyi.net/upload/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id=&#34;第二章-相关理论与技术&#34;&gt;第二章 相关理论与技术&lt;/h1&gt;
&lt;h2 id=&#34;21-内存管理&#34;&gt;2.1 内存管理&lt;/h2&gt;
&lt;p&gt;内存管理是操作系统内核中极为重要的部分，它涉及物理地址、虚拟地址、分段、分页等诸多概念。&lt;/p&gt;
&lt;h3 id=&#34;211-内存地址&#34;&gt;2.1.1 内存地址&lt;/h3&gt;
&lt;p&gt;程序使用地址来访问内存单元。对于x86架构的中央处理器，使用逻辑地址，虚拟地址，物理地址三种不同的地址&lt;sup&gt;[15]&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;逻辑地址包括段和偏移地址两部分，它们共同用来指定机器指令或者操作数在内存中的位置。逻辑地址对应下文提到的分段式内存管理。&lt;/p&gt;
&lt;p&gt;虚拟地址也被称作线性地址，它表示一个寻址空间。在Linux操作系统中，使用一个无符号长整型存储虚拟地址。如果是针对32位x86处理器的内核，这是一个32位的无符号长整型，可以寻址至多2&lt;sup&gt;32&lt;/sup&gt;，即4GB空间。而Linux在x86_64处理器上，一个无符号长整型有64位，但实际上只使用了48位，即可寻址到2&lt;sup&gt;48&lt;/sup&gt; ，即256TB的内存空间。引入虚拟地址使得用户空间的进程都独自拥有一个地址空间，方便操作系统在硬件的协助下隔离进程访问内存的操作，从而实现更高的安全性和便捷性。在32位处理器架构下，4G虚拟地址空间划分成两部分，高端的1G空间被称之为内核空间，低端的3G空间称之为用户空间。内核的代码和数据存在内核空间，用户空间的进程通过系统调用陷入内核空间执行内核空间的代码。对于64位处理器，虚拟地址同样分为内核空间和用户空间，只是针对64位处理器的内核拥有大得多的寻址范围，对内核空间和用户空间的地址划分有多种实现。&lt;/p&gt;
&lt;p&gt;物理地址被中央处理器用来寻址内存芯片上的实际的物理单元。它对应了送往处理器的针脚上的高低电平信号。&lt;/p&gt;
&lt;p&gt;       Linux中的内存管理单元 (Memory Management Unit, MMU)在硬件电路的帮助下把逻辑地址译成线性地址；而另一个硬件电路则帮助把线性地址翻译成物理地址。&lt;/p&gt;
&lt;h3 id=&#34;212-段页式内存管理&#34;&gt;2.1.2 段页式内存管理&lt;/h3&gt;
&lt;p&gt;内存分段是由80×86处理器引入的概念，它鼓励程序员在设计程序时把程序使用的内存按照逻辑上的意义相关性分成若干个部分，比如有些段存放全局数据，有些段存放程序代码&lt;sup&gt;[16]&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;内存管理单元的分页单元协助把虚拟地址译为物理地址，为了提高翻译的效率，虚拟地址被按照固定长度切分成一个个小单元，它们则被称之为页面。页面可以看成是MMU管理内存的最小单位。&lt;/p&gt;
&lt;p&gt;      分段和分页都用来划分内存，在某种程度上，它们的功能有一定重合。实际上，Linux内核的内存管理机制倾向于使用分页技术。Linux进程运行在用户空间时使用的标志代码段的代码段选择子(segmentation selector)和数据段选择子是相等的；进程运行在内核空间时使用的代码段选择子和数据段选择子也是相等的。而且这四个段选择子的段基址都设置为0。这意味着在Linux操作系统中，无论寻址数据和还是寻址指令，无论在用户空间还是内核空间，逻辑地址的段基址部分为0，偏移地址部分刚好等于虚拟地址。&lt;/p&gt;
&lt;p&gt;在Linux所支持的大多数硬件平台上，默认的页面大小是4K。但Linux同时也支持大于4K的页面的内存管理。运行在用户空间的代码可以使用glibc库中的getpagesize()函数得到当前使用的页面大小。本论文只针对在x86_64架构上页面大小是4K的Linux内核。实际上从内核2.6.38开始，内核中开始支持透明巨页(Transparent Huge Page)&lt;sup&gt;[17]&lt;/sup&gt;，内核中有些页面的大小实际上是2M，但这不影响按照4K的页面大小展开讨论。&lt;/p&gt;
&lt;p&gt;Linux使用分级页表的方式把虚拟地址映射到页面。在32位处理器上使用二级页表，在x86_64架构的处理器上则使用四级页表。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  图2-1 四级页表
&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;       如图2-1所示，以针对x86_64架构处理器的Linux内核为例，64位虚拟地址的高16位不被使用，低48位被平均分为5段，offset段占12位，其它四个段各占9位。这个划分在源代码文件arch/x86/include/asm/pgtable_64_types.h中定义。cr3寄存器存储了页全局目录的物理地址。在把虚拟地址翻译到物理地址的过程中，MMU先从cr3寄存器中取出全局目录的物理地址，再加上GLOBALDIR段算出的偏移量，从而在页全局目录中得到页上级目录的物理地址。与此类似，从页上级目录中得到页中间目录的地址，然后得到页表的地址，再得到页面的地址，最后的OFFSET字段则定位到页面中的一个字节。至此，虚拟地址被翻译到了物理地址。&lt;/p&gt;
&lt;p&gt;页全局目录，页上级目录，页中间目录，以及页表中的每一项都由相同的数据结构表示。它记载了一些重要的信息，与本论文相关的信息有：该项指向的下一级表或者页面是否存在的标志，如果访问时不存在则产生缺页中断，由do_page_fault函数负责把页面调入内存&lt;sup&gt;[18]&lt;/sup&gt;；下一级表或页面的物理地址；下一级表或页面是否可读可写的标志，利用该标志位可以写保护一个页面。&lt;/p&gt;
&lt;p&gt;Linux内核用一个struct page结构体描述一个页面的信息。这个结构体定义在include/linux/mm_types.h文件中&lt;sup&gt;[19]&lt;/sup&gt;。图2-2列出这个结构体中与本论文直接相关的字段。&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  图2-2 struct page的部分字段
&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;其中的flags字段存储了页面的状态信息，例如：表示页面刚被写了数据的脏位；该页面是否被锁定在内存中不充许置换到交换分区的标志。_count字段和_mapcount字段都是引用计数，它们用来共同维护page页面的生命期。_mapcount表示一个页面拥有多少页表项指向它，_count被称为page的使用计数，所有的_mapcount计数只相当于_count计数中的一次计数。如果内核代码中某执行序列在访问某个页面时需要确保该页面存在，则在访问前给_count计数加一，访问结束后_count计数减一。当_count计数减到负数时表示没有任何内核需要使用该页面，则表示该页面没被使用。内核代码不应该直接访问_count计数，而应该使用page_count函数。该函数用一个struct page的指针做为参数，当该页空闲时函数返回0，否则返回一个正数表示参数指向的页面正被使用。当页面被页高速缓冲使用时，mapping域指向一个address_space对象，该对象与Linux文件系统中的文件是一对一映射的关系，描述了一个文件分配到的物理页面及相关数据结构。如果页面并不被页高速缓冲使用时，mapping则有其它的意义，比如mapping字段的最低位记载这是否是一个匿名页面。virtual字段是映射到该页面的内核空间的虚拟地址，如果该页面是属于高端内存区域则virtual字段为NULL。对于x86_64架构上的Linux内核，已经没有高端内存，因此该字段不会为NULL。&lt;/p&gt;
&lt;h3 id=&#34;213-内核中的巨页&#34;&gt;2.1.3 内核中的巨页&lt;/h3&gt;
&lt;p&gt;现代处理器的内存管理单元几乎都能处理除4KB大小外的多种页面尺寸。然而，Linux内核在几乎所以平台上的实现都选用最小的页面大小，即4KB，比4KB更大的页面，都被称之为巨页(huge page)。在某些工作环境下，巨页可以给操作系统带来性能上的提高。巨页能提高操作系统的性能主要是因为两点。第一，使用巨页可以减少发生页面出错处理的频率，因为在每次页面出错处理时内核调入比使用小页面更多的内存。第二，使用巨页减少翻译虚拟地址的时间。在x86_64加构的处理器上，从虚拟地址翻译到物理地理需要依次访问四级页表，非常耗时。而使用巨页可以减少页表的级数。实际上更大的性能提高源自使用巨页后提高了旁路转换缓冲区(Translation Lookaside Buffer，TLB)的命中效率&lt;sup&gt;[20]&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;在内核2.6.38版本之前，唯一使用巨页的方式是通过非常复杂的hugetlbfs文件系统。应用程序开发者和系统管理员都需要注意一些特别事项才能够开启巨页功能。因此只有极少数真正需要巨页带来性能提高的用户，如专用数据库系统，才使用巨页。&lt;/p&gt;
&lt;p&gt;情况从内核版本2.6.38以后发生了变化，一个被称之为透明巨页的功能被合并进了内核主干代码。之前内核在VMA（Virtual Memory Area，虚拟内存区域）中的所有页面大小都是一样大的，而加入透明巨页后，VMA中的页面的大小可能不只一种。透明巨页的实现代码改写了页面出错处理函数，当一个出错发生时，内核尽力分配一个巨页，如果成功的话，其它相应的在巨页地址范围内的小页面就会被释放，巨页被插入到VMA中。如果不能分配到一个巨页，则仍然按照以前的方式分配一个小页面。当巨页需要被置换到交换分区时，透明巨页机制简单地把巨页切割成小页面，其它逻辑和处理小页面时一样。实际上不仅在置换到交换分区时需要切割巨页，很多其它的操作，如mprotect()和mlock()页面时也需要。本论文将详述的KSM在合并页面时同样需要把巨页切割成小页面。&lt;/p&gt;
&lt;p&gt;透明巨页这种轻便地利用巨页的方式使得很多内核代码并没有感知到巨页的存在，对于应用程序则更没有感知到巨页，因此被称之为透明巨页。&lt;/p&gt;
&lt;h3 id=&#34;214-内存描述符&#34;&gt;2.1.4 内存描述符&lt;/h3&gt;
&lt;p&gt;Linux内核使用一个叫内存描述符(Memory Descriptor)的结构体描述每一个进程的地址空间&lt;sup&gt;[21]&lt;/sup&gt;。这个结构体包括了所有和进程地址空间相关的信息。内存描述符和struct page一样在文件include/linux/mm_types.h中定义。图2-3列出这个结构体中与本论文直接相关的字段。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  图2-3 struct mm_struct的部分字段
&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;其中，mmap字段是用来实现一个链表。这个链表链接了属于这个内存描述符的所有vm_area_struct结构体。vm_area_struct结构体描述了一个内存区域。由于属于一个内存描述符的内存区域可能非常多，为了加快内存区域的查找以及添加删除等操作的速度，内核用mm_rb表示一棵链接了所有内存区域的红黑树。红黑树是一种二叉树，它被广泛地应用在Linux内核代码中。mmap和mm_rb是用两种不同的数据结构表示同一批数据。mm_users和mm_count是内存描述符的引用计数，它的实现原理和struct page的引用计数的原理一样。每一个进程如果拥有一个内存描述符，则会增加mm_users的计数，所有mm_users的计数只相当于mm_count的一个计数。比如n个Linux线程共享同一个内存描述符，那么对应的内存描述符的mm_users计数则为n，而mm_count则可能只是1。如果有内核执行序列想要访问一个内存描述符，则该执行序列先增加mm_count的计数，使用结束后减少mm_count的计数。一但mm_count减为0，表示该内存描述符没有任何引用，则它会被内核销毁。mmap_sem是一个读写锁，凡是需要操作内存描述符中的内存区域时，则需要先得到相应的读锁或者写锁，使用结束后释放该锁。mm_list字段是一个循环双链表。它链接了系统中所有的内存描述符。flags字段定义了内存描述符的标志，这些标志标记了内存描述符的一些状态和属性，内核代码需要使用原子操作访问该字段。&lt;/p&gt;
&lt;h3 id=&#34;215-虚拟内存区域&#34;&gt;2.1.5 虚拟内存区域&lt;/h3&gt;
&lt;p&gt;同样被定义在inlude/linux/mm_types.h中的结构体vm_area_struct用来描述一个内存区域。在Linux内核中，内存区域经常被称之为虚拟内存区域(Virtual Memory Areas,VMA)。VMA描述的内存区域是一个地址空间中的地址连续的部分。而且该部分拥有一些特定的属性，比如访问权限和相关联的操作等。不同的VMA可以用来描述不同的内存区域。比如，映射到内存的文件，用户空间的栈，特别是本论文重点关注的匿名内存区域(Anonymous VMA)。下面讨论本论文关心的vm_area_struct的一些重要字段，这些字段如图2-4所示。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux桌面环境下内存去重技术的研究与实现(第一章)</title>
      <link>https://ykyi.net/?p=967/</link>
      <pubDate>Sat, 01 Jun 2013 09:00:14 +0000</pubDate>
      <guid>https://ykyi.net/?p=967/</guid>
      <description>&lt;h1 id=&#34;linux桌面环境下内存去重技术的研究与实现&#34;&gt;Linux桌面环境下内存去重技术的研究与实现&lt;/h1&gt;
&lt;h1 id=&#34;在这里可以下载原稿httpsasgoodasgoldresearch_and_implementation_of_memory_deduplication_in_the_linux_desktop_environmentpdf&#34;&gt;&lt;strong style=&#34;font-size: 13px;&#34;&gt;&lt;a href=&#34;https://as.goodas.gold/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;span style=&#34;color: rgb(255, 0, 0);&#34;&gt;在这里可以下载原稿 https://as.goodas.gold/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id=&#34;第一章-绪论&#34;&gt;第一章 绪论&lt;/h1&gt;
&lt;h2 id=&#34;11-课题背景&#34;&gt;1.1 课题背景&lt;/h2&gt;
&lt;p&gt;内存是操作系统中最为重要的资源之一。为了最有效地利用好有限的内存资源，现代操作系统使用了很多技术以节省内存的使用。在Linux程序的内存布局中，代码段具有只读属性，永远是共享的。具体地说，即使一个程序被实例化了多个进程，但是在物理内存中对于该程序的代码只有一份拷贝，同一个程序的不同进程之间共享这份拷贝。而且，所有共享库（Windows下被称之为动态链接库）的代码段在物理内存中也只有一份拷贝&lt;sup&gt;[1]&lt;/sup&gt;，所有加载了该共享库的进程虽然把共享库加载到了不同的虚拟地址中，但实际上都映射到相同的物理地址上以实现对共享库代码区的共享。除了共享只读的代码区外，可写的页面也可能在进程之间被共享，Linux在创建进程时的fork操作使用写时拷贝技术在父子进程之间共享内存。当父进程调用fork()函数后，所有的可写页面转成写时拷贝页面。只要父子进程都不写入某页面，则该页面一直被共享。&lt;/p&gt;
&lt;p&gt;近年来，Linux操作系统中出现了一种新的节省内存的技术，它的出现源于云计算的发展。云计算能够通过互联网按需分发计算机的软硬件资源，被称之为IT产业的又一次革命&lt;sup&gt;[2]&lt;/sup&gt;。虚拟机技术是云计算的基础，Xen和KVM(Kernel Virtual Machine，内核虚拟机)是开源社区最流行的两种虚拟化技术&lt;sup&gt;[3]&lt;/sup&gt;。通过运用虚拟化技术，越来越多的Linux主机上同时运行着多个虚拟机，而虚拟机使用了相同的操作系统，操作系统中运行着相同的大型程序，如数据库服务器，邮件服务器，Web服务器等。在运行多个虚拟机的环境下，人们发现虚拟机之间存在着大量的相同内存页面，但Linux主机没有办法共享这些内存页面。为了解决虚拟机之间大量重复内存的问题，Linux社区诞生了KSM(Kernel Samepage Merging，内核相同页面合并)技术。KSM技术通过扫描内存区域，找到相同的内存页面，并把它们合并。该技术使得运行虚拟机的主机使用的内存明显下降，从而让同样的Linux主机在使用KSM技术后能运行更多的虚拟机。&lt;/p&gt;
&lt;p&gt;KSM技术虽然是为基于KVM技术的虚拟机设计，但也能运用到普通的桌面应用程序。随着软硬件技术的不断进步，Linux桌面应用程序占用的内存也越来越多。普通的Linux桌面应用程序中存在多少重复页面，重复页面的分布有些什么特点，把KSM技术运用在桌面应用程序上存在什么问题，这些是本论文将要探讨的内容。针对桌面应用程序的重复内存，本文在KSM的基础上开发了KSM+，能方便有效地合并桌面应用程序的重复内存。&lt;/p&gt;
&lt;h2 id=&#34;12-国内外研究现状&#34;&gt;1.2 国内外研究现状&lt;/h2&gt;
&lt;p&gt;对于传统的节约内存技术，如共享只读代码区，fork的写时拷贝技术。这些技术非常成熟，现代操作系统中已经普通采用。&lt;/p&gt;
&lt;p&gt;另外，文献&lt;sup&gt;[4]&lt;/sup&gt;研究了一种比较特殊的节省内存技术。它针对的是科学计算中的特殊程序，通过用注释驱动的工具把源代码转译到更高效的代码，于是编译出节省内存的程序。&lt;/p&gt;
&lt;p&gt;近年来研究较多的是基于合并相同内存页面的内存去重技术：通过查找系统中的相同内存页面，把这些页面合并从而节省系统内存。但国内外的研究基本集中在运行虚拟机的场景中。如VMware公司较早进行了虚拟机内存去重技术的研究工作，文献&lt;sup&gt;[5]&lt;/sup&gt;研究了VMware公司的Hypervisor(虚拟机管理器)使用的基于合并相同内容内存页面的去重技术，以减少虚拟机之间的内存冗余。文献&lt;sup&gt;[6]&lt;/sup&gt;详细论述了此类技术对于基于Xen的虚拟机的实现。Linux社区的类似技术称之为KSM。文献&lt;sup&gt;[7]&lt;/sup&gt;以实证研究的方式通过大量实验研究了KSM用于合并虚拟机之间冗余内存的性能。文献&lt;sup&gt;[8]&lt;/sup&gt;研究的是在数据中心中如何提高在虚拟机之间合并相同内存的效率。它实现了通过把虚拟机在各物理机中动态迁移到最适合的位置从而提高合并效率。文献&lt;sup&gt;[9]&lt;/sup&gt;使用KSM技术解决了主机和虚拟机都需要维护自己的缓存的问题，提高了缓存的效率。KSM技术并不是总能高效地去除虚拟机之间的冗余内存，也存在一些问题。内存地址的ASLR(Address Space Layout Randomization，空间布局随机化技术)是为了提高程序安全性的一种技术。该技术提高了程序的安全性，却影响了页面对齐，从而影响了KSM的合并效率&lt;sup&gt;[10]&lt;/sup&gt;。另外，KSM的运用也暴露了安全问题。运行在某台虚拟机上的程序可以通过构造特定的页面尝试让主机的KSM合并它，再计算写该页面所用的时间。因为写被KSM合并的页面的时候会发生写时拷贝，所以这个时间会比正常情况下延迟。通过利用这个时间差，运行在一台虚拟机上的程序可能会发现其它虚拟机上运行的程序&lt;sup&gt;[11]&lt;/sup&gt;，甚至让虚拟机之间秘密通信&lt;sup&gt;[12]&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;KSM技术应用在非虚拟机的场景下的研究则比较少。欧洲核子研究组织(CERN)的核子实验模拟程序产生海量的数据，并且并行工作的科学程序同时载入这些数据，使得内存中有大量的相同内容页面。CERN通过使用钩子技术修改C运行库的malloc()从而运行KSM，解决了内存中的大量重复页面的问题，节省了8%-48%的内存&lt;sup&gt;[13]&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;本论文将在一般桌面应用环境下研究并增强新的内存节省技术KSM，使之更适合运用在桌面应用环境下，更有效地减少应用程序的内存使用量。&lt;/p&gt;
&lt;h2 id=&#34;13-研究意义&#34;&gt;1.3 研究意义&lt;/h2&gt;
&lt;p&gt;内存资源总是操作系统中稀缺的资源，研究节省内存的技术具有普遍的意义。另外，随着基于Linux内核的操作系统如Android在消费电子终端上的迅速普及&lt;sup&gt;[14]&lt;/sup&gt;，以及可预见到基于Linux的Chrome OS在PC桌面市场也将占有一定市场，而目前的应用程序普遍占用越来越多的内存，研究Linux平台下新的节省内存的技术KSM，对于开发Android平台等基于Linux内核的平台下的商用优化管理软件具有重要的技术指导作用。&lt;/p&gt;
&lt;h2 id=&#34;14-论文的主要工作&#34;&gt;1.4 论文的主要工作&lt;/h2&gt;
&lt;p&gt;      本论文重点研究了Linux内核的KSM模块的设计与实现，并在原来的基础上做了针对桌面应用环境的增强与改进，同时认真研究了Linux内核代码的组织方式，配置与编译方式，内核开发及调试的技术，以及Linux的内存管理单元的实现。增强后的KSM命名为KSM+,它比原来的KSM更方便地自动采集到应用程序的相同内容页面并合并这些页面，以达到节省应用程序消耗的内存的目的。论文用多个实验展示了KSM+的功能，并与修改前的KSM做了比较。此外，本论文还编写了内核模块用于统计Linux桌面应用程序的重复内存页面的特点，同时可以用来应证KSM+运行的效果。&lt;/p&gt;
&lt;h2 id=&#34;15-论文的整体结构布局&#34;&gt;1.5 论文的整体结构布局&lt;/h2&gt;
&lt;p&gt;    本论文的第二章介绍了x86体系的段页式内存管理方式，以及Linux的内存管理的实现，还介绍了编写Linux内核代码的一些基本理论。&lt;/p&gt;
&lt;p&gt;第三章介绍了如何使用KSM以及KSM的设计和实现原理。&lt;/p&gt;
&lt;p&gt;第四章讲述KSM+的设计与实现。KSM+是在KSM的基础上的增强与改进。&lt;/p&gt;
&lt;p&gt;第五章用多个实验展示了KSM+合并程序的重复内存页面的效果，并设计了一个实验比较了KSM和KSM+的差别。最后编写了用于统计应用程序重复内存页面的内核模块，并用统计数据应证了KSM+的实验结果。这些统计数据反映了Linux桌面应用程序中重复内存页面的一些基本特点，对进一步改进KSM+的算法提供了依据。&lt;/p&gt;
&lt;h2 id=&#34;16-本章小结&#34;&gt;1.6 本章小结&lt;/h2&gt;
&lt;p&gt;      本章首先介绍了Linux操作系统中传统的节省内存技术，然后引入了因为虚拟化兴起而发展的新的内存节省技术，它通过合并内容相同的内存页面从而减少系统的内存使用，也被称之为内存去重技术，接着叙述了国内外在该技术方面的相关研究。目前对该技术的研究多针对虚拟机环境，而本论文则是在Linux桌面环境中研究内存去重技术。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux桌面环境下内存去重技术的研究与实现(中英文摘要)</title>
      <link>https://ykyi.net/?p=957/</link>
      <pubDate>Mon, 27 May 2013 14:28:12 +0000</pubDate>
      <guid>https://ykyi.net/?p=957/</guid>
      <description>&lt;h1 id=&#34;linux桌面环境下内存去重技术的研究与实现&#34;&gt;Linux桌面环境下内存去重技术的研究与实现&lt;/h1&gt;
&lt;h1 id=&#34;在这里可以下载原稿wwwykyinetuploadresearch_and_implementation_of_memory_deduplication_in_the_linux_desktop_environmentpdf&#34;&gt;&lt;strong style=&#34;font-size: 13px;&#34;&gt;&lt;a href=&#34;http://www.ykyi.net/upload/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;span style=&#34;color: rgb(255, 0, 0);&#34;&gt;在这里可以下载原稿 www.ykyi.net/upload/Research_and_Implementation_of_Memory_Deduplication_in_the_Linux_Desktop_Environment.pdf&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;论文题目： Linux桌面环境下内存去重技术的研究与实现&lt;/p&gt;
&lt;p&gt;专业：软件工程&lt;/p&gt;
&lt;p&gt;硕士生：周霄&lt;/p&gt;
&lt;p&gt;指导教师：王常吉&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  &lt;strong&gt;摘&amp;nbsp; 要&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;内存管理是操作系统中至关重要的部分。优秀的操作系统高效地管理有限的内存资源。Linux内核的内核同页合并（KSM）模块是在虚拟化兴起后为节省虚拟机使用的内存而发展的一种节约内存的技术。KSM通过合并相同内容页面的方式显著地降低了多个基于内核虚拟机（KVM）技术的虚拟机同时运行时系统使用的内存。实际上，KSM也能合并一般应用程序中的相同内容页面。但一般应用程序为了使用KSM技术合并内存，需要在源代码级别显式地调用相应的系统调用来告知KSM需要扫描的内存区域。对于一般用户来说，需要修改应用程序的源代码显然是一个太高的门槛。&lt;/p&gt;
&lt;p&gt;本论文在认真研究了KSM模块的实现的基础上，增强了KSM的功能。新设计实现的KSM+使得用户可以不必修改应用程序的源代码就能利用KSM+合并相同内容的内存页面。另外原来的KSM算法依赖程序指定的内存区域有大量的重复内存页面，而实际上，一般应用程序并没有大量的重复内存。在重复内存非常少的情况下，对这些程序应用KSM技术非但不能降低内存使用，而且因为运行KSM本身所需内存而增加了内存开销。本论文针对这一点在KSM的算法上做了改进，减少了运行KSM+算法本身所消耗的内存。然后论文用Linux桌面下的常用应用程序验证了KSM+的实际效果，并构造了一个实验比较了KSM和KSM+。最后，为了了解应用程序的重复内存页面的特点，还编写了专门统计重复页面的内核模块，发现应用程序的重复页面的一些规律，为持续改进KSM+提供了依据。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;**关键词：**KSM，重复内存合并 ，内存管理&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Title: Research and Implementation of Memory Deduplication in The Linux Desktop Environment&lt;/p&gt;
&lt;p&gt;Major: Software Engineering&lt;/p&gt;
&lt;p&gt;Name: Zhou Xiao&lt;/p&gt;
&lt;p&gt;Supervisor: Wang Changji&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
  &lt;strong&gt;Abstract&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;Memory management is one of the most important parts of the operating system. KSM (Kernel Samepage Merging) in Linux kernel is a kind of memory saving technology developed after the emerging of virtual machine. KSM can dramatically decrease the memory usage of the hypervisor running several virtual machines. Actually, KSM can also be applied to normal applications. But in order to use the KSM, application must explicitly evoke a system call in source code level to tell KSM the memory area where the KSM will scan. To normal users, modifying the source code is impossible at most of the time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>泪流满面，WARNING: modpost: Found 1 section mismatch(es).</title>
      <link>https://ykyi.net/?p=942/</link>
      <pubDate>Thu, 28 Feb 2013 02:02:31 +0000</pubDate>
      <guid>https://ykyi.net/?p=942/</guid>
      <description>&lt;p&gt;看来编译时出现警告要非常重视，一定要对警告的意义非常清楚，这极可能是出现BUG的原因。&lt;/p&gt;
&lt;p&gt;昨天调了一整个晚上，各种离奇的出错~~&lt;/p&gt;
&lt;p&gt;其实编译内核模块时，已经提示我警告了，但我一直没注意：&lt;/p&gt;
&lt;p&gt;  Building modules, stage 2.&lt;br&gt;
  MODPOST 1 modules&lt;br&gt;
WARNING: modpost: Found 1 section mismatch(es).&lt;br&gt;
To see full details build your kernel with:&lt;br&gt;
&amp;lsquo;make CONFIG_DEBUG_SECTION_MISMATCH=y&amp;rsquo;&lt;br&gt;
  CC      /home/zausiu/linux-3.0.66/mm/sksm/sksm.mod.o&lt;br&gt;
  LD [M]  /home/zausiu/linux-3.0.66/mm/sksm/sksm.ko&lt;/p&gt;
&lt;p&gt;警告告诉我使用 &lt;span style=&#34;font-size: 13px;&#34;&gt;&amp;lsquo;make CONFIG_DEBUG_SECTION_MISMATCH=y&amp;rsquo;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size: 13px;&#34;&gt;我以为要编译整棵kenel sourcecode tree时打开DEBUG_SECTION_MISMATCH编译选项，在我的虚机里编译一次要几个小时啊，果断拒绝了。其实在内核代码树外单独编译内核模块时也只用DEBUG_SECTION_MISMATCH=y这个选项。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size: 13px;&#34;&gt;# make DEBUG_SECTION_MISMATCH=y&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size: 13px;&#34;&gt;…&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  Building modules, stage 2.&lt;br&gt;
  MODPOST 1 modules&lt;br&gt;
WARNING: /home/zausiu/linux-3.0.66/mm/sksm/sksm.o(.init.text+0x193): Section mismatch in reference from the function init_module() to the function .exit.text:sksm_slab_free()&lt;br&gt;
The function __init init_module() references&lt;br&gt;
a function __exit sksm_slab_free().&lt;br&gt;
This is often seen when error handling in the init function&lt;br&gt;
uses functionality in the exit path.&lt;br&gt;
The fix is often to remove the __exit annotation of&lt;br&gt;
sksm_slab_free() so it may be used outside an exit section.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GCC内联汇编写的memcmp函数 for x86-64</title>
      <link>https://ykyi.net/?p=933/</link>
      <pubDate>Sun, 17 Feb 2013 12:32:07 +0000</pubDate>
      <guid>https://ykyi.net/?p=933/</guid>
      <description>&lt;p&gt;今天写内核代码时要写一个比较两个页框(Page Frame)的函数，想到用内联汇编来写这个功能。下面是代码：&lt;/p&gt;
&lt;p&gt;long cmp_x64(void *s1, void *s2, size_t n)&lt;br&gt;
{&lt;br&gt;
    size_t num = n / 8;&lt;br&gt;
    register long res;&lt;/p&gt;
&lt;p&gt;    __asm__ __volatile__&lt;br&gt;
    (&lt;br&gt;
     &amp;ldquo;testq %3,%3\n\t&amp;rdquo;               ; 测试num是不是0&lt;br&gt;
     &amp;ldquo;repe  cmpsq\n\t&amp;rdquo;                ; 不停地比较直到cx寄存器为0或比较到差别&lt;br&gt;
     &amp;ldquo;je        1f\n\t&amp;rdquo;              ; 两块内存相等，跳出，返回0.&lt;br&gt;
     &amp;ldquo;sbbq      %0,%0\n\t&amp;rdquo;    ; sbb是x86的减法指令，会额外地减去CF(借位)的值，这样%0就会是0或者-1&lt;br&gt;
     &amp;ldquo;orq       $1,%0\n&amp;rdquo;         ; 把立即数1或到%0上，这样%0就会是1或者-1.&lt;br&gt;
     &amp;ldquo;1:&amp;rdquo;&lt;br&gt;
         : &amp;ldquo;=&amp;amp;a&amp;rdquo;(res)          ;  传入变量res放入寄存器ax，且这个变量是输出值(=)，不要与其它输入输出共用寄存器(&amp;amp;)&lt;br&gt;
     : &amp;ldquo;0&amp;rdquo;(res), &amp;ldquo;S&amp;rdquo;(s1), &amp;ldquo;D&amp;rdquo;(s2), &amp;ldquo;c&amp;rdquo;(num)  ; 输入列表&lt;br&gt;
     : &amp;ldquo;cc&amp;rdquo;);           // clobber list 告诉gcc在这段内联汇编中哪些寄存器被显式/隐式修改.&lt;span style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; line-height: normal;&#34;&gt;If our instruction can alter the condition code register, we have to add &amp;ldquo;cc&amp;rdquo; to the list of clobbered registers.&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux内核中的宏可变参数(GCC的宏可变参数)</title>
      <link>https://ykyi.net/?p=931/</link>
      <pubDate>Sun, 17 Feb 2013 05:10:42 +0000</pubDate>
      <guid>https://ykyi.net/?p=931/</guid>
      <description>&lt;pre style=&#34;color: rgb(0, 0, 0); line-height: normal; word-wrap: break-word; white-space: pre-wrap;&#34;&gt;Linux内核中的宏可变参数(GCC的宏可变参数)。
写内核模块的时候为了调试方便，经常需要wrap一下printk函数。下面的宏定义非常有实用价值。
注意两个井号~~
记到博客里~~

#define seclvl_printk(verb, type, fmt, arg...)			\
	do {							\
		if (verbosity &amp;gt;= verb) {			\
			static unsigned long _prior;		\
			unsigned long _now = jiffies;		\
			if ((_now - _prior) &amp;gt; HZ) {		\
				printk(type &#34;%s: %s: &#34; fmt,	\
					MY_NAME, __FUNCTION__ ,	\
					## arg);		\
				_prior = _now;			\
			}					\
		}						\
	} while (0)&lt;/pre&gt;</description>
    </item>
    <item>
      <title>今天用Debian时总遇到locale的错误.</title>
      <link>https://ykyi.net/?p=925/</link>
      <pubDate>Thu, 14 Feb 2013 13:59:56 +0000</pubDate>
      <guid>https://ykyi.net/?p=925/</guid>
      <description>&lt;p&gt;我的debian一般把LC_ALL设成en_US.UTF-8。这次dpkg-reconfigure locales时没有选美国英语，而是用了香港英语。于是就出错了。&lt;/p&gt;
&lt;p&gt;解决方法的关键在于  /etc/environment 文件,  dpkg-reconfigure locales 命令用来配置local，以及locale命令列出当前期待的locale，还有 local-gen 命令可以生成local.&lt;/p&gt;
&lt;p&gt;debian报得错误类似于：&lt;/p&gt;
&lt;p&gt;perl: warning: Setting locale failed.&lt;br&gt;
perl: warning: Please check that your locale settings:&lt;br&gt;
    LANGUAGE = &amp;ldquo;en_US:en&amp;rdquo;,&lt;br&gt;
    LC_ALL = (unset),&lt;br&gt;
    LANG = &amp;ldquo;en_US&amp;rdquo;&lt;br&gt;
    are supported and installed on your system.&lt;/p&gt;
&lt;p&gt;////////////&lt;/p&gt;
&lt;p&gt;另外今天还解决了编译内核后，用新内核启动时报错：&lt;/p&gt;
&lt;p&gt;kernel panic – not syncing VFS: unable to mount root fs on unknown block (0, 0)&lt;/p&gt;
&lt;p&gt;// 通常这是因为对应文件系统被编译成模块，那么就应该生成initrd加载对应的文件驱动模块。在debian下，用update-initramfs 命令生成对应的initrd. 如： update-initramfs -c -k 3.0.63&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>git的排错神器pickaxe和git blame</title>
      <link>https://ykyi.net/?p=920/</link>
      <pubDate>Tue, 29 Jan 2013 08:30:03 +0000</pubDate>
      <guid>https://ykyi.net/?p=920/</guid>
      <description>&lt;p&gt;git log -Sstring 这里的-S选项被称作pickaxe，这是一个非常好的排错工具。&lt;/p&gt;
&lt;p&gt;比如： git log -Sinclude –pretty=oneline –abbrev-commit init/version.c&lt;/p&gt;
&lt;p&gt;会把减少了，或者增加了include的commit全部找出来。&lt;/p&gt;
&lt;p&gt;要注意的是，如果有一个提交增加和减少include的次数一样，这个commit不会被列出来。&lt;/p&gt;
&lt;p&gt;/////////////&lt;/p&gt;
&lt;p&gt;另外一个排错工作是 git blame:&lt;/p&gt;
&lt;p&gt;git blame可以用来帮助查找引入bug的commit。git blame告诉你谁，什么时候，是哪个commit更改了某个文件。&lt;/p&gt;
&lt;p&gt;如: git blame -L 32, init/version.c&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用gdb和虚拟机调试内核</title>
      <link>https://ykyi.net/?p=917/</link>
      <pubDate>Mon, 28 Jan 2013 03:31:28 +0000</pubDate>
      <guid>https://ykyi.net/?p=917/</guid>
      <description>&lt;p&gt;调试内核很麻烦，即使是有了虚拟机的帮助。在这里记下一些关键的东西，以备忘 。&lt;/p&gt;
&lt;p&gt;＃  编译内核后， 用新内核启动系统失败，报错 “unable to mount fs ….” 之类.&lt;/p&gt;
&lt;p&gt;需要用 update-initramfs 生成initram。&lt;/p&gt;
&lt;p&gt;＃ 对于grub2，我增加了一个自定义的grub开机启动项用来调试内核，如下：&lt;/p&gt;
&lt;p&gt;#!/bin/sh&lt;br&gt;
exec tail -n +3 $0&lt;br&gt;
# This file provides an easy way to add custom menu entries.  Simply type the&lt;br&gt;
# menu entries you want to add after this comment.  Be careful not to change&lt;br&gt;
# the &amp;rsquo;exec tail&amp;rsquo; line above.&lt;br&gt;
echo &amp;ldquo;Add Debugging entry&amp;rdquo;&lt;br&gt;
cat &amp;laquo; EOF&lt;br&gt;
menuentry &amp;ldquo;Debian debug 3.7.4&amp;rdquo;{&lt;br&gt;
set root=(hd0,1)&lt;br&gt;
linux /boot/vmlinuz-3.7.4 root=/dev/vda1 ro quiet kgdboc=ttyS0,115200 kgdbwait&lt;br&gt;
initrd /boot/initrd.img-3.7.4&lt;br&gt;
}&lt;br&gt;
EOF&lt;/p&gt;</description>
    </item>
    <item>
      <title>Okular是linux下最好用的pdf阅读工具</title>
      <link>https://ykyi.net/?p=911/</link>
      <pubDate>Fri, 04 Jan 2013 12:55:46 +0000</pubDate>
      <guid>https://ykyi.net/?p=911/</guid>
      <description>&lt;p style=&#34;margin: 0px 0px 13px; padding: 0px; border: 0px; outline: 0px; font-size: 15px; font-family: Georgia, Times, &#39;Liberation Serif&#39;, serif; vertical-align: baseline; line-height: 22px; &#34;&gt;
  &lt;span style=&#34;font-size: 15px; &#34;&gt;我记得对于大多数Gnome桌面环境，Evince是默认的pdf阅读软件。&lt;/span&gt;&lt;span style=&#34;font-size: 15px; &#34;&gt;今天不知道怎么回事，发现evince没有了。当时我不记得evince这个名字了，就apt-cache search pdf 随便装上了xpdf-viewer。太他妈难用了啊～～就卸载了，然后google: &lt;/span&gt;&lt;span style=&#34;font-size: 15px; &#34;&gt;The Best PDF Viewer on Linux。找到了Okular，也是免费软件，装上一用。不错哈哈哈.贴一张网络上的图片：&lt;/span&gt;
&lt;/p&gt;
&lt;p style=&#34;margin: 0px 0px 13px; padding: 0px; border: 0px; outline: 0px; font-size: 15px; font-family: Georgia, Times, &#39;Liberation Serif&#39;, serif; vertical-align: baseline; line-height: 22px; &#34;&gt;
  &lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; class=&#34;alignnone&#34; height=&#34;360&#34; src=&#34;http://cache.lifehacker.com/assets/images/17/2012/01/82d614bf4c4d89c757cb0050d3255bd9.jpg&#34; width=&#34;640&#34; /&gt;
&lt;/p&gt;
&lt;p style=&#34;margin: 0px 0px 13px; padding: 0px; border: 0px; outline: 0px; font-size: 15px; font-family: Georgia, Times, &#39;Liberation Serif&#39;, serif; vertical-align: baseline; line-height: 22px; &#34;&gt;
  另外今天才知道, Adobe也有出linux下的pdf阅读软件。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>显示Gnome3任务栏</title>
      <link>https://ykyi.net/?p=896/</link>
      <pubDate>Thu, 03 Jan 2013 09:22:54 +0000</pubDate>
      <guid>https://ykyi.net/?p=896/</guid>
      <description>&lt;p&gt;Gnome3桌面较之Gnome2有了非常大的区别～&lt;/p&gt;
&lt;p&gt;第一眼看上去有惊艳的感觉～多用了一点时间，发现没有任务栏真是相当的不方便啊。我觉得最方便的还是Win7的方式。&lt;/p&gt;
&lt;p&gt;那怎么把Gnome3消失的任务栏找回来呢？通过安装一个安装包搞定。&lt;/p&gt;
&lt;p&gt;我用的是Debian 6.06 Wheazy&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;zausiu@accolade:~$ cat /etc/debian_version&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;6.0.6&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对于Debian家族的ubuntu应该也是适用的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# apt-get install tint2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;$ tint2 &amp;amp;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;于是久违的gnome任务又回来了～&lt;/p&gt;
&lt;figure style=&#34;width: 1680px&#34; class=&#34;wp-caption alignnone&#34;&gt;&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; alt=&#34;Gnome的任务栏又回来了&#34; src=&#34;http://www.micahcarrick.com/images/migrating-to-gnome-3/tint2-panel-large.png&#34; width=&#34;800&#34; height=&#34;444&#34; /&gt;&lt;figcaption class=&#34;wp-caption-text&#34;&gt;Gnome的任务栏又回来了&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>Let the Universal Access Preferences Taskbar Icon Disappear让统一访问首选项在任务栏上消失</title>
      <link>https://ykyi.net/?p=892/</link>
      <pubDate>Wed, 02 Jan 2013 05:45:27 +0000</pubDate>
      <guid>https://ykyi.net/?p=892/</guid>
      <description>&lt;p&gt;我用的是Debian Wheezy Stable系统。今天不知道怎么搞得，把任务栏上面弄出个 配置Universal Access Preferences的图标。右链点击也没有让我选择退出的选项。&lt;/p&gt;
&lt;p&gt;搜索了一下，知道用 gnome-keyboard-properties 把这个该死的图标去掉。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;alt+F2  输入 gnome-keyboard-properties&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;选中Accessibility ，取消 Accessibility features can be toggled with keyboard shortcuts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这几天调linux内核源代码，好困难好困难。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux内核Makefiles教程(二)</title>
      <link>https://ykyi.net/?p=847/</link>
      <pubDate>Sat, 07 Jul 2012 13:52:55 +0000</pubDate>
      <guid>https://ykyi.net/?p=847/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://ykyi.net/2012/07/linux%E5%86%85%E6%A0%B8makefiles%E6%95%99%E7%A8%8B%E4%B8%80/&#34;&gt;接第一篇 &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;**3.3.**&lt;strong&gt;可加载模块目标&lt;/strong&gt; &lt;strong&gt;obj-m (Loadable module goals – obj-m)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;obj-m指定将被构建为可加载内核模块的对象文件(object file)。&lt;/p&gt;
&lt;p&gt;一个模块可以从一个源文件构建或者从多个源文件构建。如果模块仅仅从一个源文件构建，kbuild makefile仅仅把对象文件加到obj-m。如下：&lt;/p&gt;
&lt;p&gt;       #drivers/isdn/i4l/Makefile&lt;/p&gt;
&lt;p&gt;        obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o&lt;/p&gt;
&lt;p&gt;_在这个例子中，__$(CONFIG_ISDN_PPP_BSDCOMP)_&lt;em&gt;被求值为__m.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If a kernel module is built from several source files, you specify that you want to build a module in the same way as above.&lt;/p&gt;
&lt;p&gt;如果一个内核模块需要从多个源文件构建，你也是按照刚才提到的那一行指定。不过，除此之外，还要额外地指定，你的内核模块需要哪些对象文件。所以还需要设置&amp;lt;模块名&amp;gt;-objs变量。如下：&lt;/p&gt;
&lt;p&gt;       #drivers/isdn/i4l/Makefile&lt;/p&gt;
&lt;p&gt;        obj-$(CONFIG_ISDN) += isdn.o&lt;/p&gt;
&lt;p&gt;        isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o&lt;/p&gt;
&lt;p&gt;在这个例子中，模块名是 isdn 。Kbuild将编译isdn-objs列出的所有对象文件，然后运行$(LD) –r把这些对象文件链接成一个文件isdn.o。&lt;/p&gt;
&lt;p&gt;Kbuild用-objs后缀或者-y后缀识别构成复合对象文件(composite objects)的对象文件。这样，Makefile就可以使用CONFIG_* 符号来确定一个对象文件是不是一个复合对象文件的一部分。如下：&lt;/p&gt;
&lt;p&gt;       #fs/ext2/Makefile&lt;/p&gt;
&lt;p&gt;        obj-$(CONFIG_EXT2_FS)        += ext2.o&lt;/p&gt;
&lt;p&gt;        ext2-y                       := balloc.o bitmap.o&lt;/p&gt;
&lt;p&gt;        ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux内核Makefiles教程(一)</title>
      <link>https://ykyi.net/?p=840/</link>
      <pubDate>Fri, 06 Jul 2012 08:17:50 +0000</pubDate>
      <guid>https://ykyi.net/?p=840/</guid>
      <description>&lt;p&gt; &lt;/p&gt;
&lt;h1 id=&#34;linux内核makefiles&#34;&gt;Linux内核Makefiles&lt;/h1&gt;
&lt;p&gt;本教程描述了了Linux内核的Makefile是如何工作的。&lt;/p&gt;
&lt;h2 id=&#34;1概述&#34;&gt;1. 概述&lt;/h2&gt;
&lt;p&gt;Linux内核的Makefile包括五个部分。&lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:203px;&#34;&gt;
      &lt;p&gt;
        Makefile
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:373px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    最上层Makefile
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:203px;&#34;&gt;
      &lt;p&gt;
        .config
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:373px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    内核配置文件。
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:203px;&#34;&gt;
      &lt;p&gt;
        arch/$(ARCH)/Makefile
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:373px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    CPU架构相关Makefile
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:203px;&#34;&gt;
      &lt;p&gt;
        scripts/Makefile.*
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:373px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    对于所有Kbuild&amp;amp;nbsp;Makefile的公共方法。.
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;width:203px;&#34;&gt;
      &lt;p&gt;
        kbuild&amp;nbsp;Makefiles
      &lt;/p&gt;
    &lt;/td&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;td style=&amp;quot;width:373px;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;
    有将近500个kbuild&amp;amp;nbsp;Makefiles。
  &amp;lt;/p&amp;gt;
&amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;最上层Makefile读取.config文件。.config文件是由内核配置过程生成的。&lt;/p&gt;
&lt;p&gt;最上级的Makefile负责生成linux的内核映象文件vmlinux和其它所有的模块。最上级Makefile递归地进入内核代码树的各级子目录分别执行子目录下的Makefile。究竟要进入哪些子目录是由内核配置阶段决定的，即配置在.cncfig文件中。最上级Makefile提定了一个路径为arch/$(ARCH)/Makefile的子目录Makefile。这个Makefile中定义了与处理器架构紧密相关的信息。&lt;/p&gt;
&lt;p&gt;每一个子目录下面都有一个kbuild Makefile，这里都定义了一些makefile命令和变量可以被更下级的Makefile继承。Kbuild Makefile使用来自.config配置的信息生成各种文件列表用来构建内建的或者模块化的目标文件。Scripts/Makefile.*包括了很多被其它Makefile使用定义和规则。&lt;/p&gt;
&lt;h2 id=&#34;2谁使用内核makefile&#34;&gt;2. 谁使用内核Makefile&lt;/h2&gt;
&lt;p&gt;内核Makefile的使用者可以大致分为四种。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;用户(Userse)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这类使用者仅仅敲入一些命令，如“make menuconfig”或者“make”。他们很少会阅读甚修改内核Makefile和源代码文件。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一般开发者（Normal Developers）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一般开发者一般编写一些设备驱动程序，文件系统，网络协议。他们需要维护他们编写的代码涉及的子系统的kbuild Makefiles。为了工作地更有效率，他们甚至还需要对整个内核的Makefile有全局的把握，包括对kbuild的公共接口的详尽了解。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;处理器架构开发者(Arch Developers)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这部分开发者关心与某个处理器架构紧密相关的代码部分，比如PC上最广泛使用的x86，以及IA64，还有ARM,Sparc,PowerPC,Alpha,s390,MIPS。Linux支持几百种处理器架构。从内核2.6.24开始，i386和x86_64合并为x86。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KBuild的开发者(KBuild Developers)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;KBuild的开发者就是维护内核构建系统的开发者，他们需要知道内核Makefile的各个方面。&lt;/p&gt;
&lt;p&gt;——&lt;/p&gt;
&lt;p&gt;本篇教程主要面向第二类开发者和第三类开发者。即一般开发者和处理器体系架构开发者。&lt;/p&gt;
&lt;h2 id=&#34;3kbuild文件&#34;&gt;3. kbuild文件&lt;/h2&gt;
&lt;p&gt;大多数内核Makefile文件是kbuild Makefile文件，它们使用不同于一般make文件的kbuild语法。下面会介绍kbuild makefile的语法。Kbuild文件一般被命名为Mafile，但是也可以使用Kbuild名字。如果已经存在一个Makefile文件了，那么就只好用Kbuild名字了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>三分钟Qt Quick入门</title>
      <link>https://ykyi.net/?p=833/</link>
      <pubDate>Tue, 03 Jul 2012 07:32:35 +0000</pubDate>
      <guid>https://ykyi.net/?p=833/</guid>
      <description>&lt;p&gt;Qt Quick是一种设计用户界面的新方法。&lt;/p&gt;
&lt;p&gt;在介绍Qt Quick之前，让我们先看一下现念的用户界面UI是什么样的。在桌面操作系统下，标准的按钮，文本框，窗体仍然能满足要求。但是这些千篇一律的灰色单调的控件渐渐让用户感到厌倦了。用户们更想看到平滑观感的，光泽的，动态的的用户界面。Qt Quick就是为了实现这些的目标。&lt;/p&gt;
&lt;p&gt;Qt Quick包括两个部分。第一部分是QtDeclarative模块。这个模块负责把Qt Quick集成到Qt应用程序中。第二部分是一种界面描述语言：QML。使用QtDeclarative使得开发者能够在C++和QML之间共享数据对象，也可以把C++类插入到QML之中，等等。QML是个全新的语言，专门为设计用户界面设计，在其它的开发中也有用武之地。&lt;/p&gt;
&lt;p&gt;迫不及待了吧。让我们看一个简单的例子：&lt;/p&gt;
&lt;p&gt;import Qt 4.6&lt;/p&gt;
&lt;p&gt;Rectangle {&lt;br&gt;
width: 200&lt;br&gt;
height: 200&lt;/p&gt;
&lt;p&gt;Text {&lt;br&gt;
text: &amp;ldquo;hello! ykyi.net&amp;rdquo;&lt;br&gt;
font.pointSize: 10&lt;br&gt;
font.bold: true&lt;/p&gt;
&lt;p&gt;anchors.centerIn: parent&lt;br&gt;
}&lt;br&gt;
}&lt;/p&gt;
&lt;p&gt;读完这断代码，再尝试在Qt Creator中运行它。不用我多费口舌，你就恍然大悟了。每一个以大写字母开头的单词定义了一个新的对象。最外面的矩形则是主窗体，可以给它设置属性。比如anchors属性把Text限定在窗体的中央。这样，即使窗体放大了，文本仍然显示在窗体正中央。&lt;/p&gt;
&lt;p&gt;前文，我有说过平滑观感的，光泽的，动态的的用户界面。那么Qt Quick怎么做到呢？简单！看看下面的代码，编辑Text的属性，设置rotation:NumberAnimation。不可思议的事情就发生了！&lt;/p&gt;
&lt;p&gt;rotation: NumberAnimation {&lt;br&gt;
to: 360;&lt;br&gt;
duration: 1500;&lt;br&gt;
running: true;&lt;br&gt;
repeat: true;&lt;br&gt;
}&lt;/p&gt;
&lt;p&gt;现在，指定的文本疯狂的转动起来。我们已经看到在Qt Quick中开发有物资的界面是多么简单。我们所展示的只是Qt Quick特效的凤毛一角，最终能创造出什么样的奇幻效果只受限于你的想象力。&lt;/p&gt;
&lt;p&gt;copyright ykyi.net&lt;/p&gt;</description>
    </item>
    <item>
      <title>Barebox介绍</title>
      <link>https://ykyi.net/?p=831/</link>
      <pubDate>Mon, 02 Jul 2012 12:39:14 +0000</pubDate>
      <guid>https://ykyi.net/?p=831/</guid>
      <description>&lt;p&gt;从裸机上电开始启动计算机的过程听起来是相当复杂的。在PC的世界里，BIOS统治这个领域已经几十年了。不过，哲学上讲任何世界都是从出生，到繁荣，再后到死亡的过程。BIOS的寿命也即将迎来终结。BIOS的掘墓者即是EFI。对于MAC用户来说，EFI的使用已经有好长一段时间了。而在嵌入式Linux的世界里，u-boot则在长时间里扮演着老大哥的角色。&lt;/p&gt;
&lt;p&gt;U-boot，或者来自DENX的das U-boot提供了非常丰富的功能。如：网络，脚本，支持FLASH(这里的flash是存储方面的flash，而不是adobe的那个flash)。一般的嵌入式系统工程序师需要的工具，都提供好了。&lt;/p&gt;
&lt;p&gt;还是那句话，对于万事万物，都是生生死死的过程啊。u-boot的功能越来越强大。催生了新的事物的诞生。它的名字就是：Barebox。&lt;/p&gt;
&lt;p&gt;Barebox最开始被称之为：u-boot-v2，它是一个像u-boot一样野心勃勃的bootloader。不过Barebox更有Linux的味道一些。它的发展抛弃了u-boot而越来越像Linux。它有文件系统，有基本的shell，甚至还有与Linux近似的驱动模块。&lt;/p&gt;
&lt;p&gt;Barebox的另一个创新即是，bootloader可以被构建成一个用户空间的应用程序。这样的好处是显而易近的，你可以更方便的开方和调试Barebox。&lt;/p&gt;
&lt;p&gt;说了这么多，看看Barebox是个什么样子呢？&lt;/p&gt;
&lt;p&gt;uboot:/&lt;/p&gt;
&lt;p&gt;uboot:/ ls&lt;br&gt;
. .. dev env&lt;br&gt;
 &lt;/p&gt;
&lt;p&gt;和Linux一样，dev目录夹下面放了系统的设备文件。比如，mem设备文件描述了计算机的内存。&lt;/p&gt;
&lt;p&gt;再回到u-boot，它有一个特殊的命令：md。md命令可以查看内存的内容。对于Barebox，提供了同样的工具。不过这个工具是以一种POSIX的方式实现的：打开/dev/mem设备，lseek移动文件指针，read读出文件内容。这样的实现方式不仅仅提升了代码结构，它还使得md命令可以不需修改就应用到其它设备上，比如flash存诸器。&lt;/p&gt;
&lt;p&gt;如果你想测试一下Barebox到底如何。你可以有两种方法。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一：你可以下载Barebox的沙盒功能即把它构建成一个Linux的用户空间的应用。来自Barebox官方的解释是：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sandbox:&lt;br&gt;
If you develop features for Barebox, you can use the &amp;lsquo;sandbox&amp;rsquo; target which compiles Barebox as a POSIX application in the Linux userspace: it can be started like a normal command and even has network access (tun/tap). Files from the local filesytem can be used to simulate devices.   如果你要为Barebox开发功能，你可以使用&amp;rsquo;沙盒&amp;rsquo;。这种方式把Barebox构建成一个Linux的用户空间程序。它像一般的命令一样，而且还有网络功能。来自文件系统的文件可以被用来模拟设备。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第二：不说你也知道，把Barebox安装到真真正正的硬件上吧！对于我，我就尝试过在PC机的一块旧式的主板上安装Barebox。 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后，Barebox的官方网站是： &lt;a href=&#34;http://barebox.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;a href=&#34;http://barebox.org/&#34;&gt;http://barebox.org/&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux如何设置IPv6地址</title>
      <link>https://ykyi.net/?p=824/</link>
      <pubDate>Sun, 01 Jul 2012 08:46:32 +0000</pubDate>
      <guid>https://ykyi.net/?p=824/</guid>
      <description>&lt;p&gt;IPv6最终全面取待IPv6是不可逆的潮流。本文则讲一下在Linux下如何配置IPv6地址。当然本文假设你使用静态IP（不必是公共IPv6地址或公共IPv4地址，可以是私有IPv4地址）。本文不适用使用DHCP获取地址的情况。&lt;/p&gt;
&lt;p&gt;首先，你要确保你使用的Linux的内核已经支持IPv6。当前比较新的Linux都已经内建IPv6了。&lt;/p&gt;
&lt;p&gt;用root用户登录，运行：&lt;/p&gt;
&lt;p&gt;# lsmod | grep ipv6&lt;/p&gt;
&lt;p&gt;看看系统有没有已经加载了IPv6模块。如果没有，尝试用以下命令加载： &lt;/p&gt;
&lt;p&gt;# /sbin/modprobe ipv6&lt;/p&gt;
&lt;p&gt;第二，你需要有你的静态IP地址。&lt;/p&gt;
&lt;p&gt;**IPv4地址如何转成IPv6地址呢？**如果你的IP是一个IPv4地址，那么可以换算得到IPv6的地址形式。比较简单的作法可以去到 &lt;a href=&#34;http://grox.net/utils/ipv6.php&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;a href=&#34;http://grox.net/utils/ipv6.php&#34;&gt;http://grox.net/utils/ipv6.php&lt;/a&gt;&lt;/a&gt;。在左边的下拉列表中选择: IPv4 to 6to4 Address，在右边的编辑框中填上你的IPv4地址。点击: Calculate 则得到了你的IPv4地址的IPv6转化格式。&lt;/p&gt;
&lt;h2 id=&#34;配置ipv6地址&#34;&gt;配置IPv6地址&lt;/h2&gt;
&lt;p&gt;一般的Linux发行版用 /etc/network/interfaces 文件配置网卡。如果没有这个文件，那么请注意 /etc/network 目录下其它文件或者目录。&lt;/p&gt;
&lt;p&gt;假如要配置的Linux的静态IPv4地址是 192.168.1.10，这个IPv4地址转换成对应的IPv6地址则是 2002:c0a8:10a:: 。再提醒一下，上文提到过如何把IPv4地址转成IPv6地址。&lt;/p&gt;
&lt;p&gt;网关的IPv4地址是 192.168.1.1，这个IPv4地址转成对应的IPv6的地址是:2002:c0a8:0101:: 。&lt;/p&gt;
&lt;p&gt;那么 /etc/network/interfaces 文件应该配置成如下：&lt;/p&gt;
&lt;p&gt;#IPV6 static configuration(我是注释)&lt;br&gt;
iface eth0 inet6 static&lt;br&gt;
pre-up modprobe ipv6&lt;br&gt;
address 2002:c0a8:10a::&lt;br&gt;
netmask 64&lt;br&gt;
gateway 2002:c0a8:0101::&lt;/p&gt;
&lt;p&gt;注意 &amp;ldquo;pre-up&amp;rdquo; 命令。这一行保证系统在启动的时候加载支持ipv6的模块。&lt;br&gt;
最后重新启发动网络，如下：&lt;/p&gt;
&lt;p&gt;# /etc/init.d/networking restart&lt;/p&gt;
&lt;p&gt;你现在可以使用你的IPv6地址了。&lt;/p&gt;
&lt;h2 id=&#34;测试ipv6地址&#34;&gt;测试IPv6地址：&lt;/h2&gt;
&lt;p&gt;检测路由：&lt;/p&gt;
&lt;p&gt;# ip -6 route show&lt;/p&gt;
&lt;p&gt;如果IPv6工作正常的话，应该会有如下的提示。&lt;/p&gt;
&lt;p&gt;2002:c0a8:0100/64 dev eth0 proto kernel scope link src 2002:c0a8:10a&lt;/p&gt;</description>
    </item>
    <item>
      <title>X86平台的中断和异常</title>
      <link>https://ykyi.net/?p=821/</link>
      <pubDate>Sat, 30 Jun 2012 04:42:06 +0000</pubDate>
      <guid>https://ykyi.net/?p=821/</guid>
      <description>&lt;p&gt;英特尔的官方文档如下定义x86平台下的中断和异常：&lt;/p&gt;
&lt;h2 id=&#34;中断&#34;&gt;中断：&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;可屏弊中断(Maskable Interrupts)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;            所有由I/O设备发出的IRQ(Interupt Requests)都是可屏弊中断。可屏弊中断可以有两个状态：屏弊和未屏弊。屏弊状态的中断会被中断控制硬件忽略。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不可屏弊中断(Nonmaskable Interrupts)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;           只有一些关键的事件（如硬件失败）会发出不可屏弊中断。不可屏弊中断总是可以被CPU识别到。&lt;/p&gt;
&lt;h2 id=&#34;heading&#34;&gt; &lt;/h2&gt;
&lt;h2 id=&#34;异常&#34;&gt;异常：&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;处理器可侦测异常(Processor-detected Exceptions)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;           CPU执行指令时侦测到不正常的状态(anomalous condition)时产生这个异常。这种异常又根据存在内核栈上的EIP寄存器的值被划分为三组。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;错误(Faults)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;           发生错误时，一般情况下可以被纠正。纠正以后，程序继续运行，不会损失连续性。保存下的EIP寄存器的值就是产生这个错误的指令，当异常处理句柄（exception handler）结束后，程序从这条指令继续运行。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;陷入(Traps)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;          当被中止的指令无需重新执行时就产生陷入，这点与错误(Faults)不同。陷入主要被用来实现调试器。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;中止(Aborts)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;           严重出错。控制硬件出现故障，此时不可能把造成异常的指令精确地址存入EIP寄存器。Aborts被用来报告严重的出错，比如硬件出错或者无效的，不一致的系统表结构。由控制硬件单元发出的中断信号被用来把控制权转交给中止异常句柄(Abort Exception Handler)。句柄通常只有强制结束造成Abort的程序。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可编程异常(Programmed Exceptions)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;          这是由程序员发出的。程序员可以用int 或者int 3指令发出可编程异常。Into(检查溢出)bound(检查数组越界)指令也可以用来发出可编程异常。可编程异常常常被称之为软中断(software interrupts)。这种异常通常用来实现系统调用，还被用来在调试器中报告事件。(into和bound指令在IA64体系中已经被废弃了，见另一篇博文：&lt;a href=&#34;http://ykyi.net/2012/06/c%E8%AF%AD%E8%A8%80%E5%92%8C%E5%AE%83%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;C语言和它的安全性&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;copyright ykyi.net&lt;/p&gt;</description>
    </item>
    <item>
      <title>It’s a mistake to include Xen in a Linux distro</title>
      <link>https://ykyi.net/?p=788/</link>
      <pubDate>Fri, 22 Jun 2012 13:21:30 +0000</pubDate>
      <guid>https://ykyi.net/?p=788/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-size:16px;&#34;&gt;&lt;span style=&#34;font-family: &#39;lucida sans unicode&#39;, &#39;lucida grande&#39;, sans-serif; &#34;&gt;As the title show, it&amp;rsquo;s a mistake to include Xen in a linux distro. Why?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: &#39;lucida sans unicode&#39;, &#39;lucida grande&#39;, sans-serif; font-size: 16px; &#34;&gt;Somebody would argue that Xen is a very useful technology. Xen does the virtualization work very well and many projects are using Xen which prove Xen is so great.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:16px;&#34;&gt;&lt;span style=&#34;font-family: &#39;lucida sans unicode&#39;, &#39;lucida grande&#39;, sans-serif; &#34;&gt;I&amp;rsquo;m not mean Xen is not good. However, just because Xen is a hypervisor that is based on another microkernel that is not Linux kernel itself. Linux distros that ship Xen today actually are running an entirely different Operating System kernel that most users even don&amp;rsquo;t notice that. Xen should be a separate, purpose-built kernel, so it should never be a part of the Linux kernel. Isn&amp;rsquo;t it strange that you think you are running a linux OS, but this &amp;rsquo;linux&amp;rsquo; has a kernel that is not linux, which is another kernel. You take away the Linux kernel, how could you say the OS is Linux.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>traceroute failed.Specify protocal traceroute used manually to fix it.</title>
      <link>https://ykyi.net/?p=751/</link>
      <pubDate>Wed, 20 Jun 2012 14:37:16 +0000</pubDate>
      <guid>https://ykyi.net/?p=751/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-family:lucida sans unicode,lucida grande,sans-serif;&#34;&gt;&lt;span style=&#34;font-size: 16px; &#34;&gt;Today, I ran the traceroute program on a machine running FreeBSD. It failed once and again.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family:lucida sans unicode,lucida grande,sans-serif;&#34;&gt;&lt;span style=&#34;font-size: 16px; &#34;&gt;Traceroute complained:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family:lucida sans unicode,lucida grande,sans-serif;&#34;&gt;&lt;span style=&#34;font-size: 16px; &#34;&gt;&lt;span style=&#34;color: rgb(51, 51, 51); line-height: 19px; text-align: left; &#34;&gt;traceroute: sendto: Permission denied.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&#34;text-align: left;&#34;&gt;
  &lt;span style=&#34;font-family:lucida sans unicode,lucida grande,sans-serif;&#34;&gt;&lt;span style=&#34;font-size: 16px; &#34;&gt;&lt;font color=&#34;#333333&#34;&gt;&lt;span style=&#34;line-height: 19px; &#34;&gt;So I tried to ping. Ping failed, too. I then checked out the configuration of the firewall, which actually denied the pass through of ICMP packet. So I set it to allow ICMP pacakges to pass through the firewall. Ping worked as I expected. But traceroute still failed.&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>如何正确地提交内核补丁包</title>
      <link>https://ykyi.net/?p=716/</link>
      <pubDate>Wed, 20 Jun 2012 11:39:56 +0000</pubDate>
      <guid>https://ykyi.net/?p=716/</guid>
      <description>&lt;p&gt;原文：&lt;a href=&#34;https://lwn.net/Articles/500443/&#34;&gt;https://lwn.net/Articles/500443/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;翻译：&lt;a href=&#34;http://ykyi.net&#34;&gt;ykyi.net &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; &#34;&gt;Greg Kroah-Hartman(又Greg KH)在执行一个了不起的作务：减少内核开发者，尤其是维护者的暴躁情绪。他在日本横滨举行的全球Linux大会上的讲演呼吁公众理解内核维护者的工作，内核贡献者的什么样的行为会导致内核维护者变得暴戾。但是，如果内核贡献者们能够遵守一些约束，他代表他自己做了许多承诺。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; &#34;&gt;
  Greg&amp;nbsp;Kroah&amp;nbsp;Hartman把Linux内核称之为&#34;有史以来最宏大的软件开发项目&#34;，而且它的开发速度也是&amp;ldquo;亘古未有&amp;rdquo;。从3.0到3.4，有373个公司的2833位开发者参于了Linux内核的开发。这一年，(2011年的5月到，2012年的5月)，Linux内核在每个小时会有5.79处变动。而且这个开发速度仍然要加速，如果你看看3.4的开发过程，每小时共有7.21处变动。这里所说的变动仅仅指能够被合并到主干的补丁包，而那些被拒绝的补丁包没有被统计进来。
&lt;/p&gt;
&lt;p style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; &#34;&gt;
  补丁包修改了哪些文件，内核开发者就把补丁包发给负责这些文件的维护者。所以的内核维护者，现在大概有700人。他们把改变应用到130个子系统的维护者那里。再从子系统的维护者到Linus的Linux内核代码分支。最后并必Linux内核的主干。如果提交的补丁包一路通过的话。
&lt;/p&gt;
&lt;p style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; &#34;&gt;
  因此，来看看为什么一些补丁包不会被接受呢？Greg&amp;nbsp;Kroah&amp;nbsp;Hartman以刚过去的两个星期收到的补丁包为例，这两个星期刚好处于3.5版本的Merge Window时间。Merge Window是一个他确不应该接收到许多补丁包的时间段。他应该在Merge Window开始前收到所以有可能会在Merge Window其间被发往Linux Torvalds的补丁包。不过，他说他在这两个星期的时间里收到487个补丁包。其中的大多数都有很多问题，有些补丁包来自那些本应该对内核有更好理解的内核开发者们。
&lt;/p&gt;
&lt;h4 style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; &#34;&gt;
  坏的补丁包
&lt;/h4&gt;
&lt;p style=&#34;color: rgb(0, 0, 0); font-family: &#39;Times New Roman&#39;; font-size: medium; &#34;&gt;
  Greg KH举例说明了一些他收到的坏的补丁包。其中一个补丁包被命名为：patch 48/48(一个有48个补丁集的最后一个)，但是其它的47个都没有。他还收到一堆补丁但没有写清楚先后顺序。如此，他要么猜测一个顺序，这毫无疑问会失败。另一个替代方案就是安全不管这个补丁了。另外还收到过有10个补丁的补丁集，但是2号补丁确丢失了。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux内核维护者的职责</title>
      <link>https://ykyi.net/?p=710/</link>
      <pubDate>Wed, 20 Jun 2012 08:48:58 +0000</pubDate>
      <guid>https://ykyi.net/?p=710/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;&lt;span style=&#34;font-family: &#39;comic sans ms&#39;, cursive; &#34;&gt;原文: &lt;/span&gt;&lt;/span&gt;&lt;a href=&#34;http://www.linuxfoundation.org/news-media/blogs/browse/2012/06/role-linux-kernel-maintainer&#34;&gt;http://www.linuxfoundation.org/news-media/blogs/browse/2012/06/role-linux-kernel-maintainer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;翻译: &lt;a href=&#34;http://ykyi.net&#34;&gt;ykyi.net&lt;/a&gt;&lt;/p&gt;
&lt;p style=&#34;margin: 1em 0px; font-size: 1.08em; line-height: 1.53em; color: rgb(77, 77, 77); font-family: Tahoma, Verdana, Arial, Helvetica, &#39;Bitstream Vera Sans&#39;, sans-serif; &#34;&gt;
  &lt;span style=&#34;font-size:14px;&#34;&gt;&lt;span style=&#34;font-family: &#39;comic sans ms&#39;, cursive; &#34;&gt;&lt;span style=&#34;line-height: 1.53em; &#34;&gt;几个星期前在日本举行的Linux大会(LinuxCon)上，我做了一个演讲，&lt;/span&gt;&lt;span style=&#34;line-height: 1.53em; &#34;&gt;题目是&#34;Linux内核维护者，他们在做什么，如何能够帮到他们&#34;。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style=&#34;margin: 1em 0px; font-size: 1.08em; line-height: 1.53em; color: rgb(77, 77, 77); font-family: Tahoma, Verdana, Arial, Helvetica, &#39;Bitstream Vera Sans&#39;, sans-serif; &#34;&gt;
  &lt;span style=&#34;font-size:14px;&#34;&gt;&lt;span style=&#34;font-family: &#39;comic sans ms&#39;, cursive; &#34;&gt;&lt;span style=&#34;line-height: 1.53em; &#34;&gt;这个演讲的视频可以通过这个&lt;/span&gt;&lt;a href=&#34;http://video.linux.com/videos/linux-kernel-maintainers-what-they-do-and-how-you-can-help-them&#34; style=&#34;font-size: 1.08em; line-height: 1.53em; color: rgb(51, 102, 153); &#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;链接&lt;/a&gt;&lt;span style=&#34;line-height: 1.53em; &#34;&gt;看到。如果你想要幻灯片，和我的讲演稿，可以在&lt;/span&gt;&lt;a href=&#34;https://github.com/gregkh/presentation-linux-maintainer&#34; style=&#34;font-size: 1.08em; line-height: 1.53em; color: rgb(51, 102, 153); &#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这个地址&lt;/a&gt;&lt;span style=&#34;line-height: 1.53em; &#34;&gt;获得。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用Cscope阅读大型工程Linux内核的源代码教程</title>
      <link>https://ykyi.net/?p=586/</link>
      <pubDate>Tue, 12 Jun 2012 11:45:14 +0000</pubDate>
      <guid>https://ykyi.net/?p=586/</guid>
      <description>&lt;p&gt;Cscope是一个非常有用的工具，可以用来方便地阅读很大型工程的源代码。较之使用传统的Unix工具grep，使用Cscope可以省下你一大笔时间，大大提高阅读代码的效率。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;通过本教程，我会教给你如何使用Cscope阅读Linux内核的源代码。毫无疑问，你可以举一反三，用同样的方法阅读其它的大型工程的源代码，不仅仅是C语言写的工程，也可以是Java或者C++或者C#开发的工程。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;STEP 1 获得源代码：&lt;/p&gt;
&lt;p&gt;去到Linux内核的网站http://www.kernel.org下载随便一个版本的Linux内核源代码压缩包。然后解压缩，把源代码释放到某个目录。本文假设你把源代码释放到 /home/code/linux-2.6.26。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;STEP 2 选择一个目录存放Cscope所需要的数据库文件。&lt;/p&gt;
&lt;p&gt;本文假设选择用/home/cscope目录存放cscope的数据库文件和其它一些相关文件。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;STEP 3 生成文件 cscope.files&lt;/p&gt;
&lt;p&gt;在最简单的情况下，工程目录下的所有源代码都是我要关心的，于是可以跳过下面所述，简单地在工程的根目录下运行&amp;rsquo;cscope -R&amp;rsquo;命令，这样Cscope就会在工程目录下所有源代码中处理相关工作。&lt;/p&gt;
&lt;p&gt;但是你关心的代码并必工程目录下所有的代码，你还需要排除很多目录下的大量代码该如何做呢？在这种情况下，你需要生成一个文件cscope.files，这个文件包含 了所有cscope将要扫描的文件的文件名，每个名字占一行。最好使用绝对路径，这样你就可以在其它目录下，而不是现在创建cscope.files文件的目录下使用这个刚创建的数据库。下面的代码将完成这个任务（假设我要所有的java文件）：&lt;/p&gt;
&lt;p&gt;$ cd /   &lt;/p&gt;
&lt;p&gt;$ find /my/project/dir -name &amp;ldquo;*.java&amp;rdquo; &amp;gt; /my/cscope/dir/cscope.files&lt;/p&gt;
&lt;p&gt;对于Linux内核来讲，情况还要稍微复杂一点。因为我们还要排除好些文件夹，这些文件夹有存放文档的文件夹，存放脚本的文件夹，与处理器架构相关的汇编代码的目录夹，与处理器架构相关的C代码除了x86（大多数人已经仅仅对x86感兴趣），另外还会排除所有的驱动文件目录夹，因为驱动占了内核很大一部分，但驱动代码通常不是我们要关心的。如果不排除这些目录的话，cscope当然也能工作，但是却给我们增加了麻烦，因为大大增加了重复的定义出现的概率。下面看我怎么做：&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;    $ LNX=/home/linux-2.6.26&lt;/p&gt;
&lt;p&gt;    $ cd /    &lt;/p&gt;
&lt;p&gt;    $ find  $LNX                                                                \&lt;/p&gt;
&lt;p&gt;    -path &amp;quot;$LNX/arch/*&amp;quot; ! -path &amp;quot;$LNX/arch/i386*&amp;quot; -prune -o               \&lt;/p&gt;
&lt;p&gt;    -path &amp;quot;$LNX/include/asm-*&amp;quot; ! -path &amp;quot;$LNX/include/asm-i386*&amp;quot; -prune -o \&lt;/p&gt;
&lt;p&gt;    -path &amp;quot;$LNX/tmp*&amp;quot; -prune -o                                           \&lt;/p&gt;
&lt;p&gt;    -path &amp;quot;$LNX/Documentation*&amp;quot; -prune -o                                 \&lt;/p&gt;
&lt;p&gt;    -path &amp;quot;$LNX/scripts*&amp;quot; -prune -o                                       \&lt;/p&gt;
&lt;p&gt;    -path &amp;quot;$LNX/drivers*&amp;quot; -prune -o                                       \&lt;/p&gt;
&lt;p&gt;    -name &amp;quot;*.[chxsS]&amp;quot; -print &amp;gt;/home/jru/cscope/cscope.files&lt;/p&gt;</description>
    </item>
    <item>
      <title>KVM你问我答 FAQ (四)</title>
      <link>https://ykyi.net/?p=579/</link>
      <pubDate>Mon, 11 Jun 2012 15:19:17 +0000</pubDate>
      <guid>https://ykyi.net/?p=579/</guid>
      <description>&lt;p&gt;&lt;strong&gt;KVM&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Xen&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;有什么区别？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Xen&lt;span style=&#34;font-family: 宋体;&#34;&gt;是一个外部虚拟机管理程序&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;(External hypervisor)&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，它承担了管理物理机器的任务并把物理机器的各种资源分配给客户机。与&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Xen&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;不同，&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;本身是&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Linux&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;内核的一部分，它使用&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Linux&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;自己的进程调度和内存管理。这就天然决定了&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;易于使用并于体积会很小。仅管体积小，但&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的功能确不少。比如，&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;可以把客户机从内存中兑换到物理磁盘上，如同&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;swap&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;普通进程一样释放&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;RAM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;目前只在提供支持硬件虚拟化的&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;x86&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;机器上运行（如&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;vt/svm&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;指令集）。从这这方面讲，&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Xen&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;通过修改客户机操作系统，充许虚拟机运行在没有硬件虚拟化技术的&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;x86&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;平台上运行。这种虚拟化技术称之为准虚拟化&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;paravirtualization&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，参见另一贴：&lt;/span&gt;&lt;a href=&#34;http://ykyi.net/2012/06/linux%E7%9A%84%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF-kvm-%E5%92%8C-qemu/&#34;&gt;Linux&lt;span style=&#34;font-family: 宋体;&#34;&gt;的虚拟化技术&lt;/span&gt;&lt;/a&gt;。&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;在&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;CPU&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;级别不支持&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;paravirtualization&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，但为了指高&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;I/O&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;性能，会对设备驱动程序支持准虚拟化。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KVM&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Vmware&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;有什么区别呢？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VMware&lt;span style=&#34;font-family: 宋体;&#34;&gt;是一个商用专用虚拟化产品，&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;是在&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;GPL&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;许可证下发布的自由软件。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KVM&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;QEMU&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;有什么区别？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;QEMU&lt;span style=&#34;font-family: 宋体;&#34;&gt;是模拟器。参见&lt;/span&gt;&lt;a href=&#34;http://ykyi.net/2012/06/linux%E7%9A%84%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF-kvm-%E5%92%8C-qemu/&#34;&gt;Linux&lt;span style=&#34;font-family: 宋体;&#34;&gt;的虚拟化技术 &lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;KVM &amp;amp; QEMU&lt;/span&gt;&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KVM&lt;span style=&#34;font-family: 宋体;&#34;&gt;有&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;windows&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;下的移移植版本吗？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>KVM你问我答 FAQ (三)</title>
      <link>https://ykyi.net/?p=574/</link>
      <pubDate>Sun, 10 Jun 2012 13:12:57 +0000</pubDate>
      <guid>https://ykyi.net/?p=574/</guid>
      <description>&lt;h3 dir=&#34;ltr&#34;&gt;
  我在使用QEMU，如何知道我有没有启用KVM的硬件加速功能?
&lt;/h3&gt;
&lt;p&gt;如果你怀疑你没有启用KVM提供的硬件加速功能。你可以按照下面的步骤做检查。首先，看看你有没有得到下面的提示信息：&lt;/p&gt;
&lt;p&gt;qemu-system-x86_64 -hda myvm.qcow2&lt;br&gt;
open /dev/kvm: No such file or directory&lt;br&gt;
Could not initialize KVM, will disable KVM support&lt;/p&gt;
&lt;p&gt;如果是这种情况，请再检查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;kvm模块被正确载入了吗？ lsmod | grep kvm.&lt;/li&gt;
&lt;li&gt;查看 dmesg 的输出，保证没有这个提示信息： “KVM, disabled by BIOS”.&lt;/li&gt;
&lt;li&gt;请确保/dev/kvm 确实存在，而且你有权限使用它。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;其它诊断方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果你能使用 QEMU monitor ( ctrl-alt-2, 再 ctrl-alt-1 回到 VM 的显示屏 )，敲入 info kvm 命令。如果正常的话，应该有“KVM support: enabled”这条信息输出。&lt;/li&gt;
&lt;li&gt;在host机上敲 lsmod | grep kvm 命令，看看输出的最右栏。如果kvm在正常运行的话，这个数字不能是0。这行的数字与架构相关的模块(一般指的是kvm_intel,或kvm_amd)有联系，它显示了有多少个VM正在使用这个模块。举例说明，如果你有两个虚拟机正在使用KVM模块，host机的CPU使用的是vt技术，那么就会得到：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;# lsmod | grep kvm&lt;br&gt;
kvm_intel              44896  2&lt;br&gt;
kvm                   159656  1 kvm_intel&lt;/p&gt;</description>
    </item>
    <item>
      <title>KVM你问我答 FAQ (二)</title>
      <link>https://ykyi.net/?p=505/</link>
      <pubDate>Sat, 09 Jun 2012 08:26:26 +0000</pubDate>
      <guid>https://ykyi.net/?p=505/</guid>
      <description>&lt;h2 dir=&#34;ltr&#34;&gt;
  如果我的没有root权限，怎么使用KVM呢？
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;最简洁的做法就是创建一个组，比如kvm组，然后把将要使用kvm的用户添加到组里面。然后用chown命令把/dev/kvm的所有组改成kvm。如果你的系统里安装了udev，你还可以通过配置udev的方式使得linux自动把新创建的设备设成正确的组。比如在ubuntu的/etc/udev/rules.d/40-permissions.rules文件中增加一行：&lt;br&gt;
KERNEL==”kvm”, GROUP=”kvm”&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  怎么做才能得到kvm的最佳性能呢？
&lt;/h3&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  See the &lt;a href=&#34;http://www.linux-kvm.org/page/Tuning_KVM&#34;&gt;Tuning KVM&lt;/a&gt; page.
&lt;/h3&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  KVM稳定吗？
&lt;/h3&gt;
&lt;p&gt;****KVM非常稳定而且已经用于工作生产环境之中。对于所有的开始工程，开发版的稳定性总是逊于稳定发行版。建议使用稳定发行版。KVM已经被使用比较长一段时间，模拟常用的操作系统和配置。一但有问题出现，开发者会在第一时间修复。参看&lt;a href=&#34;http://www.linux-kvm.org/page/Guest_Support_Status&#34;&gt;Guest Support Status&lt;/a&gt;，列举了目前运行良好的操作系统。****zausiu’s blog &lt;a href=&#34;http://ykyi.net&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  KVM真的可以用于生产环境吗？
&lt;/h3&gt;
&lt;p&gt;****为了稳定性，强列建议你使用你使用的发行版提供的KVM模块。如前面所述，及早使用新特性总是令人开心的事情。但是，你常常要要承担一定的风险，一些未知的问题可能在使用时暴露出来。在生产环境中，最好使用你使用的发行版提供的稳定版，而开发版本，如果你愿意，可以使用在不是那么重要的环境下。&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  如果我用kill -9杀掉VM进程会发生什么事呢？
&lt;/h3&gt;
&lt;p&gt;****From the guest’s perspective, it is as if you yanked the power cord out. From the host’s perspective, the process is killed and all resources it uses are reclaimed.&lt;br&gt;
从客户虚拟机的立场来看，这就如同被拨掉了电源。从Host机的立场看，仅仅是VM进程被杀死了，这个VM进程所申请的所有系统资源被回收给操作系统。如前文所说，对于linux内核，VM进程就是一个普通的进程。&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  请帮助我设置客户机的网络。
&lt;/h3&gt;
&lt;p&gt;****可以参考这里 &lt;a href=&#34;http://www.linux-kvm.org/page/Networking&#34;&gt;Networking&lt;/a&gt; 设置网站，也可以找找QEMU的网络设置相关文档。&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  哪里有更多KVM的文档呢？
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;绝大多数问题都在QEMU的 &lt;a href=&#34;http://www.nongnu.org/qemu/user-doc.html&#34;&gt;documentation&lt;/a&gt;中被提到了，还有部分在扩展&lt;a href=&#34;http://qemu-buch.de/cgi-bin/moin.cgi/FrequentlyAskedQuestions&#34;&gt;FAQ&lt;/a&gt; ( 已经废弃的老板 &lt;a href=&#34;http://kidsquid.com/cgi-bin/moin.cgi/FrequentlyAskedQuestions&#34;&gt;FAQ&lt;/a&gt;).&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>KVM你问我答FAQ (一)</title>
      <link>https://ykyi.net/?p=502/</link>
      <pubDate>Sat, 09 Jun 2012 05:12:04 +0000</pubDate>
      <guid>https://ykyi.net/?p=502/</guid>
      <description>&lt;h3 dir=&#34;ltr&#34;&gt;
  使用KVM需要哪些准备？
&lt;/h3&gt;
&lt;p&gt;****你需要一台运行Linux的x86的机器。它的CPU是有VT技术支持的英特尔cpu或者有SVM（又常被称为AMD-V）支持的AMD的CPU.&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  KVM支持64位的处理器吗？
&lt;/h3&gt;
&lt;p&gt;****KVM支持64位的处理器！此时，你可以运行32位或者64位的客户机。&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  What is Intel VT / AMD-V / hvm?
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;英特尔VT，是什么？AMD-V又是什么？hvm是什么？&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.intel.com/technology/itj/2006/v10i3/1-hardware/6-vt-x-vt-i-solutions.htm&#34;&gt;Intel VT&lt;/a&gt; 和&lt;a href=&#34;http://www.amd.com/us-en/Processors/ProductInformation/0,,30_118_8826_14287,00.html&#34;&gt;AMD’s AMD-V&lt;/a&gt; 都指的是指令集扩展。它们在硬件层面帮助实现虚拟机管理技术。这种技术使得在虚拟机上运行的速度接近直接在真实机器上运行的速度。HVM是硬件虚拟机的缩写(Hardware Virtual Machine )则是一个生产商中立的词汇(vendor-neutral term)，它常常用来指代x86指定集扩展。&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  从哪里得到KVM内核模块呢？
&lt;/h3&gt;
&lt;p&gt;****可以从这里获得 &lt;a href=&#34;http://www.linux-kvm.org/page/Getting_the_kvm_kernel_modules&#34;&gt;http://www.linux-kvm.org/page/Getting_the_kvm_kernel_modules&lt;/a&gt; 。&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  我如何知道我的CPU支持Intel VT技术或者AMD-V技术呢？
&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;em&gt;如果你的Linux操作系统比较新，尝试以下的指令：&lt;br&gt;
. egrep ‘^flags.&lt;/em&gt;(vmx|svm)’ /proc/cpuinfo&lt;/strong&gt;&lt;/em&gt;*&lt;/p&gt;
&lt;p&gt;如果出现一些文字，那说说你的CPU支持虚拟化。你也可以在/proc/cpuinfo文件中找到处理器模块的名字，然后到供应商的网站上查询。&lt;br&gt;
注意：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果安装了Xen hypervisor，为了防止被劫持，你在dom0和domU中都得不到这些输出。dom0和domU是Xen hypervisor的术语。如果你没有安装Xen，直接忽略。&lt;/li&gt;
&lt;li&gt;一些产商默认在BIOS定设中禁用了CPU的虚拟化支持。你需要先在BIOS中打开虚拟化支持。&lt;/li&gt;
&lt;li&gt;如果你用的是intel cpu，对于内核版本2.6.15以前的Linux，你得不到这样的输出。如果你用的是amd cpu，对于内核版 本2.6.16以前的linux，你得不到这样的输出。如果你不确定你的Linux内核版本，用#uname -r 命令查看。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h3 dir=&#34;ltr&#34;&gt;
  出现 &amp;#8220;KVM: disabled by BIOS&amp;#8221; error 错误
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;Check if there is an option to enable it in the BIOS. If not, look for a more recent BIOS on the vendor’s web site.&lt;br&gt;
在BIOS设定在找找看有没有启用cpu虚拟化的选项，如果没有，去到主板厂商的网站上面看看有没有新的BIOS发布并支持打开cpu虚拟化，那么你需要刷新BIOS.&lt;br&gt;
注意：&lt;br&gt;
1.对于部分硬件(如 HP nx 6320)，你需要先关掉主机电源，再打开主机电源才能使BIOS中启用cpu虚拟化支持生效。&lt;br&gt;
2.BIOS的部分设定有可能与启用CPU虚拟化冲突。比如在Thinkpad T500上，启用Intel AMT技术会出现冲突。这样kvm-intel在载入时会抱怨”disabled by bios”错误。&lt;br&gt;
3. 在一些Dell的硬件中，你还需要禁用”Trusted Execution”，否则不能打开VT。&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux的虚拟化技术 KVM 和 QEMU</title>
      <link>https://ykyi.net/?p=484/</link>
      <pubDate>Thu, 07 Jun 2012 17:36:55 +0000</pubDate>
      <guid>https://ykyi.net/?p=484/</guid>
      <description>&lt;p&gt;Linux 2.6.20发布以后。一个称之为KVM的非常优秀的虚拟化框架加入了linux代码主干。KVM是Kernel-based Virtual Machine的首字母简写。这篇文章将在理论层面和实践层面都会简单介绍KVM是如何工作的。&lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;简单的理论背景：&lt;br&gt;
目前有几种虚拟化的方式。&lt;br&gt;
其中一种称之为准虚拟化(para-virtulization)。使用准虚拟化的时候，为了达到虚拟化的目的，客户机系统必须被修改。修改后的客户机知道它运行在虚拟的环境中，与虚拟机管理程序(Supervisor)协同工作。这样的好处理较之全虚拟化，性能上有一定的优势。&lt;br&gt;
另一种称之为全虚拟化(full virtualization)。使用这种技术则不需要修改操作系统。但相对于准虚拟化技术，全虚拟代技术牺牲了一些性能。因为没有客户机OS的参于，是非常困难得到很高的虚拟化效率的。但自从CPU产商在硬件层面推出虚拟化支持的时候，情况就不一样了。如Intel的VT，AMD的AMD-V虚拟化技术。KVM就是利用了CPU的虚拟化支持技术实现了。并且KVM作为linux内核的一个模块加载，天然继承了linux内核的诸多优势。基于KVM的虚拟机，被当成一个标准的Linux进程被Linux内核调度。这个KVM虚拟机看到的都是虚拟的硬件。对于一个标准的Linux进程，有两种运行模式：内核态和用户态。KVM给虚拟机进程加入了第三个模式：客户模式(guest mode)。而客户模式又有它自己的内核态和用户态。&lt;/p&gt;
&lt;p&gt;KVM包括两部分组件：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一个设备驱动程序用来管理虚拟化硬件。这个驱动是一个字符驱动，用来管理虚拟化硬件(for managing the virtualization hardware)。&lt;/li&gt;
&lt;li&gt;一个用户空间运行的模拟器。通常选择QEMU稍作修改。QEMU是由一个叫Fabrice Bellard的法国黑客写的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;KVM与QEMU实战,在linux下安装windows xp：&lt;/p&gt;
&lt;p&gt;前期准备，需要安装KVM和QEMU.另外还有保证你已经编译了内核。&lt;br&gt;
真正的安装超级简单。&lt;br&gt;
第一步：# qemu-img create hda.img -f qcow 6G&lt;br&gt;
第二步: # kvm -no-acpi -m 256 -cdrom winxpsp2.iso -hda hda.img -boot d&lt;/p&gt;
&lt;p&gt;下面简单的解释下。&lt;br&gt;
第一步创建了一个虚拟磁盘（实际上就是文件系统上一个文件而已，不过话又说回来，unix的哲学就是所有的东东都是文件。）这条命令选择了QEMU的写时复制策略。这使得这个文件会按需增长。所以一开始这个文件不会太大，以后随着你的虚拟xp占用的空间增大而增大。不过这条命令把大小限制到第大6G.&lt;br&gt;
第二步：指定了win xp的镜像文件就开始安装啦！喔，这条命令使用了 -no-acpi 开关。据说acpi在QEMU中支持的不够好。不过我觉得问题应该得到解决了吧，所以也可以不用 -no-acpi。ykyi.net&lt;/p&gt;
&lt;p&gt;于是就装好啦！真的非常简单啊~~&lt;br&gt;
于是你就可以用这个虚拟的xp做一些你不愿意在真实OS上作的测试啦！或者使用只有在win下的软件。&lt;/p&gt;
&lt;p&gt;转贴请注明出处 &lt;a href=&#34;http://ykyi.net/2012/06/linux%E7%9A%84%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF-kvm-%E5%92%8C-qemu/&#34;&gt;http://ykyi.net/2012/06/linux%E7%9A%84%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF-kvm-%E5%92%8C-qemu/&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux用两种信号量 Linux has two kinds of semaphore</title>
      <link>https://ykyi.net/?p=480/</link>
      <pubDate>Tue, 05 Jun 2012 12:24:40 +0000</pubDate>
      <guid>https://ykyi.net/?p=480/</guid>
      <description>&lt;p&gt;面试中经常会考什么是信号量，对于linux,实际上有两种semaphore.&lt;/p&gt;
&lt;p&gt;第一种是指一种IPC(Inter-process communication进程通讯)的方法。这种IPC是从Unix SYstem V时代开始的，System V发布时加入了三种IPC，它们是semaphore信号量，message queues消息队列，shared memory共享内存。&lt;/p&gt;
&lt;p&gt;Linux中另一种Semaphore是内核用来同步的机制。在kernel中，semaphore通常当成一个二值信号量使用。获得信号量时有可能会睡眠，这样进程就会被调度开，放弃处理机；如果某段内核代码得到了一个信号量，这段代码还可以睡眠。这点不像spinlock，尝试得到spinlock会不停地忙等，得到spinlock后不充许睡眠。当然这个“不充许”不是语法层面的，而是应该被程序员遵守。否则整个系统的的性能就会被这代不遵守约定的代码毁掉了。&lt;/p&gt;
&lt;p&gt;copyright ykyi.net&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>内核线程是什么东东 What is Kernel threads</title>
      <link>https://ykyi.net/?p=476/</link>
      <pubDate>Tue, 05 Jun 2012 05:45:13 +0000</pubDate>
      <guid>https://ykyi.net/?p=476/</guid>
      <description>&lt;p&gt;有一些Unix内核，比如Solaris和SVR4.2/MP，被组织成一些内核线程。一个内核线程是一个执行上下文且可以被调度；这样的内核线程可能与一个用户程序相关联，也有可以只执行一些内核函数。上下文切换的时候，切换内核线程上下文的开销远比切换用户进程上下文的开销要小。因为内核线程通常共用一个地址空间。而&lt;strong&gt;Linux的内核线程&lt;/strong&gt;则有不同。Linux的内核线程仅仅周期性的执行一个内核函数。而且，Linux内核进线程并不表示一个基本的可执行上下文。 zausiu&amp;rsquo;s blog. &lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some Unix Kernels, such as Solaris and SVR4.2/MP, are organized as a set of kernel threads. A kernel thread is an execution context that can be independently scheduled; it may be aasociated with a user program, or it may run only some kernel functions. Context switches between kernel threads are usually much less expensive than context switches between ordinary processes, because the former usually operate on a common address space. Linux uses kernel threads in a very limited way to execute a few kernel functions periodically; however, they do not represent the basic execution context abstractions.&lt;/p&gt;</description>
    </item>
    <item>
      <title>十个选择Oracle Linux而不是RedHat企业版Linux的原因</title>
      <link>https://ykyi.net/?p=431/</link>
      <pubDate>Sun, 27 May 2012 06:19:36 +0000</pubDate>
      <guid>https://ykyi.net/?p=431/</guid>
      <description>&lt;p&gt;Linux&lt;span style=&#34;font-family: 宋体;&#34;&gt;在当今基于云的解决方案中被普通采用。而&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Oracle Linux&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;目前最完整的集成解决方案。它提供了高性能和高可靠性，却只是选择&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;Redhat Linux&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的花费的&lt;/span&gt;&lt;span style=&#34;font-family: Arial;&#34;&gt;1/7&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt; 译！&lt;/p&gt;
&lt;p&gt;原因一: Oracle Linux成本低：&lt;/p&gt;
&lt;p&gt;Oracle Linux可以自由下载和部署。&lt;/p&gt;
&lt;p&gt;对Oracle Linux的支持订阅(Support Subscription)非常简单且价格便宜。&lt;/p&gt;
&lt;p&gt;支持花费(Support costs)不到Redhat的七分之一。&lt;/p&gt;
&lt;p&gt;你不能够下载Redhat Ent Linux，除非你购买了Support Subscription。&lt;/p&gt;
&lt;p&gt;而Redhat Ent Linux的订阅以及插件的价格都很贵。&lt;/p&gt;
&lt;p&gt;Redhat Ent Linux的授权许可证非常的复杂。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;原因二: Oracle Linux已包含管理工具。&lt;/p&gt;
&lt;p&gt;Oracle Linux支持用户使用免费的Oracle Linux服务器的生命期管理工具，这个工具相当于Redhat的卫星服务以及相关模块。&lt;/p&gt;
&lt;p&gt;同样的Oracle企业管理者工具也能被授权管理从应用到磁盘的整个解决方案。&lt;/p&gt;
&lt;p&gt;而红帽的卫星服务器用户则需要分别为每台服务器都申请许可证。可想而知，花费要高很多。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;原因三：Oracle Linux的高有效性。&lt;/p&gt;
&lt;p&gt;Oracle Linux includes OCFS2 and Oracle Linux Basic and Premier Support subscribers have free access to Oracle Clusterware&lt;/p&gt;
&lt;p&gt;Red Hat charges separately for add-ons that include clustering software for HA&lt;/p&gt;</description>
    </item>
    <item>
      <title>怎么订阅Linux内核邮件列表</title>
      <link>https://ykyi.net/?p=425/</link>
      <pubDate>Sun, 20 May 2012 06:07:40 +0000</pubDate>
      <guid>https://ykyi.net/?p=425/</guid>
      <description>&lt;p&gt;官方页面：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://vger.kernel.org/majordomo-info.html&#34;&gt;http://vger.kernel.org/majordomo-info.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As of now, subscription support is &lt;em&gt;not&lt;/em&gt; handled at the web!&lt;/p&gt;
&lt;p&gt;从现在开始，订阅操作不在通过web方式操作啦。&lt;/p&gt;
&lt;p&gt;All VGER list control activities (joining and leaving, that is) are handled via email server at address:&lt;/p&gt;
&lt;p&gt;所以的VGER列表的操作都通过邮件的方式搞定。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;majordomo@vger.kernel.org&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All email sent to there &lt;strong&gt;must&lt;/strong&gt; be &lt;strong&gt;TEXT/PLAIN&lt;/strong&gt;, there can be no multipart messages, no VCARDs, nothing “fancy&amp;rsquo;&amp;rsquo;. In presense of such things, Majordomo will very likely do wrong thing.&lt;/p&gt;
&lt;p&gt;所以的邮件都必须以纯文本发送。不需要multipart message，不需要VCARD，不需要花哨的东东。如果你违反了，Majordomo系统就会出错。&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;color: red;&#34;&gt;When you send there email, &lt;strong&gt;do make sure&lt;/strong&gt; that all of the email headers, both visible and transport level, have &lt;strong&gt;same&lt;/strong&gt; addresses in them. People experience problems when for example “From:&amp;rsquo;&amp;rsquo;, “Sender:&amp;rsquo;&amp;rsquo; and possible “Reply-To:&amp;rsquo;&amp;rsquo; headers present different addresses. &lt;strong&gt;The most common manifestation is complete &lt;em&gt;silence&lt;/em&gt; from VGER!&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>gcc的-E选项什么意思</title>
      <link>https://ykyi.net/?p=408/</link>
      <pubDate>Wed, 22 Feb 2012 05:37:54 +0000</pubDate>
      <guid>https://ykyi.net/?p=408/</guid>
      <description>&lt;p&gt;gcc的-E选项可以为你生成预编译后的文件。预编译后的文件将把c文件中的宏以及该文件包含的所有头文件展开。这样就没有了一层一层进入嵌套包含的头文件。下面是一个使用gcc的-E选项的例子。&lt;/p&gt;
&lt;p&gt;下面是来自gcc mannual page的解释：&lt;/p&gt;
&lt;p&gt;-E Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of  preprocessed source code, which is sent to the standard output. Input files which don&amp;rsquo;t require preprocessing are ignored.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;$ gcc -E drivers/char/mydrv.c -D__KERNEL__ -Iinclude -Iinclude/asm-x86/mach-default &amp;gt; mydrv.i&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;其中的-I选项告诉编译器在哪些目录中搜索所需要的头文件。&lt;/p&gt;
&lt;p&gt;还可以用gcc的-S选项生成汇编码的文件。如：&lt;/p&gt;
&lt;p&gt;$ gcc -S drivers/char/mydrv.c -D__KERNEL__ -Iinclude -Ianother/include/path&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://ykyi.net&#34;&gt;ykyi.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>怎么为Linux源代码生成补丁</title>
      <link>https://ykyi.net/?p=402/</link>
      <pubDate>Wed, 22 Feb 2012 05:27:48 +0000</pubDate>
      <guid>https://ykyi.net/?p=402/</guid>
      <description>&lt;p&gt;怎么为Linux源代码生成补丁&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;用diff命令来为linux源代码生成补丁。如：&lt;/p&gt;
&lt;p&gt;$ diff -Nur /path/to/original/kernel /path/to/your/kernel &amp;gt; change.patch&lt;/p&gt;
&lt;p&gt;注意原始的源代码在前，更改后的源代码在后。2.6.x内核的补丁包提交约定指出你需要在每个patch后面写上这样一行：&lt;/p&gt;
&lt;p&gt;Sined-off-by: name &lt;email&gt;&lt;/p&gt;
&lt;p&gt;这样注明这个补丁包由你制作并贡献给社区。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;参看 Documentation/SubmittingPatches可以知道更多关于提交linux源代码补丁的内容 。&lt;/p&gt;
&lt;p&gt;参看 Documentation/applying-patches.txt 可以知道更多如果打补丁包。&lt;/p&gt;
&lt;p&gt;copyright ykyi.net&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unix网络编程 第13章 Daemon Processes and the inetd Superserver 笔记</title>
      <link>https://ykyi.net/?p=356/</link>
      <pubDate>Mon, 26 Dec 2011 16:59:47 +0000</pubDate>
      <guid>https://ykyi.net/?p=356/</guid>
      <description>&lt;p&gt;# The syslogd daemon runs in an infinite loop that calls select, waiting for any one of its three descriptors to be readable. it reads the log message and does what the configuration file says to do with that message. If the daemon receives the SIGHUP signal, it rereads its configuration file. So, what are the three descriptors that the select system call is waiting for ?  1. A unix domain socket is created and bound to the pathname /var/run/log (/dev/log on some systems). 2. A udp socket is created and bound to port 514(the syslog service). 3. The pathname /devklog is opened. Any error messages from within the kernel appears as input on this device. Newer implementation disable the creation of the UDP socket, unless specified by the administrator, as allowing anyone to send UDP datagrams to this port opens the system up to denial-of-service attacks, where some one could fill up the filesystem.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unix网络编程 第十二章 IPv4 and IPv6 Interoperability</title>
      <link>https://ykyi.net/?p=352/</link>
      <pubDate>Mon, 26 Dec 2011 13:28:35 +0000</pubDate>
      <guid>https://ykyi.net/?p=352/</guid>
      <description>&lt;p&gt;# Ethernet header contains a type fileld of 0x0800, which identifies the frame as an IPv4 frame.&lt;/p&gt;
&lt;p&gt;# 若支持dual-stack的server既有IPv4又有IPv6。则IP层让server透明地既可处理IPv4又可处理IPv6.该server需要绑定到wildcard且未设置IPV6_V6ONLY socket option.&lt;/p&gt;
&lt;p&gt;# UNP Page359 Figure 12.5 Summary of interoperability between IPv4 and IPv6 clients and servers.&lt;/p&gt;
&lt;p&gt;# 尽可能用IPv6,  since an IPv6 client can still communicate with IPv4 servers, and vice versa.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unix网络编程 第11章 Name and Address Conversions 笔记</title>
      <link>https://ykyi.net/?p=344/</link>
      <pubDate>Mon, 26 Dec 2011 12:48:53 +0000</pubDate>
      <guid>https://ykyi.net/?p=344/</guid>
      <description>&lt;p&gt;# gethostbyname 和 gethostbyaddr 用来在 IPv4 地址和 hostname 之间转换. getservbyport 和 getservbyname 则是与服务相关。gethostbyname出错时不设errno而是设h_errno，并有hstrerror()函数。&lt;/p&gt;
&lt;p&gt;# FQDN的全称是: Fully Qualified domain name. 技术上说必须以点号(period)终止.&lt;/p&gt;
&lt;p&gt;# AAAA 被称为 &amp;ldquo;quad A&amp;rdquo; rcord, 给出了从hostname到Ipv6地址的映射。 PTR用来把IP地址到hostname.&lt;/p&gt;
&lt;p&gt;# Entries in the DNS are known as Resource Records(RRs).&lt;/p&gt;
&lt;p&gt;# 一个点分十进制(dotted-decimal)IPv4的地址前加 0::ffff:就是 IPv6的字符串形式。&lt;/p&gt;
&lt;p&gt;# 与getpeername对应的函数不是gethostname而是getsockname.&lt;/p&gt;
&lt;p&gt;# getaddrinfo函数的host参数指定为dotted-decimal IPv4或 IPv6 hex string,会使得只有IPv4或IPv6的addrinfo返回。&lt;/p&gt;
&lt;p&gt;# 不给UDP套接字设置SO_REUSEADDR选项。We do not set the SO_REUSEADDR socket option for the UDP socket because this socket option can allow multiple sockets to bind the same UDP port on hosts that support multicasting. Since there is nothing like TCP&amp;rsquo;s TIME_WAIT state for a UDP socket, there is no need to set this socket option when the server is started.&lt;/p&gt;</description>
    </item>
    <item>
      <title>我看过的unix/linux世界的好书</title>
      <link>https://ykyi.net/?p=330/</link>
      <pubDate>Sat, 24 Dec 2011 12:36:43 +0000</pubDate>
      <guid>https://ykyi.net/?p=330/</guid>
      <description>&lt;p&gt;&amp;ldquo;Advanced Programming in the Unix Environment&amp;rdquo; Volum I 2nd Edition 大名鼎鼎的  apue 作者是享誉 unix 世界的大牛 Richard Stevens.全书分两卷。第一卷我看了两遍， 第二卷翻了翻目录，不想看。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Linux Device Drivers&amp;rdquo; 3rd Edition 简称LDD.这本书的中文版翻译的奇烂无比。果断读影印版的，要么就别看了。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Managing Projects with GNU make&amp;rdquo; 讲GNU make的书. make这个古老的build工具。怎么 说呢。至少我觉得语法设计的非常不友好。无奈的历史问题。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Version Control with Git&amp;rdquo; 讲git的书.混了个眼熟。一个人单独做小规模开发用不到那 么多特性咯。&lt;/p&gt;
&lt;p&gt;&amp;lt;Linux内核设计与实现&amp;gt; 很薄的一本讲linux kernel的书。这本书看的中文版。陈莉君翻 译的还不错。只有很少错误。&lt;/p&gt;
&lt;p&gt;&amp;lt;Unix编程艺术&amp;gt; 这本书我有中文版和英文版。先买了英文版看看不懂，于是买了中文版看 。除非你的英文水平接近有native speaker的水平并且词汇量超大，至少在一万以上吧。 否则还是看中文版吧。中文版译得很不错。英文版哥看得非常吃力。5。哥的词汇量接近一万 对自己的英文水平看技术类书还是很自信的，但是写这本书的作者是一位极具个性，极具 争议的unix hacker，行文风格尽显不羁个性。同样这本书也是争议颇多。支持的奉为圣经 ，反对的嘲笑作者见识短浅。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Advanced Bash programming Guide&amp;rdquo;  讲编写bash脚本的。看的网上的电子版。太多内容了，基本上bash的特性面面惧到。很多内容看了就忘了。&lt;/p&gt;
&lt;p&gt;&amp;lt;鸟哥的私房菜 基础篇&amp;gt;据说是中文书里算入门的好书了。网上的口啤不错。个人感觉讲的 内容非常之浅，不过确实是本入门的好书。但不觉得有收藏价值。这套书还有服务器部分，没有看过。没兴趣也不需要看. &lt;/p&gt;
&lt;p&gt;正在看 Richard Stevens 的另一本bible，“Unix network Programming” Volumn I 3 rd Edition。 看完了一半。一定要在寒假结束前看完。和apue一样，虽然最新版都是由新 的作者在原来的基础上更改的，但仍然保持了Richard Stevens的行文风格用语简练不花哨 ，详细细致易懂的风格。 明年争取啃下 &amp;ldquo;Understanding Linux Kernel&amp;rdquo;. 计划选择性看部分&amp;quot;Essential Linux Device Drivers&amp;quot;. 顺便提一下Richard Steven写的另一套久负盛名的书Tcp/ip详解，共三卷。简单的过了一下第一卷。没有认真看。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unix 网络编程 第十章 SCTP Client/Server Example</title>
      <link>https://ykyi.net/?p=313/</link>
      <pubDate>Mon, 19 Dec 2011 11:25:57 +0000</pubDate>
      <guid>https://ykyi.net/?p=313/</guid>
      <description>&lt;p&gt;这一章的内容还是满少的。也就是给出一个SCTP的简单例子。所以也没有太多需要做笔记的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;什么是 head-of-line blocking.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Head-of-line blocking occurs when a TCP segment is lost and a subsequent TCP segment arrives out of order. That subsequent segment is held until the first TCP segment is retransmitted and arrives at the receiver.&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;&lt;strong&gt;怎么更改SCTP连接的stream的数量。&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;SCTP连接的streams的数量是在association的握手之前协商好的。对于FreeBSD的KAME实现，SCTP的outbound streams默认为10。这个值可以用setsocket函数更改。与SCTP_INITMSG scoket option相关，设置struct sctp_initmsg结构体。&lt;/p&gt;
&lt;p&gt;也可以用sendmsg函数发送ancillary数据来到达同样的目标。但发送ancillary data只对one-to-many形式的sctp socket有效。&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;strong&gt;怎么结束一个SCTP连接。&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以设置sctp_sndrcvinfo结构的sinfo_flags值的MSG_EOF flag来关闭一个sctp连接gracefully. This flag forces an association to shut down after the message being sent is acknowledged.&lt;/p&gt;
&lt;p&gt;还可以给sinfo_flags设置 MSG_ABORT。这样就会立即发送一个ABORT给peer端。任何还没来得及发送出的数据会被丢弃。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unix网络编程.第九章笔记</title>
      <link>https://ykyi.net/?p=307/</link>
      <pubDate>Sat, 17 Dec 2011 08:58:14 +0000</pubDate>
      <guid>https://ykyi.net/?p=307/</guid>
      <description>&lt;p&gt;# TCP 协议在1981年标准化，而SCTP协议则是在2000年由IETF组织标准化。IETF： Internet Engineering Task Force 互联网工程任务组成立于1985年。&lt;/p&gt;
&lt;p&gt;# SCTP支持两种类型的socket. one to one(为了方便现有的tcp程序迁移到sctp) 和 one to many.&lt;/p&gt;
&lt;p&gt;# sctp的sctp_bindx可以绑定多个地址，并且可以动态增删。但动态增删不影响已经存在的associations.不过各个unix分支不一定支持这个特性。&lt;/p&gt;
&lt;p&gt;# sctp_getpaddrs和sctp_getladdrs分别是getpeername和gethostname的sctp版。They are designed with the concept of a multihoming aware transport protocol.&lt;/p&gt;
&lt;p&gt;# sctp传输的报文是有边界的。sctp在传输层支持传输超大的message.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unix网络编程.第七章笔记</title>
      <link>https://ykyi.net/?p=296/</link>
      <pubDate>Thu, 15 Dec 2011 06:33:56 +0000</pubDate>
      <guid>https://ykyi.net/?p=296/</guid>
      <description>&lt;div&gt;
  1.&amp;nbsp;有一个&amp;nbsp;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Generic&amp;nbsp;Socket&amp;nbsp;Option&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;：&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SO_BROADCAST&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;用来开启是否充许广播。&lt;/span&gt;2.&amp;nbsp;仅有&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;TCP&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;支持&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SO_DEBUG&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Kernel&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;把详细的发送包的接收包信息存在一个环路&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;buffer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;里。可以用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;trpt&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;查看它。&lt;/span&gt;3.&amp;nbsp;SO_ERROR&lt;span style=&#34;font-family: 宋体;&#34;&gt;套接字选项只能被取得，不能被设置。如果进程阻塞在&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;select&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;调用里，不论是读还是写，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;select&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;都会返回&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;conditions&amp;nbsp;set&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。如果进程使用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;signal-driven&amp;nbsp;I/O&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，则&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SIGIO&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;信号会被发到这个进程或者它所在的进程组。进程用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;getsockopt&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;得到&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;so_error&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;后，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;so_error&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就会被重置为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;0.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;如果&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;so_error&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;不为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，此时调用&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;read&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;或者&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;write&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就会立即返回&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;-1&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;errno&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;被置为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;so_error&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的值。&lt;/span&gt;&lt;/p&gt; 
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    4.&amp;nbsp;SO_KEEPALIVE&lt;span style=&#34;font-family: 宋体;&#34;&gt;在一个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;tcp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;连接没有任何收发达两个小时时会发一个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;prob&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;给对方。两个钟喔。好长的时间啊！！！&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Richard&amp;nbsp;Stevens&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;认为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SO_KEEPALIVE&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;应该改叫&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;make-dead&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。大多&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Unix&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;kernel&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;把这个两小时时长存为一个系统级的变量。这意味着如果你用某种方法改变了这个时长，会影响这个操作系统的所有&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;socket.Richard&amp;nbsp;Stevens&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;认为想把这个时长改短的想法是错误理解了这个选项的意义。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    5.&amp;nbsp;SO_LINGER&lt;span style=&#34;font-family: 宋体;&#34;&gt;仅仅适用于面向连接的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;socket&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，比如&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;TCP&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SCTP&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，因此不适用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;UDP&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    Struct&amp;nbsp;linger{
  &lt;/p&gt;
  &lt;p&gt;
    int&amp;nbsp;l_onofff;
  &lt;/p&gt;
  &lt;p&gt;
    int&amp;nbsp;l_linger;
  &lt;/p&gt;
  &lt;p&gt;
    };
  &lt;/p&gt;
  &lt;p&gt;
    L_onoff&lt;span style=&#34;font-family: 宋体;&#34;&gt;为零是，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;behavior&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就是默认情况：&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;立即返回，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;kernel&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;继续发送缓冲区内未发送的数据。当&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;l_onoff&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;不为零，而&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;l_linger&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;TCP&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;协议则会立即终止连接，发送&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;RST&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;给&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;peer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;端，这样做避免了&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;TCP&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;TIME_WAIT&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;状态，这样的坏处是&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;:&amp;nbsp;leaves&amp;nbsp;open&amp;nbsp;the&amp;nbsp;possibility&amp;nbsp;of&amp;nbsp;another&amp;nbsp;incarnation&amp;nbsp;of&amp;nbsp;this&amp;nbsp;connection&amp;nbsp;being&amp;nbsp;created&amp;nbsp;within&amp;nbsp;2MSL&amp;nbsp;seconds&amp;nbsp;and&amp;nbsp;having&amp;nbsp;old&amp;nbsp;duplicate&amp;nbsp;segments&amp;nbsp;from&amp;nbsp;the&amp;nbsp;just-terminated&amp;nbsp;connection&amp;nbsp;being&amp;nbsp;incorrectly&amp;nbsp;delivered&amp;nbsp;to&amp;nbsp;the&amp;nbsp;new&amp;nbsp;incarnation.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;对于&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SCTP,&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;也会发送一个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ABORT&amp;nbsp;chunk&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;给&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;peer.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;第三种情况：如果&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;l_onoff&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;为真，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;l_linger&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;不为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;0.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;则&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;不会立即返回，会最多等待指定的时长，在这段时间里&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;kernel&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;发送缓冲区内的数据给&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;peer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。如果在这段时间内发送完则&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;返回&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;0.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;如果没有发送完毕，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就会返回&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;EWOULDBLOCK&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;send&amp;nbsp;buffer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;里的数据会被丢弃。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    6.&amp;nbsp;MSL:&amp;nbsp;maximum&amp;nbsp;segment&amp;nbsp;lifetime.
  &lt;/p&gt;
  &lt;p&gt;
    7.&amp;nbsp;因此&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;默认情况下立即返回，即使用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SO_LINGER&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;设置等待时间也在理论上存在&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;close&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;先于发送缓冲区的数据被&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;peer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;端&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;acknowleded&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的情况。因此一个更好的解决方案是用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;shutdown&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;系统调用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;with&amp;nbsp;a&amp;nbsp;second&amp;nbsp;argument&amp;nbsp;of&amp;nbsp;SHUT_WR&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。在调用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;shutdown&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;后，用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;read&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;调用直到&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;read&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;返回&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，即收到&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;peer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;端的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;FIN&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    8.&amp;nbsp;UDP&lt;span style=&#34;font-family: 宋体;&#34;&gt;没有&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;congestion&amp;nbsp;control&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，如果发得太快，不仅仅&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;peer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;端来不及收。&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;A&amp;nbsp;fast&amp;nbsp;sender&amp;nbsp;can&amp;nbsp;overwhelm&amp;nbsp;its&amp;nbsp;own&amp;nbsp;network&amp;nbsp;interface,&amp;nbsp;causing&amp;nbsp;datagrams&amp;nbsp;to&amp;nbsp;be&amp;nbsp;discarded&amp;nbsp;by&amp;nbsp;the&amp;nbsp;sender&amp;nbsp;itself.&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    9.&amp;nbsp;因为&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;tcp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;在三次握手阶段的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SYN&amp;nbsp;segment&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;里交换窗口大小&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;(windows&amp;nbsp;scale)&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。所以&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;tcp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的接收缓冲大小必须在&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;shank&amp;nbsp;hands&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;之前就设置好。&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Connected&amp;nbsp;socket&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;从&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;listening&amp;nbsp;socket&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;继承这个选项。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    10.&amp;nbsp;TCP&lt;span style=&#34;font-family: 宋体;&#34;&gt;的套接字缓冲区大小至少需要是&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;倍&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;MSS&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的大小。&lt;/span&gt;这里指的套接字缓冲，如果是针对单向的传输，比如单向传一个文件，指的是发送方的发送缓冲和接收方的接收缓冲。如果是双向的传输，则指的是双方的接收和发送缓冲。为什么&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;tcp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;套接字的缓冲区需要至少&amp;nbsp;&amp;nbsp;&amp;nbsp;是&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;倍&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;MSS&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的大小呢？&lt;/span&gt;这是因为&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;tcp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的快恢复&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;(fast&amp;nbsp;recovery)&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;算法。快恢复算法定义：如果接收端连续收到三个同样的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ACK&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，就认为有&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;packet&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;丢失了。而接收端在&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;segment&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;丢失后，每收到新的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;segment&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就不停地重发一个重复的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ack&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;给&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;sender&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。如果窗口大小小于&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;segments,&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就不会有三个重复的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ACK,&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;所以快恢复算法就没办法工作了。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    11.&amp;nbsp;What&amp;nbsp;is&amp;nbsp;bandwidth-delay&amp;nbsp;product.
  &lt;/p&gt;
  &lt;p&gt;
    A:&amp;nbsp;The&amp;nbsp;capacity&amp;nbsp;of&amp;nbsp;the&amp;nbsp;pipe&amp;nbsp;is&amp;nbsp;called&amp;nbsp;the&amp;nbsp;bandwidth-delay&amp;nbsp;product&amp;nbsp;and&amp;nbsp;we&amp;nbsp;calculate&amp;nbsp;this&amp;nbsp;by&amp;nbsp;multiplying&amp;nbsp;the&amp;nbsp;bandwidth(in&amp;nbsp;bits/sec)&amp;nbsp;times&amp;nbsp;the&amp;nbsp;RTT(in&amp;nbsp;seconds),&amp;nbsp;converting&amp;nbsp;the&amp;nbsp;result&amp;nbsp;from&amp;nbsp;bits&amp;nbsp;to&amp;nbsp;bytes.&amp;nbsp;&lt;span style=&#34;font-family: 宋体;&#34;&gt;即网速乘上&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;RTT.&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    12.&amp;nbsp;UDP&lt;span style=&#34;font-family: 宋体;&#34;&gt;没有&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;send&amp;nbsp;buffer&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，但有一个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;send&amp;nbsp;buffer&amp;nbsp;size.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;只要&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;socket&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;buffer&amp;nbsp;size&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;大于&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;LO_WATER&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，就永远是可写的。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    13.&amp;nbsp;SO_REUSEADDR&lt;span style=&#34;font-family: 宋体;&#34;&gt;有四种用途。好难写。见&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Unix&amp;nbsp;Network&amp;nbsp;Programming&amp;nbsp;Section&amp;nbsp;7.5&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;影印版第&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;211&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;页啦。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    14.&amp;nbsp;It&#39;s&amp;nbsp;Ok&amp;nbsp;for&amp;nbsp;the&amp;nbsp;MSS&amp;nbsp;to&amp;nbsp;be&amp;nbsp;different&amp;nbsp;in&amp;nbsp;each&amp;nbsp;direction.
  &lt;/p&gt;
  &lt;p&gt;
    15.&amp;nbsp;Nagle&lt;span style=&#34;font-family: 宋体;&#34;&gt;算法是为了减少&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;small&amp;nbsp;package&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的数量.&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;The&amp;nbsp;algorithm&amp;nbsp;states&amp;nbsp;that&amp;nbsp;if&amp;nbsp;a&amp;nbsp;given&amp;nbsp;connection&amp;nbsp;has&amp;nbsp;outstanding&amp;nbsp;data,&amp;nbsp;then&amp;nbsp;no&amp;nbsp;small&amp;nbsp;packets&amp;nbsp;will&amp;nbsp;be&amp;nbsp;sent&amp;nbsp;on&amp;nbsp;the&amp;nbsp;connection&amp;nbsp;in&amp;nbsp;response&amp;nbsp;to&amp;nbsp;a&amp;nbsp;user&amp;nbsp;write&amp;nbsp;operation&amp;nbsp;until&amp;nbsp;the&amp;nbsp;existing&amp;nbsp;data&amp;nbsp;is&amp;nbsp;acknowledged.&amp;nbsp;Small&amp;nbsp;package&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;指的是任何比&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;MSS&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;小的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;package.&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    16.&amp;nbsp;Delayed&amp;nbsp;ACK&amp;nbsp;algorithm:&amp;nbsp;This&amp;nbsp;algorithm&amp;nbsp;causes&amp;nbsp;TCP&amp;nbsp;to&amp;nbsp;not&amp;nbsp;send&amp;nbsp;an&amp;nbsp;ACK&amp;nbsp;immediately&amp;nbsp;when&amp;nbsp;it&amp;nbsp;receives&amp;nbsp;data;&amp;nbsp;instead,&amp;nbsp;TCP&amp;nbsp;will&amp;nbsp;wait&amp;nbsp;some&amp;nbsp;small&amp;nbsp;amount&amp;nbsp;of&amp;nbsp;time&amp;nbsp;(typically&amp;nbsp;50-200ms)and&amp;nbsp;only&amp;nbsp;then&amp;nbsp;send&amp;nbsp;the&amp;nbsp;ACK.
  &lt;/p&gt;
  &lt;p&gt;
    17.&amp;nbsp;SCTP&lt;span style=&#34;font-family: 宋体;&#34;&gt;有一个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SCTP_AUTOCLOSE&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;套接字选项。&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;This&amp;nbsp;option&amp;nbsp;allows&amp;nbsp;us&amp;nbsp;to&amp;nbsp;fetch&amp;nbsp;or&amp;nbsp;set&amp;nbsp;the&amp;nbsp;autoclose&amp;nbsp;time&amp;nbsp;for&amp;nbsp;an&amp;nbsp;SCTP&amp;nbsp;endpoint.&amp;nbsp;The&amp;nbsp;autoclose&amp;nbsp;time&amp;nbsp;is&amp;nbsp;the&amp;nbsp;number&amp;nbsp;of&amp;nbsp;seconds&amp;nbsp;an&amp;nbsp;SCTP&amp;nbsp;association&amp;nbsp;will&amp;nbsp;remain&amp;nbsp;open&amp;nbsp;when&amp;nbsp;idle.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;即&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;SCTP&amp;nbsp;association&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;能够保持空闲状态的最长时间。超时就会被关闭。&lt;/span&gt;
  &lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>Unix网络编程.第五，六章笔记.</title>
      <link>https://ykyi.net/?p=284/</link>
      <pubDate>Sat, 10 Dec 2011 13:56:00 +0000</pubDate>
      <guid>https://ykyi.net/?p=284/</guid>
      <description>&lt;p&gt;# Unix世界里经常看到的 pst  是 pseudo terminal 的意思啊。&lt;/p&gt;
&lt;p&gt;# ps -t pts/6 -o pid,ppid,tty,stat,args,wchan&lt;/p&gt;
&lt;p&gt;ps 命令的进程状态。 S表示进程在睡眠，I表示进程在等待输入，O表示进程在等待输出。当进程在S状态时，wlan指示了更详细的状态信息。&lt;/p&gt;
&lt;p&gt;# SIGSTOP 和 SIGKILL 两个posix信号不可以被caught.&lt;/p&gt;
&lt;p&gt;# 缺省情况下，Unix的信号是不排在队列中的。这意味着多个相同signal到达的时候如果没有来得及处理，就只会记下一个signal.如果需要稳定的信号支持，就要使用RealTime Posix接口。&lt;/p&gt;
&lt;p&gt;# init 进程的PID是 1.&lt;/p&gt;
&lt;p&gt;# 可以用sigprocmask函数block和unblock信号。This let us protect a critical region of code by preventing certain signals from being caught while that region of code is executing.&lt;/p&gt;
&lt;p&gt;# 对于 Unix System V 和 Unix98, the child of a process does not become a zombie if the process sets the disposition of SIGCHLD to SIG_IGN. unfortunately, tis works only under System V &amp;amp; Unix98. Posix明确指票这个行为是未定义的。The portable way to handle zombies is to catch SIGCHILD &amp;amp; call wait or waitpid.&lt;/p&gt;</description>
    </item>
    <item>
      <title>linux的soname，链接库的问题.</title>
      <link>https://ykyi.net/?p=269/</link>
      <pubDate>Thu, 08 Dec 2011 09:36:54 +0000</pubDate>
      <guid>https://ykyi.net/?p=269/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;第一次看到soname是读&amp;lt;程序员的自我修养.第一册:链接库&amp;gt;看来的。顺便说一下，这本书确实是本好书吖，国内出的难得技术好书。后来在公司的项目中把它从windows平台下移植到linux下，写makefile时用到过。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;再后来又忘记了。今天再次看到soname的时候就有点记不起来了。又只好搜索了一些资料看。趁热打铁把学会的东西记下来。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;linux为尝试解决动态链接库版本冲突的问题(windows平台下称之为DLL HELL)，引入了soname进制。linux的动态链接库的扩展名约定为.so 即shared object的缩写。下面的makefile语句来自于哥今年上半年写的makefile文件:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;&lt;span style=&#34;color: rgb(0, 0, 255); &#34;&gt;VERSION_NUM := 1.0.0&lt;/span&gt;&lt;br /&gt; soname = lib$(dirname).so.$(firstword $(subst ., ,$(VERSION_NUM)))&lt;br /&gt; LINKFLAGS := -shared -Wl,-soname,$(soname) -L. -lpthread -lrt -lpentagon -lcross_platform&lt;br /&gt; 其中的变量$(soname)会被替换为eibcomm.so.1。再看看LINKFLAGS变量指定的几个选项. -shared 表示要生成一个shared object，即动态共享库. -pthread -lrt -lpentagon -lcross_platform 是要链接其它几个库，thread和linux的posix线程库,rt是一个和实时系统相关的库它提供了高精度的时间函数。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;比较奇怪的是 -Wl,-soname,$(soname) 它们之前用逗号分开，而不是用空格分开。实际上这几个东东会被gcc传给ld(linux下的链接器)作为链接器的参数。gcc规定的写法就是这样的。指定的soname会被链接器写入到最终生成的elf文件中(linux下的可执行文件格式)。要查看elf文件的段布局什么的，可以用readelf工具。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;最终生成的文件将命名为 libname.so.x.y.z 的形式。soname是libname.so.x的格式(也不尽然，这只是一个convetion,并非在语法或机制上强行要求)。接着把生成的so文件拷贝到/usr/lib 或者 /lib，这两个文件夹是系统用来放置动态链接库的地方。debian下没有把/usr/local/lib作为默认的动态链接库文件夹.可以通过改/etc/ld.so.conf 文件把更多的路径加入。再运行 ldconfig,更新cache中的库文件信息。为什么要用cache呢，有人就问了！因为library实在太多了咯，cache就被引用了。cache是个好东西啊！！！&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;这个时候依赖 libname.so.x 的文件就可以找到这个library并加载起来了。但是编译程序时还是找不到呢.编译程序时通常会写 -lname 这个时候会先找 libname.so 再找 libname.a 文件，结果找不到。link就会抱怨没有找到这个库文件。为了让编译通过，于是你就用 ln -sf libname.so libname.so.x.y.z (这个是realname,版本号部分可能只有x.y两个部分) 建一个软链接！搞定！&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;copyright ykyi.net&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>initramfs 和 initrd 的区别</title>
      <link>https://ykyi.net/?p=236/</link>
      <pubDate>Fri, 25 Nov 2011 05:21:49 +0000</pubDate>
      <guid>https://ykyi.net/?p=236/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;Linux 2.6内核引入了一个新的feature叫做initramfs。与initrd相比,initramfs有几个好处。&lt;br /&gt; initrd模拟一个磁盘(这就是它的名字的由来，initramdisk或initrd)。模拟磁盘也就同时引入了Linux的块IO子系统的开销，比如缓存(caching)，而initramfs从根本上把cache也装载(mounted)成filesystem(因此叫做initramfs).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;Initramfs建立在page cahce之上，和page cache一样，会动态地自动增长和缩减尺寸来减入内存的使用量，而initrd做不到这点。&lt;br /&gt; 另外，不像initrd需要文件系统驱动(filesystem driver)的支持，比如EXT2 driver，如果你的initrd使用ext2。而initramfs则不需要文件系统的支持，initramfs的实现代码很简单，只是基于page cache的简单一层。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;copyright ykyi.net&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux的开机启动顺序</title>
      <link>https://ykyi.net/?p=228/</link>
      <pubDate>Fri, 25 Nov 2011 05:01:39 +0000</pubDate>
      <guid>https://ykyi.net/?p=228/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;对于x86机器的Linux的启动顺序，BIOS首先从启动设备载入MBR(Master Boot Record).存在MBR里的代码就去找分区表，从活动分区读入Linux的bootloader，最常用的像Grub,其它的有LILO,SYSLINUX。&lt;br /&gt; Bootloader把压缩格式的内核映象载入并把控制权交给内核映像。&lt;br /&gt; 内核映像自解压，启动内核！&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;x86处理器有两种工作模式。实模式和保护模式。在实模式，你只能够寻址1M内存。保护模式下，就复杂得多，可以作到使用处理器的很多高级特性比如分页。CPU必须从实模式转到保护模式是一个单行通道(one-way street)。你不能从保护模式退入实模式。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;内核第一阶段的内核初始化是在实模式中完成的。接下来从init/main.c 中定义的 start_kernel()函数进入你保护模式。start_kernel()先初始化CPU subsystem。接下来启动存储器和进程管理。然后启动外围总线和IO设备。启动序列的最后一个阶段便是init进程被启动。这个进程是所有的Linux进程的祖先。Init进程执行用户空间的脚本。这些脚本被用来启动必要的内核服务程序。Init最后spawn一个控制台给你。于是启动就完成了。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size:14px;&#34;&gt;copyright ykyi.net&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Diff, Patch, and Friends(diff, patch和他们的相关工具)(第二篇)</title>
      <link>https://ykyi.net/?p=191/</link>
      <pubDate>Fri, 02 Sep 2011 05:16:30 +0000</pubDate>
      <guid>https://ykyi.net/?p=191/</guid>
      <description>&lt;p&gt;原文 &lt;a href=&#34;http://www.linuxjournal.com/article/1237&#34;&gt;http://www.linuxjournal.com/article/1237&lt;/a&gt;&lt;br&gt;
翻译: &lt;a href=&#34;https://www.ykyi.net&#34;&gt;www.ykyi.net&lt;/a&gt; zausiu&lt;br&gt;
&lt;a href=&#34;http://ykyi.net/2011/02/diff-patch-and-friendsdiff-patch%e5%92%8c%e4%bb%96%e4%bb%ac%e7%9a%84%e7%9b%b8%e5%85%b3%e5%b7%a5%e5%85%b7%e7%ac%ac%e4%b8%80%e7%af%87/&#34; title=&#34;接上篇&#34;&gt;接上篇&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Use the diff program to avoid eyestrain and insanity:&lt;br&gt;
使用diff程序来避免会令人发疯的肉眼查找。&lt;/p&gt;
&lt;p&gt;diff -u 1 2&lt;br&gt;
— 1 Sat Apr 20 22:11:53 1996&lt;br&gt;
+++ 2 Sat Apr 20 22:12:01 1996&lt;br&gt;
-1,9 +1,9&lt;br&gt;
Ecce Eduardus Ursus scalis nunc tump-tump-tump&lt;br&gt;
occipite gradus pulsante post Christophorum&lt;br&gt;
Robinum descendens. Est quod sciat unus et solus&lt;br&gt;
-modus gradibus desendendi, non nunquam autem&lt;br&gt;
+modus gradibus descendendi, nonnunquam autem&lt;br&gt;
sentit, etiam alterum modum exstare, dummodo&lt;br&gt;
-pulsationibus desinere et de no modo meditari&lt;br&gt;
+pulsationibus desinere et de eo modo meditari&lt;br&gt;
possit. Deinde censet alios modos non esse. En,&lt;br&gt;
nunc ipse in imo est, vobis ostentari paratus.&lt;br&gt;
Winnie ille Pu.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Syntax Highlight in DDD DDD的语法高亮</title>
      <link>https://ykyi.net/?p=198/</link>
      <pubDate>Wed, 24 Aug 2011 00:32:07 +0000</pubDate>
      <guid>https://ykyi.net/?p=198/</guid>
      <description>&lt;p&gt;这几天用DDD调试linux下的程序.发现DDD没有语法高亮~&lt;br&gt;
于是google了一下。悲剧地发现一个贴子:&lt;/p&gt;
&lt;p&gt;Hello!&lt;/p&gt;
&lt;p&gt;Is it possible to enable syntax highlighting in DDD?&lt;br&gt;
I searched through the Google and found this answer:&lt;br&gt;
可以在DDD里开启语法高亮吗？我用谷歌搜索后发现这个答案。&lt;/p&gt;
&lt;p&gt;Sorry, no, this isn’t possible.&lt;br&gt;
The biggest problem is that Motif’s text widget doesn’t&lt;br&gt;
support multiple colours, and would have to be replaced.&lt;br&gt;
That would be an enormous job.&lt;br&gt;
不好意思。没有！这不可能.&lt;br&gt;
最大的问题是Motif的文本控件不支持多彩显示，必须把motif替换掉.&lt;br&gt;
这不是一个普通的/简单的任务.&lt;/p&gt;
&lt;p&gt;/////////////////////&lt;br&gt;
悲剧啊！！！在黑白的Linux世界。………..&lt;/p&gt;
&lt;p&gt;Is it still impossible (post date is Thu, 10 Feb 2005)?&lt;br&gt;
Are there any workarounds/patches/forks?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Diff, Patch, and Friends(diff, patch和他们的相关工具)(第一篇)</title>
      <link>https://ykyi.net/?p=188/</link>
      <pubDate>Sat, 12 Feb 2011 03:29:02 +0000</pubDate>
      <guid>https://ykyi.net/?p=188/</guid>
      <description>&lt;p&gt;原文 &lt;a href=&#34;http://www.linuxjournal.com/article/1237&#34;&gt;http://www.linuxjournal.com/article/1237&lt;/a&gt;&lt;br&gt;
翻译: ykyi.net&lt;/p&gt;
&lt;p&gt;“Kernel patches” may sound like magic, but the two tools used to create and apply patches are simple and easy to use—if they weren&amp;rsquo;t, some Linux developers would be too lazy to use them…&lt;br&gt;
&amp;ldquo;内核补丁&amp;quot;听起来相当之神奇，但是有两个用来创建补丁和应用补丁的工具却简单易用。如果它们很难用的话，一些Linux开发者才懒得用它们呢。&lt;/p&gt;
&lt;p&gt;Diff is designed to show you the differences between files, line by line. It is fundamentally simple to use, but takes a little practice. Don&amp;rsquo;t let the length of this article scare you; you can get some use out of diff by reading only the first page or two. The rest of the article is for those who aren&amp;rsquo;t satisfied with very basic uses.&lt;br&gt;
diff这个工具设计成可以向你展示文件之间行与行的区别。它使用起来是相当的简单，但需要一点练习才习。你千万不要让长长的介绍文档把你吓住。你可以先只读前一两页文档，这样你就可以使用diff来开展一些工作了。余下的diff介绍文档是写给那些对基本用法非常不满的奇异人士的。 &lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>tcpdump基础教程</title>
      <link>https://ykyi.net/?p=45/</link>
      <pubDate>Sun, 31 Oct 2010 05:34:49 +0000</pubDate>
      <guid>https://ykyi.net/?p=45/</guid>
      <description>&lt;p&gt;英文原文出自： &lt;a href=&#34;http://danielmiessler.com/study/tcpdump/&#34;&gt;A tcpdump Tutorial and Primer&lt;/a&gt;&lt;br&gt;
翻译: ykyi.net&lt;/p&gt;
&lt;p&gt;Tcpdump是信息安全专业人士最重要的一个网络分析工具。对这个工具有一个深入的理解对于每一个喜欢透彻理解tcp/ip协议栈的人来话都是必须的。但很多人选择一个更高级别的工级，比如Ethereal Wireshark，但是我认为这是一个错误！&lt;/p&gt;
&lt;p&gt;不应该机械的反复记忆概念而应该做到真正的理解，因为对tcp/ip协议簇保持清醒的认知非常的重要。如果对该协议簇能够完全精通，那你调试网络的能力则能比同行们高出几个档次。但是，要学精神tcp/ip协议簇，只有不够的实践剖析它们才能做到。&lt;/p&gt;
&lt;p&gt;当你使用某种工具来显示网络中的原始流量信息时，人类，而不是机器，就要承担起分析这些流量的重任了。用这种方法就可以不断地加深对tcp/ip的理解。并且，用这种学习方法的时候，我在任何可能的情况下都强烈主张使用tcpdump而不是其它工具。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;选项&lt;/strong&gt;&lt;br&gt;
下面将列出一些用例子的选项，这样可以在你使用这个工具时对你有很大的帮助。这些选项很容易淡忘或与其它类型的滤镜(Filter,笔者认为这里的滤镜实际上指的是其它网络工具)混淆。比如, ethereal。所以，希望这篇文章可以作为一个参考文档，我就是这样使用它的。&lt;/p&gt;
&lt;p&gt;首先，我要先介绍几个我认为很方便的tcpdump的选项。第一个是 -n, 这样的话域名就不会被解析了，而是用数字IP的形式显示地址(译者注: 同netstat的-n是一样的喔)。第二个是 -X, 这样就会同时把包的内容以ASCII码和十六制的形式显示。最后一个是 -S, 它个选项会显示绝对序号而不是相对序号。因为当包被隐藏起来的话，你也不会看到奇怪的序号。请谨记，tcpdump较之其它工具的优势之一就是可以与包(packets)手工交互。&lt;/p&gt;
&lt;p&gt;值得注意的是，tcpdump默认只会从packet中取出前96个字节。如果你想要多一些的话，那就需要需要把 -s xxxx 加上。这里的xxxx是你确切想要抓取的总字节数。如果我使用这个选项的话，我通常会把这个数字设定为1514而得到所有的数据。下面是一个简短的列表列出我经常使用的选项。&lt;/p&gt;
&lt;p&gt;-i any: 监听所有的介面。这样你就知道是不是有流量产生。&lt;br&gt;
-n: 不要解决主机名，以IP数字形式显示主机。&lt;br&gt;
-nn: 不要解析主机名或端口名字。&lt;/p&gt;
&lt;p&gt;-A: 以ASCII字符显示包的数据。&lt;br&gt;
-X: 同时以十六进制和ASCII字符显示包的数据。&lt;br&gt;
-XX: 同-X,但也会显示 Ethernet头部。&lt;br&gt;
-v, -vv, -vvv: 详细，更详细，再详细些！ 冗余输出得到的包信息。&lt;br&gt;
-c: 抓取 x 个包后就停下。&lt;br&gt;
-S: 打印绝对序号。&lt;br&gt;
-e: 同时得到Ethernet头部。&lt;br&gt;
-q: 显示少一点协议信息。&lt;br&gt;
-E: 用提供的密钥解密 IPSEC 流量。&lt;br&gt;
-s: 设置显示前多少个字节的包内容（snaplength）。&lt;/p&gt;
&lt;p&gt;tcpdump 4.0的snaplength的长度从68字节改成了96字节，这样你就可以看到多些内容了。但仍然看不到所有的内容，指定 -s 1514 得到包的所有内容。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;一些基本的应用&lt;/strong&gt;&lt;br&gt;
根据我要查看的不同流量，我使用不同的选项组合，如下:&lt;/p&gt;
&lt;p&gt;1.Basic communication // see the basics without many options&lt;br&gt;
tcpdump -nS&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
