<?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>Linux on kamuszhou&#39;s blog</title>
    <link>https://ykyi.net/tags/linux/</link>
    <description>Recent content in Linux on kamuszhou&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Fri, 14 Jun 2019 09:06:00 +0000</lastBuildDate>
    <atom:link href="https://ykyi.net/tags/linux/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>linux怎么把一个正在前台运行的进程用nohup放入后台运行</title>
      <link>https://ykyi.net/?p=1592/</link>
      <pubDate>Fri, 14 Jun 2019 09:06:00 +0000</pubDate>
      <guid>https://ykyi.net/?p=1592/</guid>
      <description>&lt;p&gt;假设进程在控制台运行。&lt;br&gt;
三个步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ctrl + z 停止正在运行的进程&lt;/li&gt;
&lt;li&gt;$ bg 命令把该进程放入后台&lt;/li&gt;
&lt;li&gt;disown -h [job的序号] 后台的进程有类似%1, %2, %3的序号。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;至此，一个正在控制台前台运行进程被放入后台，且忽略SIGHUP信号。这样，即使关闭了控制台，也不会杀死这个进程了。&lt;/p&gt;</description>
    </item>
    <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>Linux系统级/进程级最多打开文件数,FD文件描述符数</title>
      <link>https://ykyi.net/?p=1551/</link>
      <pubDate>Thu, 22 Nov 2018 11:55:39 +0000</pubDate>
      <guid>https://ykyi.net/?p=1551/</guid>
      <description>&lt;p&gt;如何增加Linux系统最大文件打开数目呢？&lt;/p&gt;
&lt;h3 id=&#34;查看系统最大可打开文件数&#34;&gt;查看系统最大可打开文件数&lt;/h3&gt;
&lt;p&gt;以下命令查看操作系统级最多可打开文件数,fd数目&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;$ cat /proc/sys/fs/file-max
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我用ubuntu 16输出:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;573738
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;怎么调整系统最大可打开文件数&#34;&gt;怎么调整系统最大可打开文件数&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;# sysctl -w fs.file-max=1000000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;需要用root用户执行以上命令，设最大为一百万。&lt;br&gt;
但在命令行上修改了这个配置，会在下一次操作系统重启后重置为以前的值。要一劳永逸的改变系统最大打开文件数，需要修改 /etc/sysctl.conf 文件。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;fs.file-max = 1000000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在/etc/sysctl.conf文件中增加上述一行。&lt;/p&gt;
&lt;h3 id=&#34;ulimit命令查看调整进程级最大文件打开数&#34;&gt;ulimit命令查看/调整进程级最大文件打开数&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;$ ulimit -Sn
1024
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个命令查看一个ulimit的软极限值(soft limit)，本用户起的进程的最大文件打开数的限制。我的ubuntu 16显示进程最多开1024个fd。如果要提高每个进程可同时打开的文件数，需要更改这个值。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;&#34;&gt;$ ulimit -Sn 2048
bash: ulimit: open files: cannot modify limit: Invalid argument
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但我想把每个进程可同时打开的文件数增加到以前的两倍时，报错了。这是因为，软极限值(soft limit)不能够越过(Hard Limit)。我看了一下Hard limit，也是1024&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;&#34;&gt;$ ulimit -Hn
1024
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那没办法罗，需要以root用户登录更改Hard Limit。&lt;/p&gt;
&lt;h3 id=&#34;怎么修改普通用户的硬极限hard-limit&#34;&gt;怎么修改普通用户的硬极限hard Limit&lt;/h3&gt;
&lt;p&gt;用root账户登录后，编辑 /etc/security/limits.conf文件，假如普通用户名是kamuszhou。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-bash &#34;&gt;kamuszhou hard nofile 10000
kamuszhou soft nofile 5000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上配置修改kamuszhou普通用户的最多打开文件数的hard limit为10000，soft limit为5000。&lt;br&gt;
对于ubuntu 16，如果使用图形桌面，还需要修改 /etc/systemd/system.conf 和 /etc/systemd/user.conf。&lt;br&gt;
加上这么一行：&lt;/p&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>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>dpkg的一些用法</title>
      <link>https://ykyi.net/?p=940/</link>
      <pubDate>Mon, 25 Feb 2013 02:28:11 +0000</pubDate>
      <guid>https://ykyi.net/?p=940/</guid>
      <description>&lt;div class=&#34;showHead&#34; style=&#34;padding: 0px; margin: 5px 12px 0px; height: 60px; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: rgb(204, 204, 204); color: rgb(85, 85, 85); font-family: 宋体, &#39;Arial Narrow&#39;, arial, serif; line-height: normal;&#34;&gt;
  &lt;div class=&#34;showTitleBOx&#34; style=&#34;padding: 20px 0px 0px; margin: 0px; overflow: hidden; text-align: center;&#34;&gt;
    &lt;div class=&#34;showTitle&#34; style=&#34;padding: 0px; margin: 0px; font-weight: bold; font-size: 20px; line-height: 20px; font-family: 宋体;&#34;&gt;
      Debian的dpkg的一些用法
    &lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;p&amp;gt;
  &amp;amp;nbsp;
&amp;lt;/p&amp;gt;&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;showContent&#34; style=&#34;padding: 0px; margin: 20px 15px 8px; line-height: 2; font-size: 14px; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: rgb(217, 217, 217); word-wrap: break-word; word-break: normal; color: rgb(85, 85, 85); font-family: 宋体, &#39;Arial Narrow&#39;, arial, serif;&#34;&gt;
  &lt;b style=&#34;padding: 0px; margin: 0px;&#34;&gt;1. 查看当前系统中的软件信息(dpkg -l)&lt;/b&gt;&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; &#34;dpkg -l&#34;命令用于查看当前系统中所有deb的软件包信息；通过&#34;dpkg -l&#34;命令与less和grep命令配合使用，可以实现更复杂的软件包信息查询功能。&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&#34;padding: 0px; margin: 0px; color: rgb(102, 102, 204);&#34;&gt;debian:~/Desktop# dpkg -l&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; 期望状态=未知(u)/安装(i)/删除(r )/清除(p)/保持(h)&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; | 当前状态=未(n)/已安装(i)/仅存配置(c )/仅解压缩(U)/配置失败(F)/不完全安装(H)&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; |/ 错误？=(无)/保持(?)/须重装(R )/两者兼有(#) (状态，错误：大写=故障)&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; ||/ 名称 版本 简介&lt;/span&gt;&lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br style=&#34;padding: 0px; margin: 0px;&#34; /&gt;&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>今天用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>使用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>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>使用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>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>内核线程是什么东东 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>我看过的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>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>
  </channel>
</rss>
