﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Good Good code,Day Day up-文章分类-Linux/Unix</title><link>http://www.cppblog.com/dawnbreak/category/8987.html</link><description>PearLi's Blog</description><language>zh-cn</language><lastBuildDate>Sun, 30 Jan 2011 00:48:05 GMT</lastBuildDate><pubDate>Sun, 30 Jan 2011 00:48:05 GMT</pubDate><ttl>60</ttl><item><title>AT&amp;T汇编语言(转)</title><link>http://www.cppblog.com/dawnbreak/articles/139598.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Sat, 29 Jan 2011 14:51:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/139598.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/139598.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/139598.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/139598.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/139598.html</trackback:ping><description><![CDATA[<font size=5>&nbsp;&nbsp;今天开始学习linux内核编程了，从没有内核编程基础开始学起。所以很多相关的知识都要了解。首先就是AT&amp;T汇编语言。因为在linux内核源代码中，好像除了开始的bootsect.s和head.s是用intel的汇编外，别的汇编代码都是用的AT&amp;T汇编语言，所以有必要把AT&amp;T汇编语言了解一下。</font>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">不过，由于AT&amp;T汇编和intel汇编大同小异，所以，了解一下一些不同的地方就可以了。</span></div>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 以下的内容都是AT&amp;T汇编的特点：</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">1、寄存器前面要加&#8220;%&#8221;，如&nbsp; mov %eax,%ebx</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;这里要注意的一点是，AT&amp;T汇编中，源寄存器和目的寄存器的顺序和intel汇编刚好相反，AT&amp;T汇编中，左边的是源寄存器，右边的是目的寄存器，在上边那个例子中，%eax是源寄存器，%ebx是目的寄存器。</span></div>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">2、立即数/常数前面要加$，如&nbsp; mov&nbsp;$4,%ebx&nbsp;把4这个数装入ebx这个寄存器。</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 符号常数直接用， 如&nbsp; mov&nbsp; value,%eax 即把value代表的那个值装入eax寄存器。</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov $value,%eax 即把value的值作为地址，而把对应那个地址中的值装入eax。</span></div>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">3、b(byte):8位， w（word）：16位， l（long）：32位</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 如：&nbsp; movb %al,%bl&nbsp;&nbsp;&nbsp;&nbsp; movw&nbsp;%ax,%bx&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,%ebx</span></div>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">4、jum/call的操作数前要加上&#8220;*"作为前缀， 远跳转ljmp，远调用lcall</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 如&nbsp; ljmp $section,$offset</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lcall $section,$offset</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 这里$section和offset表示的就是，以section为段地址，offset为段内偏移地址。因此，ljmp $section,$offset即跳转到section:offset地址。</span></div>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">5、远返回lret</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 如&nbsp; lret $stack_adjust</span></div>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">6、寻址方式</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 21px; -webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px" class=Apple-style-span>寄存器间接寻址&nbsp;AT&amp;T:&nbsp;(%eax) &nbsp;Intel:&nbsp;[eax] &nbsp;</span></span></div>
<p><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 表示方式&nbsp;section:disp(base,index,scale)</span></p>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 计算方法 base+index*scale+disp</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;即 section:[base+index*scale+disp]</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 其中disp是表示偏移地址。</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 如&nbsp; movl -4(%ebp),%eax&nbsp; 把[%ebp-4]的内容装入eax</span></div>
<p><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 21px; BORDER-COLLAPSE: separate; FONT-FAMILY: Verdana; FONT-SIZE: 14pt; -webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px" class=Apple-style-span>变址寻址 &nbsp;AT&amp;T:&nbsp;_variable(%eax) &nbsp;Intel:&nbsp;[eax&nbsp;+&nbsp;_variable]</span></span></p>
<span style="LINE-HEIGHT: 21px; BORDER-COLLAPSE: separate; FONT-FAMILY: Verdana; FONT-SIZE: 14pt; -webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px" class=Apple-style-span>　　　　　 &nbsp;AT&amp;T:&nbsp;_array(,%eax,4)&nbsp;&nbsp;</span><span style="LINE-HEIGHT: 21px; BORDER-COLLAPSE: separate; FONT-FAMILY: Verdana; FONT-SIZE: 14pt; -webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px" class=Apple-style-span>Intel:&nbsp;[eax*4&nbsp;+&nbsp;_array]<br></span><span style="LINE-HEIGHT: 21px; BORDER-COLLAPSE: separate; FONT-FAMILY: Verdana; FONT-SIZE: 14pt; -webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px" class=Apple-style-span>　　　　 &nbsp; &nbsp; AT&amp;T:&nbsp;_array(%ebx,%eax,8)&nbsp;&nbsp;</span><span style="LINE-HEIGHT: 21px; BORDER-COLLAPSE: separate; FONT-FAMILY: Verdana; FONT-SIZE: 14pt; -webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px" class=Apple-style-span>Intel:&nbsp;[ebx&nbsp;+&nbsp;eax*8&nbsp;+&nbsp;_array]&nbsp;&nbsp;<span style="BORDER-COLLAPSE: collapse" class=Apple-style-span>&nbsp;</span></span>
<div>&nbsp;</div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">7、C语言中嵌入汇编</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 格式: _asm_("asm statements":outputs:inputs:registers-modified)</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 其中，"asm statements"是汇编语句表达式，outputs,inputs,register-modified都是可选参数，以冒号隔开，且一次以0～9编号，如outputs的寄存器是0号，inputs寄存器是1号，往后依次类推。outputs是汇编语句执行完后输出到的寄存器，inputs是输入到某个寄存器。</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;例1：_asm_("pushl %%eax\n\t" "movl $0,%%eax\n\t" "popl %%eax");</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 在嵌入汇编中，寄存器前面要加两个%，因为gcc在编译是，会先去掉一个%再输出成汇编格式。</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp; 例2：{ register char _res;\</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;asm("push %%fs\n\t"</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "movw %%ax,%%fs\n\t"</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "movb %%fs:%1,%%al\n\t"</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"pop %%fs"</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :"=a"(_res):"0"(seg),"m"(*(addr)));\</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _res;}</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp; movb %%fs:%1,%%al\n\t一句中是把以fs为段地址，以后面的第二号寄存器即后面的seg中的值为偏移地址所对应的值装入al。"=a"(_res):"0"(seg),"m"(*(addr)))一句中，"=a"(_res)表示把a寄存器中的内容给_res，"0"(seg)表示把seg中的内容给0所对应的寄存器，而0即表示使用和前一个寄存器相同的寄存器，这里即使用a寄存器，也就是说把seg中的内容个a寄存器。</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;需要解释以下的是，a,b,c,d分别表示寄存器eax，ebx，ecx，edx</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; S，D分别表示寄存器esi，edi</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r表示任意寄存器</span></div>
<div><span style="FONT-FAMILY: Verdana; FONT-SIZE: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0（数字0，不是o！）表示使用上一个寄存器</span></div>
<script type=text/javascript>
if ($ != jQuery) {
$ = jQuery.noConflict();
}
var isLogined = false;
var cb_blogId = 64958;
var cb_entryId = 1645194;
var cb_blogApp = "parrynee";
var cb_blogUserGuid = "94efeb15-54f5-de11-ba8f-001cf0cd104b";
var cb_entryCreatedDate = '2010/1/12 15:25:00';
</script>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/139598.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2011-01-29 22:51 <a href="http://www.cppblog.com/dawnbreak/articles/139598.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入分析任务切换与堆栈 </title><link>http://www.cppblog.com/dawnbreak/articles/139597.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Sat, 29 Jan 2011 14:50:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/139597.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/139597.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/139597.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/139597.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/139597.html</trackback:ping><description><![CDATA[深入分析任务切换与堆栈 by Liu Wanli <br><br>关键字：时间中断、任务切换、堆栈、LINUX0.01 <br><br>引言： <br><br>任务切换与堆栈的关系怎样？很多朋友可能不知道她们之间有什么关系，还有一些朋友可能认为他们之间不会有太大的关系（文献4）。而我认为：任务切换跟堆栈有着密切的关系！下面是我对它们之间关系进行的探讨，这里的任务切换我指的是发生时间中断时进行强制调度发生的任务切换，所以下面考虑堆栈时我是从中断开始探讨的。当然，我在进行这方面分析的时候，也愈感它们的复杂性，错误之处在所难免，望各位朋友多多指正。建议读者水平：* * * <br><br><br>一、时间中断。 <br><br>假设一个进程在用户空间执行时（这时CPL=3），发生了时间中断。这时的中断处理过程为（文献1：P438）： <br>1、根据中断向量号找到中断门描述符； <br>2、从描述符中分解出选择子、偏移量、属性字段并进行相应的特权检查； <br>3、根据描述符类型转入相应中断处理程序中去执行。 <br>好象太肤浅了一些？再看看（文献1：P439图10.20）： <br>1、选择子为空？no继续； <br>2、取得对应描述符；（描述符中DPL属性应该为0，文献3中断向量初始化部分） <br>3、存储段描述符？yes继续； <br>4、非一致代码段且DPL&lt;CPL且段存在？yes继续；根据假设CPL=3，DPL=0，所以到5！ <br>5、切换成内层堆栈！ <br>如何切换？？因为一个进程有用户空间堆栈和系统空间（也叫内核空间）堆栈，用户空间堆栈在哪儿我不管，它应该是由该进程的任务状态段TSS中SS2指定，SS0指定系统空间堆栈，它和该进程任务结构task_struct共占一页空间（见文献3:sched.c）。所以这里的切换成内层堆栈应该是将该进程的TSS中SS0的值赋给SS寄存器。 <br>6、使RPL=0； <br>7、把描述符装入CS； <br>8、入口偏移越界？no继续； <br>9、EFLAG、CS、EIP入栈；呵，开始栈的改变了哟！ <br>10、TF=0、NT=0、IF=0；这里考虑的是中断门。 <br>11、转入处理程序。 <br><br>别急，先看看现在的堆栈情况： <br><br>| 外层EIP | <br>| 外层CS | <br>| EFLAG | <br>| 外层ESP | <br>| 外层SS | <br>----------- <br>这个栈在什么地方呢？这相当重要！这是在当初切换至内层堆栈时进行的，即已经到了当前进程的系统空间堆栈，也就是跟task_struct共占一页的那个堆栈。而这里保存的就是该进程在用户空间的堆栈和代码信息，以便中断完成后恢复进程执行。 <br><br>二、中断处理程序。 <br>这里指的是时间中断。（文献3：system_call.c: timer_interrupt:） <br><br>timer_interrupt: <br>1. push %ds <br>2. push %es <br>3. push %fs <br>4. pushl %edx <br>5. pushl %ecx <br>6. pushl %ebx <br>7. pushl %eax <br>8. movl $0x10,%eax <br>9. mov %ax,%ds <br>10. mov %ax,%es <br>11. movl $0x17,%eax <br>12. mov %ax,%fs <br>13. incl jiffies <br>14. movb $0x20,%al <br>15. outb %al,$0x20 <br>16. movl CS(%esp),%eax <br>17. andl $3,%eax <br>18. pushl %eax <br>19. call do_timer <br>20. andl $4,%esp <br>21. jmp ret_from_sys_call <br><br>1-7行为压栈操作，这是我们所关心的！16-18即是将CPL（CPL=CS&amp;3）压栈，目的是用于do_tiemr(long cpl)函数。那么在执行到do_timer里面时的堆栈怎么样呢？看看： <br><br><br>|返回地址 | <br>----------- <br>| CPL | <br>| eax | <br>| ebx | <br>| ecx | <br>| edx | <br>| fs | <br>| es | <br>| ds | <br>----------- <br>| 外层EIP | <br>| 外层CS | <br>| EFLAG | <br>| 外层ESP | <br>| 外层SS | <br>----------- <br><br>上面的返回地址当然就是调用do_timer后的那条语句，即20行的andl $4,%esp语句。那么是不是do_timer函数执行完就返回到这儿呢，也是，当然要复杂得多，因为在do_timer()函数中调用了schedule()并且发生了任务切换！哎，好麻烦，也不知道什么时候才能返回到这儿来呢，还是一步一步来看吧。 <br><br>三、do_timer()（文献3：sched.c: do_timer()） <br><br>void do_timer(long cpl) <br>{ <br>... <br>if ((--current-&gt;counter)&gt;0) return; <br>current-&gt;counter=0; <br>if(!cpl)return; <br>schedule(); <br>} <br><br>省略号为无关紧要的两条语句，进行进程的计时。如果时间片没有用完(counter&gt;0)或CPL为0，不发生调度直接返回，当然这里也不是就直接返回到以前执行的进程空间，而是返回到do_timer()中，注意开始的返回地址，然后再通过iret指令从中断处理返回到进程中去。当然，根据我们的假设，这儿CPL应该为3，因为是在用户空间发生中断的。我们要从最复杂的情况来讨论这个问题。好了，就让我们进入到中心点吧，请进schedule()。 <br><br>四、schedule()。 （文献3：sched.c: schedule()） <br><br>void schedule(void ) <br>{ <br>int next; <br>... <br>switch_to(next); <br>} <br><br>呵，这里我又省略了几句代码，它执行的是调度算法，即从所有状态为&#8216;运行&#8217;的进程中找出下一个要执行的进程，然后将编号赋给next。进行切换！ <br><br>switch_to()是一个宏，它在（文献3： sched.h）中定义： <br><br>#define switch_to(n) { \ <br>struct (long a,b;} __tmp; \ <br>__asm__("cmpl %%ecx,current \n\t" \ <br>"je 1f\n\t" \ <br>"xchgl %%ecx, current\n\t" \ <br>"movw %%dx, %1\n\t" \ <br>"ljmp *%0\n\t" \ <br>"cmpl %%ecx, %2\n\t" \ <br>"jne 1f\n\t" \ <br>"clts\n" \ <br>"1:" \ <br>::"m" (*&amp;__tmp.a), "m" (*&amp;__tmp.b), \ <br>"m" (last_task_used_math),"d" _TSS(n), "c" ((long) task[n])); \ <br>} <br><br>这是任务切换的关键代码，原理是直接通过TSS来进行任务的切换（文献1：P420）。那我就将这段关键代码逐行解说一下吧。cmpl %%ecx, current，比较任务n是不是当前进程，如果是当然就不用切换了，直接结束schedule()。xchgl %%ecx,current，current指针指向任务n的任务结构，ecx寄存器保存当前进程的任务结构指针。movw %%dx, %1， 使__tmp.b=&#8216;GDT中第n个任务的TSS选择子&#8217;，注意_TSS(n)是求选择子的宏！ljmp *%0，这句代码就是真正的任务切换罗， AT&amp;T语法的ljmp相当于INTEL的jmp far SECTION:OFFSET指令格式，它的绝对地址前加*号。这里引用（文献1：P420）一段话：当段间转移指令JMP所含指针的选择子指示一个可用任务状态段TSS描述符时，正常情况下就发生从当前任务到由该可用任务的切换。目标任务的入口点由目标任务TSS内的CS和EIP字段所规定的指针确定，这样的JMP指令内的偏移被丢弃。再具体的任务切换你也许得翻翻（文献1：P421），这里我只讲有关堆栈的处理，那就是把寄存器现场保存到当前任务的TSS。把通用寄存器、段寄存器、EIP及EFLAGS的当前值保存到当前的TSS中。保存的EIP的值是返回地址，指向引起任务切换指令的下一条指令；恢复目标任务的寄存器现场，根据保存在TSS中的内容恢复各通用寄存器、段寄存器、EFLAG、EIP。好了，基本概念就引用这么多，那么，刚才提到的进程马上要被切换出去了，它保存TSS中EIP是什么呢？显然，根据刚才的分析应该是cmpl %%ecx, %2这条指令。这意味着什么呢？这就是说，如果下次这个任务要被切换成运行状态时，它将从cmpl %%ecx, %2这条指令开始执行！那么，由彼任务推到此任务，也就是说我们切换至任务next时，它也是从这条指令开始执行的！于是我们进入到任务next的堆栈空间，并开始执行，但由于任务next和当前的任务有着相同的堆栈路径（这和LINUX中的内核控制路径是不是一回事呢？），所以我们还是引用当前的堆栈来继续分析。 <br>哦，有点糊涂了，好象是。休息一下，再参考一下（文献2：上册P373）。专家也是这样说的;) <br>要不，我们这么理解，刚才被中断的进程发生了强制调度，且也发生了任务切换，只不过是切换到它自己，实际上不是哟。好吧，JMP成功，开始执行。 <br><br>五、转折点，从schedule()返回。 <br><br>cmpl %%ecx, %2；jne 1f; clts;1: 这几句是与协处理器有关，还有TS标志，我们就直接到1：吧，开始从schedule()返回，注意switch_to()是宏，它在schedule()末端。返回到哪儿去了呢？跟踪一下，看看上面的堆栈示意图，返回地址就是调用do_timer后的那条语句， <br>addl $4, %esp <br>jmp ret_from_sys_call <br>这儿esp加4就是把堆栈中的CPL去掉，因为我们不用了，跳转到ret_from_sys_call。哦，剩下的处理与系统调用返回共用代码。 <br><br>六、ret_from_sys_call （文献3，kernel/system_call.s） <br>先看看我们的焦点，堆栈怎么样了呢？ <br><br>| eax | <br>| ebx | <br>| ecx | <br>| edx | <br>| fs | <br>| es | <br>| ds | <br>----------- <br>| 外层EIP | <br>| 外层CS | <br>| EFLAG | <br>| 外层ESP | <br>| 外层SS | <br>----------- <br><br>ret_from_sys_call: <br>movel current, %eax <br>cmpl task, %eax <br>je 3f <br>movl CS(%esp), %ebx <br>testl $3, %ebx <br>je 3f <br>cmpw $0x17, OLDSS(%esp) <br>jne 3f <br>2: <br>.... <br>3: <br>popl %eax <br>popl %ebx <br>popl %ecx <br>popl %edx <br>pop %fs <br>pop %es <br>pop %ds <br>iret <br><br>2标号处我省略了一些有关信号及其它一些处理。让我们分析一下，如果当前任务是0号进程，或是任务先前的CPL为3（即用户态），或是任务先前的堆栈段为LDT中指定的堆栈，JMP到3标号处。由先前的假设可知，此任务的CPL为3，那就跳吧。把eax, ebc, ecx, edx, fs, es, ds寄存器从堆栈中恢复出来。 <br>现在堆栈如下： <br><br>| 外层EIP | <br>| 外层CS | <br>| EFLAG | <br>| 外层ESP | <br>| 外层SS | <br>----------- <br>记得我们还有最后一条语句哟，iret。这条指令大家想必已经很熟悉了，它恢复EIP、CS、EFLAG、ESP、SS。记得不，这是不是已经恢复到了最初的时间中断时进程被中断的那一刻？恭喜！你终于可以继续做你需要做的事情了！小心，还有下一个时间中断，哦，你不怕？因为它不会影响你的连贯性。 <br><br>结束语： <br>我们走过了一段艰辛的历程，但我们走的是一段近乎直线的路径，并没有分析到其它各个方面的情况。不过我相信，通过这段路程，会让我们对于任务切换机制有一个更深入的认识。希望对大家有所帮助，这也是我写出来与大家分享的缘故。 <br><br>参考文献： <br>1、80X86汇编语言程序设计教程 杨季文编著 清华大学出版社 <br>2、LINUX内核源代码情景分析 毛德操 胡希明著 浙江大学出版社 <br>3、LINUX0.01源代码 <br>4、http://www.linuxforum.net/ LINUX内核分析--&gt;精华篇--&gt;进程调度 <br><br>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/139597.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2011-01-29 22:50 <a href="http://www.cppblog.com/dawnbreak/articles/139597.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ARM寄存器介绍 </title><link>http://www.cppblog.com/dawnbreak/articles/101346.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Wed, 18 Nov 2009 13:55:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/101346.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/101346.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/101346.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/101346.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/101346.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ARM处理器共有37个寄存器。其中包括：31个通用寄存器，包括程序计数器(PC)在内。这些寄存器都是32位寄存器。以及6个32位状态寄存器。但目前只使用了其中12位。ARM处理器共有7种不同的处理器模式，在每一种处理器模式中有一组相应的寄存器组。任意时刻(也就是任意的处理器模式下)，可见的寄存器包括15个通用寄存器(R0～R14)、一个或两个状态寄存器及程序计数器(PC)。在所有的寄存器中，有些是...&nbsp;&nbsp;<a href='http://www.cppblog.com/dawnbreak/articles/101346.html'>阅读全文</a><img src ="http://www.cppblog.com/dawnbreak/aggbug/101346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-11-18 21:55 <a href="http://www.cppblog.com/dawnbreak/articles/101346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 驱动学习日志</title><link>http://www.cppblog.com/dawnbreak/articles/101254.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Tue, 17 Nov 2009 13:53:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/101254.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/101254.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/101254.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/101254.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/101254.html</trackback:ping><description><![CDATA[11月17日<br>/proc/devices 可获知系统注册的设备
<img src ="http://www.cppblog.com/dawnbreak/aggbug/101254.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-11-17 21:53 <a href="http://www.cppblog.com/dawnbreak/articles/101254.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ps -aux 进程状态标识</title><link>http://www.cppblog.com/dawnbreak/articles/101225.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Tue, 17 Nov 2009 10:40:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/101225.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/101225.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/101225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/101225.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/101225.html</trackback:ping><description><![CDATA[<p>PROCESS STATE CODES<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Here are the different values that the s, stat and state output<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; specifiers (header "STAT" or "S") will display to describe the state of<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a process.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D&nbsp;&nbsp;&nbsp; Uninterruptible sleep (usually IO)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R&nbsp;&nbsp;&nbsp; Running or runnable (on run queue)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; S&nbsp;&nbsp;&nbsp; Interruptible sleep (waiting for an event to complete)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T&nbsp;&nbsp;&nbsp; Stopped, either by a job control signal or because it is being<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; traced.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; W&nbsp;&nbsp;&nbsp; paging (not valid since the 2.6.xx kernel)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; X&nbsp;&nbsp;&nbsp; dead (should never be seen)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Z&nbsp;&nbsp;&nbsp; Defunct ("zombie") process, terminated but not reaped by its<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; parent.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For BSD formats and when the stat keyword is used, additional<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; characters may be displayed:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;&nbsp;&nbsp;&nbsp; high-priority (not nice to other users)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; N&nbsp;&nbsp;&nbsp; low-priority (nice to other users)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; L&nbsp;&nbsp;&nbsp; has pages locked into memory (for real-time and custom IO)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s&nbsp;&nbsp;&nbsp; is a session leader<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l&nbsp;&nbsp;&nbsp; is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +&nbsp;&nbsp;&nbsp; is in the foreground process group<br></p>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/101225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-11-17 18:40 <a href="http://www.cppblog.com/dawnbreak/articles/101225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>kmalloc  vmalloc</title><link>http://www.cppblog.com/dawnbreak/articles/101219.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Tue, 17 Nov 2009 09:18:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/101219.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/101219.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/101219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/101219.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/101219.html</trackback:ping><description><![CDATA[<p>在设备驱动程序中动态开辟内存，不是用malloc，而是kmalloc，或者用get_free_pages直接申请页。释放内存用的是kfree，或free_pages.</p>
<p>&nbsp;&nbsp; 对于提供了MMU（存储管理器，辅助操作系统进行内存管理，提供虚实地址转换等硬件支持）的处理器而言，Linux提供了复杂的存储管理系统，使得进程所能访问的内存达到4GB。</p>
<p>　　进程的4GB内存空间被人为的分为两个部分--用户空间与内核空间。用户空间地址分布从0到3GB(PAGE_OFFSET，在0x86中它等于0xC0000000)，3GB到4GB为内核空间。</p>
<p>　　内核空间中，从3G到vmalloc_start这段地址是物理内存映射区域（该区域中包含了内核镜像、物理页框表mem_map等等），比如我们使用的 VMware虚拟系统内存是160M，那么3G～3G+160M这片内存就应该映射物理内存。在物理内存映射区之后，就是vmalloc区域。对于 160M的系统而言，vmalloc_start位置应在3G+160M附近（在物理内存映射区与vmalloc_start期间还存在一个8M的gap 来防止跃界），vmalloc_end的位置接近4G(最后位置系统会保留一片128k大小的区域用于专用页面映射)</p>
<p>　　　　　kmalloc和get_free_page申请的内存位于物理内存映射区域，而且在物理上也是连续的，它们与真实的物理地址只有一个固定的偏移，因此存在较简单的转换关系，virt_to_phys()可以实现内核虚拟地址转化为物理地址：<br>&nbsp;&nbsp; #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)<br>&nbsp;&nbsp; extern inline unsigned long virt_to_phys(volatile void * address)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　return __pa(address);<br>&nbsp;&nbsp; }<br>上面转换过程是将虚拟地址减去3G（PAGE_OFFSET=0XC000000）。</p>
<p>与之对应的函数为phys_to_virt()，将内核物理地址转化为虚拟地址：<br>&nbsp;&nbsp; #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))<br>&nbsp;&nbsp; extern inline void * phys_to_virt(unsigned long address)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　return __va(address);<br>&nbsp;&nbsp; }<br>virt_to_phys()和phys_to_virt()都定义在include\asm-i386\io.h中。</p>
<p>-------------------------------------------------------------------------------------<br>1、kmalloc() 分配连续的物理地址，用于小内存分配。 </p>
<p>　　2、__get_free_page() 分配连续的物理地址，用于整页分配。 </p>
<p>　　至于为什么说以上函数分配的是连续的物理地址和返回的到底是物理地址还是虚拟地址，下面的记录会做出解释。 </p>
<p>　　kmalloc() 函数本身是基于 slab 实现的。slab 是为分配小内存提供的一种高效机制。但 slab 这种分配机制又不是独立的，它本身也是在页分配器的基础上来划分更细粒度的内存供调用者使用。也就是说系统先用页分配器分配以页为最小单位的连续物理地址，然后 kmalloc() 再在这上面根据调用者的需要进行切分。 </p>
<p>　　关于以上论述，我们可以查看 kmalloc() 的实现，kmalloc()函数的实现是在 __do_kmalloc() 中，可以看到在 __do_kmalloc()代码里最终调用了 __cache_alloc() 来分配一个 slab，其实 </p>
<p>　　kmem_cache_alloc() 等函数的实现也是调用了这个函数来分配新的 slab。我们按照 __cache_alloc()函数的调用路径一直跟踪下去会发现在 cache_grow() 函数中使用了 kmem_getpages()函数来分配一个物理页面，kmem_getpages() 函数中调用的alloc_pages_node() 最终是使用 __alloc_pages() 来返回一个struct page 结构，而这个结构正是系统用来描述物理页面的。这样也就证实了上面所说的，slab 是在物理页面基础上实现的。kmalloc() 分配的是物理地址。 </p>
<p>　　__get_free_page() 是页面分配器提供给调用者的最底层的内存分配函数。它分配连续的物理内存。__get_free_page() 函数本身是基于 buddy 实现的。在使用 buddy 实现的物理内存管理中最小分配粒度是以页为单位的。关于以上论述，我们可以查看__get_free_page()的实现，可以看到__get_free_page()函数只是一个非常简单的封状，它的整个函数实现就是无条件的调用 __alloc_pages() 函数来分配物理内存，上面记录 kmalloc()实现时也提到过是在调用 __alloc_pages() 函数来分配物理页面的前提下进行的 slab 管理。那么这个函数是如何分配到物理页面又是在什么区域中进行分配的？回答这个问题只能看下相关的实现。可以看到在 __alloc_pages() 函数中，多次尝试调用get_page_from_freelist() 函数从 zonelist 中取得相关 zone，并从其中返回一个可用的 struct page 页面（这里的有些调用分支是因为标志不同）。至此，可以知道一个物理页面的分配是从 zonelist（一个 zone 的结构数组）中的 zone 返回的。那么 zonelist/zone 是如何与物理页面关联，又是如何初始化的呢？继续来看 free_area_init_nodes() 函数，此函数在系统初始化时由 zone_sizes_init() 函数间接调用的，zone_sizes_init()函数填充了三个区域：ZONE_DMA，ZONE_NORMAL，ZONE_HIGHMEM。并把他们作为参数调用 free_area_init_nodes()，在这个函数中会分配一个 pglist_data 结构，此结构中包含了 zonelist/zone结构和一个 struct page 的物理页结构，在函数最后用此结构作为参数调用了 free_area_init_node() 函数，在这个函数中首先使用 calculate_node_totalpages() 函数标记 pglist_data 相关区域，然后调用 alloc_node_mem_map() 函数初始化 pglist_data结构中的 struct page 物理页。最后使用 free_area_init_core()函数关联 pglist_data 与 zonelist。现在通以上分析已经明确了__get_free_page() 函数分配物理内存的流程。但这里又引出了几个新问题，那就是此函数分配的物理页面是如何映射的？映射到了什么位置？到这里不得不去看下与 VMM 相关的引导代码。 </p>
<p>　　在看 VMM 相关的引导代码前，先来看一下 virt_to_phys() 与phys_to_virt 这两个函数。顾名思义，即是虚拟地址到物理地址和物理地址到虚拟地址的转换。函数实现十分简单，前者调用了__pa( address ) 转换虚拟地址到物理地址，后者调用 __va(addrress ) 将物理地址转换为虚拟地址。再看下 __pa __va 这两个宏到底做了什么。 </p>
<p>　　#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) <br>　　#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) </p>
<p>　　通过上面可以看到仅仅是把地址加上或减去 PAGE_OFFSET，而PAGE_OFFSET 在 x86 下定义为 0xC0000000。这里又引出了疑问，在 linux 下写过 driver 的人都知道，在使用 kmalloc() 与 </p>
<p>　　__get_free_page() 分配完物理地址后，如果想得到正确的物理地址需要使用 virt_to_phys() 进行转换。那么为什么要有这一步呢？我们不分配的不就是物理地址么？怎么分配完成还需要转换？如果返回的是虚拟地址，那么根据如上对 virt_to_phys() 的分析，为什么仅仅对 PAGE_OFFSET 操作就能实现地址转换呢？虚拟地址与物理地址之间的转换不需要查页表么？代着以上诸多疑问来看 VMM 相关的引导代码。 </p>
<p>　　直接从 start_kernel() 内核引导部分来查找 VMM 相关内容。可以看到第一个应该关注的函数是 setup_arch()，在这个函数当中使用paging_init() 函数来初始化和映射硬件页表（在初始化前已有 8M内存被映射，在这里不做记录），而 paging_init() 则是调用的pagetable_init() 来完成内核物理地址的映射以及相关内存的初始化。在 pagetable_init() 函数中，首先是一些 PAE/PSE/PGE 相关判断与设置，然后使用 kernel_physical_mapping_init() 函数来实现内核物理内存的映射。在这个函数中可以很清楚的看到，pgd_idx 是以PAGE_OFFSET 为启始地址进行映射的，也就是说循环初始化所有物理地址是以 PAGE_OFFSET 为起点的。继续观察我们可以看到在 PMD 被初始化后，所有地址计算均是以 PAGE_OFFSET 作为标记来递增的。分析到这里已经很明显的可以看出，物理地址被映射到以 PAGE_OFFSET 开始的虚拟地址空间。这样以上所有疑问就都有了答案。kmalloc() 与__get_free_page() 所分配的物理页面被映射到了 PAGE_OFFSET 开始的虚拟地址，也就是说实际物理地址与虚拟地址有一组一一对应的关系， </p>
<p>　　正是因为有了这种映射关系，对内核以 PAGE_OFFSET 启始的虚拟地址的分配也就是对物理地址的分配（当然这有一定的范围，应该在 PAGE_OFFSET与 VMALLOC_START 之间，后者为 vmalloc() 函数分配内存的启始地址）。这也就解释了为什么 virt_to_phys() 与 phys_to_virt() 函数的实现仅仅是加/减 PAGE_OFFSET 即可在虚拟地址与物理地址之间转换，正是因为了有了这种映射，且固定不变，所以才不用去查页表进行转换。这也同样回答了开始的问题，即 kmalloc() / __get_free_page() 分配的是物理地址，而返回的则是虚拟地址（虽然这听上去有些别扭）。正是因为有了这种映射关系，所以需要将它们的返回地址减去 PAGE_OFFSET 才可以得到真正的物理地址。</p>
<p>另一篇更容易理解的：</p>
<p>kmalloc, vmalloc分配的内存结构 zz<br>2008-01-20 16:05<br>进程空间：| &lt;-用户空间-&gt; | &lt;-内核空间-&gt; |<br>内核空间：| &lt;-物理内存映射区-&gt; | &lt;-vmalloc区域-&gt; |</p>
<p>==============原文================================ </p>
<p>&nbsp;&nbsp; 对于提供了MMU（存储管理器，辅助操作系统进行内存管理，提供虚实地址转换等硬件支持）的处理器而言，Linux提供了复杂的存储管理系统，使得进程所能访问的内存达到4GB。</p>
<p>进程的4GB内存空间被人为的分为两个部分--用户空间与内核空间。用户空间地址分布从0到3GB(PAGE_OFFSET，在0x86中它等于0xC0000000)，3GB到4GB为内核空间。</p>
<p>内核空间中，从3G到vmalloc_start这段地址是物理内存映射区域（该区域中包含了内核镜像、物理页框表mem_map等等），比如我们使用 的 VMware虚拟系统内存是160M，那么3G～3G+160M这片内存就应该映射物理内存。在物理内存映射区之后，就是vmalloc区域。对于 160M的系统而言，vmalloc_start位置应在3G+160M附近（在物理内存映射区与vmalloc_start期间还存在一个8M的gap 来防止跃界），vmalloc_end的位置接近4G(最后位置系统会保留一片128k大小的区域用于专用页面映射)</p>
<p>kmalloc和get_free_page申请的内存位于物理内存映射区域，而且在物理上也是连续的，它们与真实的物理地址只有一个固定的偏移，因此存在较简单的转换关系，virt_to_phys()可以实现内核虚拟地址转化为物理地址：<br>&nbsp;&nbsp; #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)<br>&nbsp;&nbsp; extern inline unsigned long virt_to_phys(volatile void * address)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　return __pa(address);<br>&nbsp;&nbsp; }<br>上面转换过程是将虚拟地址减去3G（PAGE_OFFSET=0XC000000）。</p>
<p>与之对应的函数为phys_to_virt()，将内核物理地址转化为虚拟地址：<br>&nbsp;&nbsp; #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))<br>&nbsp;&nbsp; extern inline void * phys_to_virt(unsigned long address)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　return __va(address);<br>&nbsp;&nbsp; }<br>virt_to_phys()和phys_to_virt()都定义在include\asm-i386\io.h中。</p>
<p>而vmalloc申请的内存则位于vmalloc_start～vmalloc_end之间，与物理地址没有简单的转换关系，虽然在逻辑上它们也是连续的，但是在物理上它们不要求连续。</p>
<p>我们用下面的程序来演示kmalloc、get_free_page和vmalloc的区别：<br>#include &lt;linux/module.h&gt;<br>#include &lt;linux/slab.h&gt;<br>#include &lt;linux/vmalloc.h&gt;<br>MODULE_LICENSE("GPL");<br>unsigned char *pagemem;<br>unsigned char *kmallocmem;<br>unsigned char *vmallocmem;</p>
<p>int __init mem_module_init(void)<br>{<br>//最好每次内存申请都检查申请是否成功<br>//下面这段仅仅作为演示的代码没有检查<br>pagemem = (unsigned char*)get_free_page(0);<br>printk("&lt;1&gt;pagemem addr=%x", pagemem);</p>
<p>kmallocmem = (unsigned char*)kmalloc(100, 0);<br>printk("&lt;1&gt;kmallocmem addr=%x", kmallocmem);</p>
<p>vmallocmem = (unsigned char*)vmalloc(1000000);<br>printk("&lt;1&gt;vmallocmem addr=%x", vmallocmem);</p>
<p>return 0;<br>}</p>
<p>void __exit mem_module_exit(void)<br>{<br>free_page(pagemem);<br>kfree(kmallocmem);<br>vfree(vmallocmem);<br>}</p>
<p>module_init(mem_module_init);<br>module_exit(mem_module_exit);</p>
<p>我们的系统上有160MB的内存空间，运行一次上述程序，发现pagemem的地址在0xc7997000（约3G+121M）、kmallocmem 地址在0xc9bc1380（约3G+155M）、vmallocmem的地址在0xcabeb000（约3G+171M）处，符合前文所述的内存布局。 </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/sandflee/archive/2009/07/28/4388322.aspx">http://blog.csdn.net/sandflee/archive/2009/07/28/4388322.aspx</a></p>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/101219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-11-17 17:18 <a href="http://www.cppblog.com/dawnbreak/articles/101219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows下 POSIX 线程编程</title><link>http://www.cppblog.com/dawnbreak/articles/76946.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Tue, 17 Mar 2009 15:58:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/76946.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/76946.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/76946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/76946.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/76946.html</trackback:ping><description><![CDATA[<h3><strong>1. POSIX 标准</strong></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POSIX是Portable Operating System Interface of Unix的缩写。由IEEE（Institute of Electrical and Electronic Engineering）开发，由ANSI和ISO标准化。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POSIX的诞生和Unix的发展是密不可分的，Unix于70年代诞生于Bell lab，并于80年代向美各大高校分发V7版的源码以做研究。UC Berkeley在V7的基础上开发了BSD Unix。后来很多商业厂家意识到Unix的价值也纷纷以Bell Lab的System V或BSD为基础来开发自己的Unix，较著名的有Sun OS，AIX，VMS。由于各厂家对Unix的开发各自为政，造成了Unix的版本相当混乱，给软件的可移植性带来很大困难，对Unix的发展极为不利。为结束这种局面，IEEE开发了POSIX，POSIX在源代码级别上定义了一组最小的Unix(类Unix)操作系统接口。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POSIX 表示可移植操作系统接口（Portable Operating System Interface ，缩写为 POSIX 是为了读音更像 UNIX）。电气和电子工程师协会（Institute of Electrical and Electronics Engineers，IEEE）最初开发 POSIX 标准，是为了提高 UNIX 环境下应用程序的可移植性。然而，POSIX 并不局限于 UNIX。许多其它的操作系统，例如 DEC OpenVMS 和 Microsoft Windows NT，都支持 POSIX 标准，尤其是 IEEE Std. 1003.1-1990（1995 年修订）或 POSIX.1，POSIX.1 提供了源代码级别的 C 语言应用编程接口（API）给操作系统的服务程序，例如读写文件。POSIX.1 已经被国际标准化组织（International Standards Organization，ISO）所接受，被命名为 ISO/IEC 9945-1:1990 标准。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POSIX 现在已经发展成为一个非常庞大的标准族，某些部分正处在开发过程中。表 1-1 给出了 POSIX 标准的几个重要组成部分。POSIX 与 IEEE 1003 和 2003 家族的标准是可互换的。除 1003.1 之外，1003 和 2003 家族也包括在表中。 </p>
<p><strong>表1：标准的重要组成部分</strong><br>1003.0 <br>管理 POSIX 开放式系统环境（OSE）。IEEE 在 1995 年通过了这项标准。 ISO 的版本是 ISO/IEC 14252:1996。 <br>1003.1 <br>被广泛接受、用于源代码级别的可移植性标准。1003.1 提供一个操作系统的 C 语言应用编程接口（API）。IEEE 和 ISO 已经在 1990 年通过了这个标准，IEEE 在 1995 年重新修订了该标准。 <br>1003.1b <br>一个用于实时编程的标准（以前的 P1003.4 或 POSIX.4）。这个标准在 1993 年被 IEEE 通过，被合并进 ISO/IEC 9945-1。 <br>1003.1c <br>一个用于线程（在一个程序中当前被执行的代码段）的标准。以前是 P1993.4 或 POSIX.4 的一部分，这个标准已经在 1995 年被 IEEE 通过，归入 ISO/IEC 9945-1:1996。 <br>1003.1g <br>一个关于协议独立接口的标准，该接口可以使一个应用程序通过网络与另一个应用程序通讯。 1996 年，IEEE 通过了这个标准。 <br>1003.2 <br>一个应用于 shell 和 工具软件的标准，它们分别是操作系统所必须提供的命令处理器和工具程序。 1992 年 IEEE 通过了这个标准。ISO 也已经通过了这个标准（ISO/IEC 9945-2:1993）。 <br>1003.2d <br>改进的 1003.2 标准。 <br>1003.5 <br>一个相当于 1003.1 的 Ada 语言的 API。在 1992 年，IEEE 通过了这个标准。并在 1997 年对其进行了修订。ISO 也通过了该标准。 <br>1003.5b <br>一个相当于 1003.1b（实时扩展）的 Ada 语言的 API。IEEE 和 ISO 都已经通过了这个标准。ISO 的标准是 ISO/IEC 14519:1999。 <br>1003.5c <br>一个相当于 1003.1q（协议独立接口）的 Ada 语言的 API。在 1998 年， IEEE 通过了这个标准。ISO 也通过了这个标准。 <br>1003.9 <br>一个相当于 1003.1 的 FORTRAN 语言的 API。在 1992 年，IEEE 通过了这个标准，并于 1997 年对其再次确认。ISO 也已经通过了这个标准。 <br>1003.10 <br>一个应用于超级计算应用环境框架（Application Environment Profile，AEP）的标准。在 1995 年，IEEE 通过了这个标准。 <br>1003.13 <br>一个关于应用环境框架的标准，主要针对使用 POSIX 接口的实时应用程序。在 1998 年，IEEE 通过了这个标准。 <br>1003.22 <br>一个针对 POSIX 的关于安全性框架的指南。 <br>1003.23 <br>一个针对用户组织的指南，主要是为了指导用户开发和使用支持操作需求的开放式系统环境（OSE）框架 <br>2003 <br>针对指定和使用是否符合 POSIX 标准的测试方法，有关其定义、一般需求和指导方针的一个标准。在 1997 年，IEEE 通过了这个标准。 <br>2003.1 <br>这个标准规定了针对 1003.1 的 POSIX 测试方法的提供商要提供的一些条件。在 1992 年，IEEE 通过了这个标准。 <br>2003.2 <br>一个定义了被用来检查与 IEEE 1003.2（shell 和 工具 API）是否符合的测试方法的标准。在 1996 年，IEEE 通过了这个标准。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 除了 1003 和 2003 家族以外，还有几个其它的 IEEE 标准，例如 1224 和 1228，它们也提供开发可移植应用程序的 API。要想得到关于 IEEE 标准的最新信息，可以访问 IEEE 标准的主页，网址是 <a href="http://standards.ieee.org/"><u><font color=#0066cc>http://standards.ieee.org/</font></u></a>。有关 POSIX 标准的概述信息，请访问 Web 站点 <a href="http://standards.ieee.org/reading/ieee/stad_public/description/posix/"><u><font color=#0066cc>http://standards.ieee.org/reading/ieee/stad_public/description/posix/</font></u></a>。</p>
<h3><strong>2. Liniux下的线程编程</strong></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Linux系统下的多线程遵循POSIX线程接口，称为pthread。从上面的描述不难知道，<strong>POSIX线程接口是POSIX众多标准中的一个（<a href="http://www.unix-systems.org/version3/ieee_std.html"><u><font color=#0066cc>POSIX 1003.1-2001</font></u></a>）</strong>。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编写Linux下的多线程程序，需要使用头文件pthread.h，连接时需要使用库libpthread.a。顺便说一下，Linux下pthread的实现是通过系统调用 clone() 来实现的。clone() 是Linux所特有的系统调用，它的使用方式类似fork，关于 clone() 的详细情况，有兴趣的读者可以去查看有关文档说明。</p>
<p>下面是一个 POSIX 线程的简单示例程序(thread1.c)： </p>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">pthread.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">unistd.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img id=_95_198_Open_Image onclick="this.style.display='none'; document.getElementById('_95_198_Open_Text').style.display='none'; document.getElementById('_95_198_Closed_Image').style.display='inline'; document.getElementById('_95_198_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056210.gif" align=top><img id=_95_198_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_95_198_Closed_Text').style.display='none'; document.getElementById('_95_198_Open_Image').style.display='inline'; document.getElementById('_95_198_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056233.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">thread_function(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">arg)&nbsp;</span><span id=_95_198_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_95_198_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br><img id=_130_181_Open_Image onclick="this.style.display='none'; document.getElementById('_130_181_Open_Text').style.display='none'; document.getElementById('_130_181_Closed_Image').style.display='inline'; document.getElementById('_130_181_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056227.gif" align=top><img id=_130_181_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_130_181_Closed_Text').style.display='none'; document.getElementById('_130_181_Open_Image').style.display='inline'; document.getElementById('_130_181_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056512.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;</span><span id=_130_181_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_130_181_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Thread&nbsp;says&nbsp;hi! </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;sleep(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056186.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;NULL;<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056497.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img id=_215_472_Open_Image onclick="this.style.display='none'; document.getElementById('_215_472_Open_Text').style.display='none'; document.getElementById('_215_472_Closed_Image').style.display='inline'; document.getElementById('_215_472_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056210.gif" align=top><img id=_215_472_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_215_472_Closed_Text').style.display='none'; document.getElementById('_215_472_Open_Image').style.display='inline'; document.getElementById('_215_472_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056233.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)&nbsp;</span><span id=_215_472_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_215_472_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;pthread_t&nbsp;mythread;<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;<br><img id=_307_362_Open_Image onclick="this.style.display='none'; document.getElementById('_307_362_Open_Text').style.display='none'; document.getElementById('_307_362_Closed_Image').style.display='inline'; document.getElementById('_307_362_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056227.gif" align=top><img id=_307_362_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_307_362_Closed_Text').style.display='none'; document.getElementById('_307_362_Open_Image').style.display='inline'; document.getElementById('_307_362_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056512.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;pthread_create(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">mythread,&nbsp;NULL,&nbsp;thread_function,&nbsp;NULL)&nbsp;)&nbsp;</span><span id=_307_362_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_307_362_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">error&nbsp;creating&nbsp;thread.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;abort();<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056186.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=_405_459_Open_Image onclick="this.style.display='none'; document.getElementById('_405_459_Open_Text').style.display='none'; document.getElementById('_405_459_Closed_Image').style.display='inline'; document.getElementById('_405_459_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056227.gif" align=top><img id=_405_459_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_405_459_Closed_Text').style.display='none'; document.getElementById('_405_459_Open_Image').style.display='inline'; document.getElementById('_405_459_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056512.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;pthread_join&nbsp;(&nbsp;mythread,&nbsp;NULL&nbsp;)&nbsp;)&nbsp;</span><span id=_405_459_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_405_459_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">error&nbsp;joining&nbsp;thread.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;abort();<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056186.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056497.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top></span></div>
</div>
<p>&nbsp;要编译这个程序，只需先将程序存为 thread1.c，然后输入：</p>
<div>$ gcc thread1.c -o thread1 -lpthread</div>
<p>运行则输入：</p>
<div>$ ./thread1</div>
<h3><strong>3. Windows下POSIX线程编程</strong></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Windows本身没有提供对POSIX的支持。但有一个叫 <a href="http://sources.redhat.com/pthreads-win32/"><u><font color=#0066cc>POSIX Threads for Win32</font></u></a> 的开源项目给出了一个功能比较完善的Windows下pthreads API的实现。目前的最新版本是Pthreads-w32 release 2.8.0 (2006-12-22)。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我没有测试过这个最新版本，这里只给出2.7.0版的链接：<a title=ftp://sources.redhat.com/pub/pthreads-win32/pthreads-w32-2-7-0-release.exe href="ftp://sources.redhat.com/pub/pthreads-win32/pthreads-w32-2-7-0-release.exe"><u><font color=#0066cc>ftp://sources.redhat.com/pub/pthreads-win32/pthreads-w32-2-7-0-release.exe</font></u></a>。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关于该开源项目的详细介绍见：<a title=http://sources.redhat.com/pthreads-win32/ href="http://sources.redhat.com/pthreads-win32/"><u><font color=#0066cc>http://sources.redhat.com/pthreads-win32/</font></u></a>。</p>
<h4><strong>3.1 简单使用</strong></h4>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的exe文件是一个自解压文件，解压后，Pre-built.2目录中有编译所需要的头文件（include子目录）和库文件（lib子目录）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个简单的测试程序(main.cpp)：</p>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">pthread.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">assert.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;Function_t(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;Param)<br><img id=_91_214_Open_Image onclick="this.style.display='none'; document.getElementById('_91_214_Open_Text').style.display='none'; document.getElementById('_91_214_Closed_Image').style.display='inline'; document.getElementById('_91_214_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056210.gif" align=top><img id=_91_214_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_91_214_Closed_Text').style.display='none'; document.getElementById('_91_214_Open_Image').style.display='inline'; document.getElementById('_91_214_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056233.gif" align=top></span><span id=_91_214_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_91_214_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">I&nbsp;am&nbsp;a&nbsp;thread!&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_t&nbsp;myid&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;pthread_self();<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">thread&nbsp;ID=%d&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;myid);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;NULL;<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056497.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=_228_596_Open_Image onclick="this.style.display='none'; document.getElementById('_228_596_Open_Text').style.display='none'; document.getElementById('_228_596_Closed_Image').style.display='inline'; document.getElementById('_228_596_Closed_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056210.gif" align=top><img id=_228_596_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_228_596_Closed_Text').style.display='none'; document.getElementById('_228_596_Open_Image').style.display='inline'; document.getElementById('_228_596_Open_Text').style.display='inline';" alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056233.gif" align=top></span><span id=_228_596_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id=_228_596_Open_Text><span style="COLOR: #000000">{<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_t&nbsp;pid;<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_attr_t&nbsp;attr;<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_attr_init(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">attr);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_attr_setscope(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">attr,&nbsp;PTHREAD_SCOPE_PROCESS);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_attr_setdetachstate(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">attr,&nbsp;PTHREAD_CREATE_DETACHED);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_create(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pid,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">attr,&nbsp;Function_t,&nbsp;NULL);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">========================================&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;getchar();<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pthread_attr_destroy(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">attr);<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056264.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056497.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;</span></div>
</div>
<p>使用 cl.exe 编译（不熟悉 cl.exe 的请参考：<a title=http://blog.csdn.net/liuyongjin1984/archive/2008/01/07/2029405.aspx href="http://blog.csdn.net/liuyongjin1984/archive/2008/01/07/2029405.aspx"><u><font color=#800080>http://blog.csdn.net/liuyongjin1984/archive/2008/01/07/2029405.aspx</font></u></a> 或者参见下面3.2部分）：</p>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>》<span style="COLOR: #000000">rem&nbsp;cl.bat<br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>》cl.exe&nbsp;main.cpp &nbsp;</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">c&nbsp; </span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">I</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c:pthreads-w32-2-7-0-releasePre-built.2include</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top><br><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056480.gif" align=top>》link.exe&nbsp; </span><span style="COLOR: #000000">/</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">:main_cl.exe&nbsp; main.obj&nbsp; </span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">LIBPATH:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c:pthreads-w32-2-7-0-releasePre-built.2lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp; pthreadVC2.lib</span></div>
</div>
<p><font size=3>&nbsp;<strong>3.2 使用VC++ 6.0或Visual Studio 2005来运行上面的程序</strong></font></p>
<p>关键有两点：</p>
<p>1. 是将<strong>头文件（include子目录）和库文件（lib子目录）</strong>中的内容添加到VC++ 6.0或Visual Studio 2005开发环境对应的include和lib目录下。</p>
<p>具体来说（<strong>以添加include目录为例，添加lib目录类似</strong>）：</p>
<p><strong>图1：VC++ 6.0（添加include目录：工具--》选项--》目录）</strong></p>
<p><a href="http://p.blog.csdn.net/images/p_blog_csdn_net/liuyongjin1984/WindowsLiveWriter/WindowsPOSIX_14824/1.png"></a><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056899.bmp">&nbsp;</p>
<p>&nbsp;</p>
<p><strong>图2：Visual Studio 2005(添加include目录：tools--》options)</strong></p>
<p><a href="http://p.blog.csdn.net/images/p_blog_csdn_net/liuyongjin1984/WindowsLiveWriter/WindowsPOSIX_14824/2.png"></a><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056941.bmp">&nbsp;</p>
<p>&nbsp;</p>
<p><strong>2. 指定link时要连接的库的名称（pthreadVC2.lib）</strong></p>
<p><strong>图3：VC++ 6.0（工程--》设置--》连接）</strong></p>
<p><strong><a href="http://p.blog.csdn.net/images/p_blog_csdn_net/liuyongjin1984/WindowsLiveWriter/WindowsPOSIX_14824/3.png"></a></strong></p>
<p><strong><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056613.bmp"></strong></p>
<p><strong></strong></p>
<p><strong>图4：Visual Studio 2005(project--&gt;* property pages)</strong></p>
<p><a href="http://p.blog.csdn.net/images/p_blog_csdn_net/liuyongjin1984/WindowsLiveWriter/WindowsPOSIX_14824/4.png"></a><img alt="" src="http://www.newbooks.com.cn/infos/pic/200801/179364/20080109010056694.bmp">&nbsp;</p>
<strong></strong>
<h3>4. 书籍推荐<br><font size=3>&lt;&lt; POSIX Multithread Programming Primer &gt;&gt;:</font> <a href="http://download.csdn.net/source/237125"><u><font color=#0066cc>http://download.csdn.net/source/237125</font></u></a></h3>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/76946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2009-03-17 23:58 <a href="http://www.cppblog.com/dawnbreak/articles/76946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>cygwin 使用</title><link>http://www.cppblog.com/dawnbreak/articles/68393.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Tue, 02 Dec 2008 07:09:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/68393.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/68393.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/68393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/68393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/68393.html</trackback:ping><description><![CDATA[<p>对于经常在Windows编程的使用者，想体验*nix编程可以选择vw，vpc，双系统，而对于真正的开发者而言一个*nix shell加上<span style="COLOR: red">GCC</span> <span style="COLOR: red">GDB</span> <span style="COLOR: red">MAKE</span>以及相关的函数库文件足以，哦，也许加上DEVDOC才算完整，也就是可以使用<span style="COLOR: red">man</span>，所有这些cygwin完全可以搞定。<br>cygwin简介：<br>这个问题你最好google一下"cygwin的历史",或许能够获得更为详尽的答案。简而言之，cygwin是一个在windows平台上运行的 linux模拟环境，是cygnus solutions公司开发的自由软件（该公司开发了很多好东西，著名的还有eCos，不过现已被Redhat收购）。插一句废话，很多朋友不明白 linux和unix的区别和联系，在此也简要介绍一下。UNIX是一个注册商标，是要满足一大堆条件并且支付可观费用才能够被授权使用的一个操作系统; linux是unix的克隆版本，是由其创始人Linus和诸多世界知名的黑客手工打造的一个操作系统。为什么linux和unix之间有很多软件可以很轻松的移植？因为linux也满足POSIX规范,所以在运行机制上跟unix相近。&nbsp;&nbsp; <br>&nbsp;&nbsp; 以下引用网上的一段话（出处：<a href="http://blog.csdn.net/glock18/archive/2004/07/10/38275.aspx"><u><font color=#e6a306>http://blog.csdn.net/glock18/archive/2004/07/10/38275.aspx</font></u></a>），<br>用于说明cygwin的工作机制：cygnus当初首先把gcc，gdb，gas等开发工具进行了改进，使他们能够生成并解释win32的目标文件。然后，他们要把这些工具移植到windows平台上去。一种方案是基于win32 api对这些工具的源代码进行大幅修改，这样做显然需要大量工作。因此，他们采取了一种不同的方法——他们写了一个共享库(就是cygwin dll)，把win32 api中没有的unix风格的调用（如fork,spawn,signals,select,sockets等）封装在里面，也就是说，他们基于 win32 api写了一个unix系统库的模拟层。这样，只要把这些工具的源代码和这个共享库连接到一起，就可以使用unix主机上的交叉编译器来生成可以在 windows平台上运行的工具集。以这些移植到windows平台上的开发工具为基础，cygnus又逐步把其他的工具（几乎不需要对源代码进行修改，只需要修改他们的配置脚本）软件移植到windows上来。这样，在windows平台上运行bash和开发工具、用户工具，感觉好像在unix上工作。关于cygwin实现的更详细描述，请参考<a href="http://cygwin.com/cygwin-ug-net/highlights.html"><u><font color=#e6a306>http://cygwin.com/cygwin-ug-net/highlights.html</font></u></a><br><br>那么接下来就安装：<br>&nbsp;1. 先去Cygwin网站（www.cygwin.com）下载一个安装文件（setup.exe），这个文件体积很小，只有不到300KB。然后双击运行setup.exe。因为是第一次安装，所以必须选择从Internet在线安装，也可以先从Internet下载安装文件，然后再手动安装。我选择后者，因为这样，以后我可以在不联网的时候也能安装。</p>
<p>2. 接下来点击&#8220;下一步&#8221;，然后从一系列服务器列表中选择一个你认为网速最快的一个作为下载服务器。接着点击&#8220;下一步&#8221;就会出现如下图所示的界面，用来选择你想安装的程序。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 如果你不做任何修改，将默认安装Cygwin运行所需的最少的程序和组件。不过，gcc编译器不在默认安装程序之列，所以你必须选择安装gcc。具体是， 在上述窗口中的列表中展开Devel目录，找到gcc-g++一项，点击&#8220;Default&#8221;，它就变成了&#8220;Install&#8221;，同时由于程序之间的依赖性 gcc-core条目的&#8220;Default&#8221;，也变成了&#8220;Install&#8221;。</p>
<p>&nbsp;&nbsp;&nbsp; 此外，为了使gcc能正确编译源文件，还必须安装win32api库，否则会编译出错。因此，你需要在上述窗口中展开Libs目录，找到win32api一项，将它点成&#8220;Install&#8221;。</p>
3. 接下来就是耐心等待程序去下载所需的安装文件了。一旦下载完毕，你再次运行setup.exe，先选择你将要把Cygwin安装在什么地方，然后再选择你 刚才所下载的那些安装文件所在的硬盘位置。接着你还需要再次选择安装gcc和win32api。这样，你就可以开始安装了。
<p>4. 安装完成后，运行Cygwin。在窗口中敲入gcc就可以直接用gcc来编译了。编译链接生成的可执行文件，系统会自动加上.exe后缀，在Cygwin 环境中可以直接运行。但如果脱离Cygwin环境，而在MS DOS下运行，则会出错。解决办法很简单，那就是将cygwin1.dll文件拷贝到C:\WINDOWS目录下即可。<br><br><span style="COLOR: red">在这里我想强调，如果图省事，完全可以直接将all右边的default设为install。但是这将这样你4个G的空间，所以如果你不是拥有特别大的空间的话，还是建议选择性的安装，需要什么可以随时点击先前的setup.exe加装新的组件除去以上所说的组件外，在devel下的GDB和make相信也是大多数开发者所必须的。<br></span>至此已将解决的了文章开头提及的前三项要件，而第四项man则是cygwin默认安装的，不过不是很全面，所以可以通过<a href="http://tldp.org/manpages/man.php"><u><font style="COLOR: #3366ff" color=#ffffff>The Linux Documentation Project </font></u></a>（很好很强大的文档网站）来解决，不过貌似这个网站大陆打不开，反正我是没打开，还好有香港同胞建立的mirror，比较好用的是<a href="ftp://ftp.hkmirror.org/pub/ldp/manpages/">ftp://ftp.hkmirror.org/pub/ldp/manpages/</a>，在其中找到适合你的man版本，下载，解压到$(cygwin)目录下的/usr/share/man/下面，编辑/usr/share/misc/man.conf，文件末尾加上MANPATH&nbsp;/usr/share/man/man-pages-*.**即可。<br><br>好啦，如下配置后，启动cygwin，来编一个小程序helloworld热热身<br>随便选一个目录建立helloworld.cc文件，记事本打开，写入以下代码：<br>#include "stdio.h"<br>int<br>main(int args,char* argv[])<br>{<br>&nbsp;printf("helloworld");<br>&nbsp;return 0;<br>}<br>保存，启动cygwin cd到helloworld.cc文件目录，执行<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;gcc&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">o&nbsp;helloworld&nbsp;helloworld.cc</span></div>
然后执行<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;.</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">helloworld</span></div>
得到结果<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">helloworld</span></div>
<br><span style="COLOR: #0000ff">Appendix<br><br>pwd&nbsp;&nbsp; 显示当前的路径<br>cd&nbsp;&nbsp;&nbsp; 改变当前路径，无参数时进入对应用户的home目录<br>ls&nbsp;&nbsp;&nbsp; 列出当前目录下的文件。此命令有N多参数，比如ls -al<br>ps&nbsp;&nbsp;&nbsp; 列出当前系统进程<br>kill&nbsp; 杀死某个进程<br>mkdir 建立目录<br>rmdir 删除目录<br>rm&nbsp;&nbsp;&nbsp; 删除文件<br>mv&nbsp;&nbsp;&nbsp; 文件改名或目录改名<br>man&nbsp;&nbsp; 联机帮助<br>less&nbsp; 显示文件的最末几行<br>df&nbsp;&nbsp;&nbsp; 显示文件系统<br></span>
<img src ="http://www.cppblog.com/dawnbreak/aggbug/68393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2008-12-02 15:09 <a href="http://www.cppblog.com/dawnbreak/articles/68393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 中的一些快捷键</title><link>http://www.cppblog.com/dawnbreak/articles/68119.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Fri, 28 Nov 2008 17:21:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/68119.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/68119.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/68119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/68119.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/68119.html</trackback:ping><description><![CDATA[载终端中，复制为ctrl-shift-c，黏贴为ctrl-shift-v<br>而在ubuntu中定义两者可以有鼠标中键完成<br>其他终端快捷键<br>终端快捷键<br>
tab=补全<br>
ctrl+a=开始位置<br>
ctrl+e=最后位置<br>
ctrl+k=删除此处至末尾所有内容<br>
ctrl+u=删除此处至开始所有内容<br>常用<br>
win+n切换背景颜色风格<br>
alt+tab=不用说了。<br>
win+tab若开3D效果了切换<br>
ctrl+alt+backspace=相当于强制注销<br>
ctrl+alt+del=调出关机菜单<br>
ctrl+alt+l=锁定桌面<br>
<br>
ctrl+alt+d=最小化gnome所有窗口<br>
ctrl+alt+f2=linux<span href="http://www.linuxdiyf.com/bbs/tag.php?name=%D6%D5%B6%CB" onclick="tagshow(event)" class="t_tag">终端</span>用户（alt + f7返回x<span href="http://www.linuxdiyf.com/bbs/tag.php?name=windows" onclick="tagshow(event)" class="t_tag">windows</span>，alt+ &lt;- 或-&gt; 进行<span href="http://www.linuxdiyf.com/bbs/tag.php?name=%D6%D5%B6%CB" onclick="tagshow(event)" class="t_tag">终端</span>切换）<br>
ctrl+alt+ &lt;- 或-&gt; =切换桌面<br><br><img src ="http://www.cppblog.com/dawnbreak/aggbug/68119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2008-11-29 01:21 <a href="http://www.cppblog.com/dawnbreak/articles/68119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> ubuntu解压命令全览</title><link>http://www.cppblog.com/dawnbreak/articles/68118.html</link><dc:creator>pear_li</dc:creator><author>pear_li</author><pubDate>Fri, 28 Nov 2008 17:11:00 GMT</pubDate><guid>http://www.cppblog.com/dawnbreak/articles/68118.html</guid><wfw:comment>http://www.cppblog.com/dawnbreak/comments/68118.html</wfw:comment><comments>http://www.cppblog.com/dawnbreak/articles/68118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dawnbreak/comments/commentRss/68118.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dawnbreak/services/trackbacks/68118.html</trackback:ping><description><![CDATA[<div id="blog_text" class="cnt">
<div class="cnt">
<h1>&nbsp;<a  href="http://blog.csdn.net/lg_Mp5/archive/2006/12/14/1443280.aspx">ubuntu下使用rar</a><cite class="fav_csdnstylebykimi"></cite></h1>
<p>1  用ubuntu自带的新立得软件包安装ark软件，搜索ark，然后选中就行了，会自动安装附带的10多个库文件。</p>
<p>2 安装完ark，会在菜单的附件中找到，你会发现ark其实已经设计成为支持rar，因为在新建打开等操作中都可以选择rar格式，不过只是写了出来，不是真正的支持。接下来主角要登场了。</p>
<p>3 到这里<a  href="http://www.rarlab.com/download.htm">RARLAB</a>，你可以下载rar for linux的文件，当然不是用rar格式压缩的，用默认打开的归档管理器解压缩，将其中的文件找一个路径存放。</p>
<p>4&nbsp; 将刚才解压缩的rar for linux的文件中的四个可执行文件：default.sfx，rar，rar_static， unrar，复制到 /usr/local/bin 目录下。你可能需要管理员帐号。如果在终端下操作，可以简单的sudo mv一下。</p>
<br><strong><font size="2"><font color="#0000ff"><br>.tar</font></font></strong><br>
解包：tar xvf FileName.tar<br>
打包：tar cvf FileName.tar DirName<br>
<font color="#008000">（注：tar是打包，不是压缩！）</font><br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.gz</font></font></strong><br>
解压1：gunzip FileName.gz<br>
解压2：gzip -d FileName.gz<br>
压缩：gzip FileName<br>
<strong><font size="2"><font color="#0000ff">.tar.gz 和 .tgz</font></font></strong><br>
解压：tar zxvf FileName.tar.gz<br>
压缩：tar zcvf FileName.tar.gz DirName<br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.bz2</font></font></strong><br>
解压1：bzip2 -d FileName.bz2<br>
解压2：bunzip2 FileName.bz2<br>
压缩： bzip2 -z FileName<br>
<strong><font size="2"><font color="#0000ff">.tar.bz2</font></font></strong><br>
解压：tar jxvf FileName.tar.bz2<br>
压缩：tar jcvf FileName.tar.bz2 DirName<br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.bz</font></font></strong><br>
解压1：bzip2 -d FileName.bz<br>
解压2：bunzip2 FileName.bz<br>
压缩：<font color="#ffa500">未知</font><br>
<strong><font size="2"><font color="#0000ff">.tar.bz</font></font></strong><br>
解压：tar jxvf FileName.tar.bz<br>
压缩：<font color="#ffa500">未知</font><br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.Z</font></font></strong><br>
解压：uncompress FileName.Z<br>
压缩：compress FileName<br>
<strong><font size="2"><font color="#0000ff">.tar.Z</font></font></strong><br>
解压：tar Zxvf FileName.tar.Z<br>
压缩：tar Zcvf FileName.tar.Z DirName<br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.zip</font></font></strong><br>
解压：unzip FileName.zip<br>
压缩：zip FileName.zip DirName<br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.rar</font></font></strong><br>
解压：rar x FileName.rar<br>
压缩：rar a FileName.rar DirName<br>
<font color="#008000"><br>
rar请到：<a href="http://www.rarsoft.com/download.htm" style="color: #003793;" target="_blank"><font color="#003793">http://www.rarsoft.com/download.htm</font></a> 下载！<br>
解压后请将rar_static拷贝到/usr/bin目录（其他由$PATH环境变量指定的目录也可以）：<br>
[root@www2 tmp]# cp rar_static /usr/bin/rar</font><br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.lha</font></font></strong><br>
解压：lha -e FileName.lha<br>
压缩：lha -a FileName.lha FileName<br>
<font color="#008000"><br>
lha请到：<a href="http://www.infor.kanazawa-it.ac.jp/%7Eishii/lhaunix/" style="color: #003793;" target="_blank"><font color="#003793">http://www.infor.kanazawa-it.ac.jp/~ishii/lhaunix/</font></a>下载！<br>
&gt;解压后请将lha拷贝到/usr/bin目录（其他由$PATH环境变量指定的目录也可以）：<br>
[root@www2 tmp]# cp lha /usr/bin/</font><br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.rpm</font></font></strong><br>
解包：rpm2cpio FileName.rpm | cpio -div<br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.deb</font></font></strong><br>
解包：ar p FileName.deb data.tar.gz | tar zxf -<br>
---------------------------------------------<br>
<strong><font size="2"><font color="#0000ff">.tar .tgz .tar.gz .tar.Z
.tar.bz .tar.bz2 .zip .cpio .rpm .deb .slp .arj .rar .ace .lha .lzh
.lzx .lzs .arc .sda .sfx .lnx .zoo .cab .kar .cpt .pit .sit .sea</font></font></strong><br>
解压：sEx x FileName.*<br>
压缩：sEx a FileName.* FileName<br>
<font color="#008000"><br>
sEx只是调用相关程序，本身并无压缩、解压功能，请注意！<br>
sEx请到： <a href="http://sourceforge.net/projects/sex" style="color: #003793;" target="_blank"><font color="#003793">http://sourceforge.net/projects/sex</font></a>下载！<br>
解压后请将sEx拷贝到/usr/bin目录（其他由$PATH环境变量指定的目录也可以）：<br>
[root@www2 tmp]# cp sEx /usr/bin/</font></div>
</div><img src ="http://www.cppblog.com/dawnbreak/aggbug/68118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dawnbreak/" target="_blank">pear_li</a> 2008-11-29 01:11 <a href="http://www.cppblog.com/dawnbreak/articles/68118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>