??xml version="1.0" encoding="utf-8" standalone="yes"?>99久久精品国产高清一区二区,久久亚洲精品国产精品婷婷,日韩人妻无码精品久久免费一http://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203451.htmlhoshellyhoshellyFri, 27 Sep 2013 01:13:00 GMThttp://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203451.htmlhttp://www.shnenglu.com/zhenglinbo/comments/203451.htmlhttp://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203451.html#Feedback0http://www.shnenglu.com/zhenglinbo/comments/commentRss/203451.htmlhttp://www.shnenglu.com/zhenglinbo/services/trackbacks/203451.html摘抄自:http://www.cnblogs.com/vamei 

当程序文件运行ؓq程的时候,q程在内存中得到I间(q程自己的小戉K)。每个进E空间按照如下方式分Z同区?

                    内存I间

Text区域用来储存指o(instruction)Q来告诉E序每一步的操作。Global Data用于存放全局变量Qstack用于存放局部变量,heap用于存放动态变?(dynamic variable. E序利用mallocpȝ调用Q直接从内存中ؓdynamic variable开辟空??span style="margin: 0px; padding: 0px; color: #ff0000;">Text?span style="margin: 0px; padding: 0px; color: #ff0000;">Global data在进E一开始的时候就定了,q在整个q程中保?span style="margin: 0px; padding: 0px; color: #ff0000;">固定大小?/span>

 

Stack(?span style="margin: 0px; padding: 0px; color: #000000;">)?span style="margin: 0px; padding: 0px; color: #ff0000;">stack frame为单位。当E序调用函数的时候,比如main()函数中调用inner()函数Qstack会向下增长一个stack frame。Stack frame中存储该函数?span style="margin: 0px; padding: 0px; color: #ff0000;">参数?span style="margin: 0px; padding: 0px; color: #ff0000;">局部变?/span>Q以及该函数?span style="margin: 0px; padding: 0px; color: #ff0000;">q回地址(return address)。此Ӟ计算机将控制权从main()转移到inner()Qinner()函数处于Ȁz?/span>(active)状态。位于Stack最下方的frame和Global Data构成了当前的环?context)。激zd数可以从中调用需要的变量。典型的~程语言都只允许你用位于stack最下方的frame Q而不允许你调用其它的frame (q也W合stackl构“先进后出”的特征。但也有一些语a允许你调用stack的其它部分,相当于允怽在运行inner()函数的时候调用main()中声明的局部变量,比如Pascal)。当函数又进一步调用另一个函数的时候,一个新的frame会l增加到stack下方Q控制权转移到新的函C。当Ȁzd?span style="margin: 0px; padding: 0px; color: #ff0000;">q回的时候,会从stack?span style="margin: 0px; padding: 0px; color: #ff0000;">弹出(popQ就是读取ƈ删除)该frameQƈҎframe中记录的q回地址Q将控制权交l返回地址所指向的指?/span>(比如从inner()函数中返回,l箋执行main()中赋值给main2的操??/span>

下图是stack在运行过E中的变化,头表示stack增长的方向,每个方块代表一个stack frame。开始的时候我们有一个ؓmain()服务的frameQ随着调用inner()Q我们ؓinner()增加一个frame。在inner()q回Ӟ我们再次只有main()的frameQ直到最后main()q回Q其q回地址为空Q所以进E结束?br />


                                                          stack变化


在进E运行的q程中,通过调用和返回函敎ͼ控制?/span>不断在函数间转移。进E可以在调用函数的时候,原函数的stack frame中保存有在我们离开时的状态,qؓ新的函数开辟所需的stack frameI间。在调用函数q回Ӟ该函数的stack frame所占据的空间随着stack frame的弹清I。进E再ơ回到原函数的stack frame中保存的状态,q根据返回地址所指向的指令l执行。上面过E不断l,stack不断增长或减,直到main()q回的时候,stack完全清空Q进E结束?/span>

 

 当程序中使用malloc的时候,heap(?span style="margin: 0px; padding: 0px; color: #000000;">)?/span>向上增长Q其增长的部分就成ؓmalloc从内存中分配的空间。malloc开辟的I间会一直存在,直到我们用freepȝ调用来释放,或者进E结束。一个经典的错误?span style="margin: 0px; padding: 0px; color: #ff0000;">内存泄漏(memory leakage), 是指我们没有释放不再用的heapI间Q导致heap不断增长Q而内存可用空间不断减?/span>

׃stack和heap的大则会随着q程的运行增大或者变,当stack和heap增长C者相遇时候,也就是内存空间图中的蓝色区域(unused area)完全消失的时候,q程会出?span style="margin: 0px; padding: 0px; color: #ff0000;">栈溢?/span>(stack overflow)的错误,Dq程l止。在C计算ZQ内怸般都会ؓq程分配_多的蓝色区域Q如果我们即时清理的话,stack overflow是可以避免的。但是,在进行一些矩阵运的时候,׃所需的内存很大,依然可能出现stack overflow的情c一U解x式是增大内核分配l每个进E的内存I间。如果依然不能解决问题的话,我们需要增加物理内存?br />


堆和栈的区别Q?br />

2.1甌方式    
  stack:    
  ql自动分配?nbsp;  例如Q声明在函数中一个局部变?nbsp;  int   b;   pȝ自动在栈中ؓb开辟空  
  ?nbsp;   
  heap:    
  需要程序员自己甌Qƈ指明大小Q在c中malloc函数    
  如p1   =   (char   *)malloc(10);    
  在C++中用newq算W?nbsp;   
  如p2   =   new   char[10];    
  但是注意p1、p2本n是在栈中的?nbsp;   
   
   
  2.2    
  甌后系l的响应    
  栈:只要栈的剩余I间大于所甌I间Q系l将为程序提供内存,否则报异常提示栈溢  
  出?nbsp;   
  堆:首先应该知道操作pȝ有一个记录空闲内存地址的链表,当系l收到程序的甌Ӟ  
  会遍历该链表Q寻扄一个空间大于所甌I间的堆l点Q然后将该结点从I闲l点链表  
  中删除,q将该结点的I间分配l程序,另外Q对于大多数pȝQ会在这块内存空间中?nbsp; 
  首地址处记录本ơ分配的大小Q这P代码中的delete语句才能正确的释放本内存I间?nbsp; 
  另外Q由于找到的堆结点的大小不一定正好等于申L大小Q系l会自动的将多余的那?nbsp; 
  分重新放入空闲链表中?nbsp;   
   
  2.3甌大小的限?nbsp;   
  栈:在Windows?栈是向低地址扩展的数据结构,是一块连l的内存的区域。这句话的意  
  思是栈顶的地址和栈的最大容量是pȝ预先规定好的Q在WINDOWS下,栈的大小?MQ也?nbsp; 
  的说?MQM是一个编译时q定的常数Q,如果甌的空间超q栈的剩余空间时Q将  
  提示overflow。因此,能从栈获得的I间较小?nbsp;   
  堆:堆是向高地址扩展的数据结构,是不q箋的内存区域。这是由于系l是用链表来存储  
  的空闲内存地址的,自然是不q箋的,而链表的遍历方向是由低地址向高地址。堆的大?nbsp; 
  受限于计机pȝ中有效的虚拟内存。由此可见,堆获得的I间比较灉|Q也比较大?nbsp;   
   
   
   
  2.4甌效率的比较:    
  栈由pȝ自动分配Q速度较快。但E序员是无法控制的?nbsp;   
  堆是由new分配的内存,一般速度比较慢,而且Ҏ产生内存片,不过用v来最方便.    
  另外Q在WINDOWS下,最好的方式是用VirtualAlloc分配内存Q他不是在堆Q也不是在栈?nbsp; 
  直接在进E的地址I间中保留一块内存,虽然用v来最不方ѝ但是速度快,也最灉|?nbsp; 
     
   
  2.5堆和栈中的存储内?nbsp;   
  栈:   在函数调用时Q第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可  
  执行语句Q的地址Q然后是函数的各个参敎ͼ在大多数的C~译器中Q参数是由右往左入?nbsp; 
  的,然后是函C的局部变量。注意静态变量是不入栈的?nbsp;   
  当本ơ函数调用结束后Q局部变量先出栈Q然后是参数Q最后栈指针指向最开始存的地  
  址Q也是dC的下一条指令,E序p点l运行?nbsp;   
  堆:一般是在堆的头部用一个字节存攑֠的大。堆中的具体内容q序员安排?nbsp;   
   
  2.6存取效率的比?nbsp;   
   
  char   s1[]   =   "aaaaaaaaaaaaaaa";    
  char   *s2   =   "bbbbbbbbbbbbbbbbb";    
  aaaaaaaaaaa是在q行时刻赋值的Q?nbsp;   
  而bbbbbbbbbbb是在~译时就定的;    
  但是Q在以后的存取中Q在栈上的数l比指针所指向的字W串(例如?快?  

  2.7结Q?nbsp;   
  堆和栈的区别可以用如下的比喻来看出:    
  使用栈就象我们去饭馆里吃饭,只管点菜Q发出申P、付钱、和吃(使用Q,吃饱了就  
  赎ͼ不必理会切菜、洗菜等准备工作和洗、刷锅等扫尾工作Q他的好处是快捷Q但是自  
  由度?nbsp;   
  使用堆就象是自己动手做喜Ƣ吃的菜_比较ȝQ但是比较符合自q口味Q而且自由  
  度大?nbsp;  (l典Q?  


hoshelly 2013-09-27 09:13 发表评论
]]>
Java对象引用Q{Q?/title><link>http://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203450.html</link><dc:creator>hoshelly</dc:creator><author>hoshelly</author><pubDate>Fri, 27 Sep 2013 00:39:00 GMT</pubDate><guid>http://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203450.html</guid><wfw:comment>http://www.shnenglu.com/zhenglinbo/comments/203450.html</wfw:comment><comments>http://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhenglinbo/comments/commentRss/203450.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhenglinbo/services/trackbacks/203450.html</trackback:ping><description><![CDATA[<div><span style="font-size: 12px;">作者:Vamei 出处Qhttp://www.cnblogs.com/vamei Ƣ迎转蝲Q也请保留这D声明。谢谢!</span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">我们之前一直在使用“对象”q个概念Q但没有探讨对象在内存中的具体存储方式。这斚w的讨论将引出“对象引用”(object reference)q一重要概念?nbsp;</span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">对象引用</span></div><div><span style="font-size: 12px;">我们沿用之前定义的Humanc,q有一个Testc?</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">复制代码</span></div><div><span style="font-size: 12px;">public class Test</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">    public static void main(String[] args)</span></div><div><span style="font-size: 12px;">    {</span></div><div><span style="font-size: 12px;">        Human aPerson = new Human(160);                 </span></div><div><span style="font-size: 12px;">    }</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">class Human</span></div><div><span style="font-size: 12px;">{   </span></div><div><span style="font-size: 12px;">    /**</span></div><div><span style="font-size: 12px;">     * constructor</span></div><div><span style="font-size: 12px;">     */</span></div><div><span style="font-size: 12px;">    public Human(int h)</span></div><div><span style="font-size: 12px;">    {</span></div><div><span style="font-size: 12px;">        this.height = h;</span></div><div><span style="font-size: 12px;">    }</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">    /**</span></div><div><span style="font-size: 12px;">     * accessor</span></div><div><span style="font-size: 12px;">     */</span></div><div><span style="font-size: 12px;">    public int getHeight()</span></div><div><span style="font-size: 12px;">    {</span></div><div><span style="font-size: 12px;">       return this.height;</span></div><div><span style="font-size: 12px;">    }</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">    /**</span></div><div><span style="font-size: 12px;">     * mutator</span></div><div><span style="font-size: 12px;">     */</span></div><div><span style="font-size: 12px;">    public void growHeight(int h)</span></div><div><span style="font-size: 12px;">    {</span></div><div><span style="font-size: 12px;">        this.height = this.height + h;</span></div><div><span style="font-size: 12px;">    }</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">    private int height;</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;">复制代码</span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">外部可以调用cL创徏对象Q比如上面在TestcM:</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">Human aPerson = new Human(160);</span></div><div><span style="font-size: 12px;">创徏了一个Humancȝ对象aPerson?nbsp;</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">上面是一个非常简单的表述Q但我们有许多细节需要深?</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">首先看等L右侧。new是在内存中ؓ对象开辟空间。具体来_new是在内存的堆(heap)上ؓ对象开辟空间。这一I间中,保存有对象的数据和方法?/span></div><div><span style="font-size: 12px;">再看{号的左侧。aPerson指代一个Human对象Q被UCؓ对象引用(reference)。实际上QaPersonq不是对象本w,而是cM于一个指向对象的指针。aPerson存在于内存的?stack)中?/span></div><div><span style="font-size: 12px;">当我们用{号赋值时Q是右侧new在堆中创建对象的地址赋予l对象引用?/span></div><div><span style="font-size: 12px;">q里的内存,指的是JVM (Java Virtual Machine)虚拟出来的Javaq程内存I间。内存的堆和栈概念可参考Linux从程序到q程?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> <img src="http://www.shnenglu.com/images/cppblog_com/zhenglinbo/31232316-9ceb14006ae34b97b3fbefaafccc9f80.png" border="0" alt="" width="211" height="274" /></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">对象引用</span></div><div><span style="font-size: 12px;"><br /></span></div><div></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">栈的d速度比堆快,但栈上存储的数据受到有效范围的限制。在C语言中,当一ơ函数调用结束时Q相应的栈(stack frame)要删除,栈上存储的参量和自动变量就消失了。Java的栈也受到同L限制Q当一ơ方法调用结束,该方法存储在栈上的数据将清空。在 Java中,所有的(普?对象都储存在堆上。因此,new关键字的完整含义是,在堆上创建对象?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">基本cd(primitive type)的对象,比如int, doubleQ保存在栈上。当我们声明基本cdӞ不需要new。一旦声明,Java在栈上直接存储基本cd的数据。所以,基本cd的变量名表示的是数据本nQ不是引用?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">引用和对象的关系像风筝和h。我们看天空?E序里写?Q看到的是风{?引用)Q但风筝下面对应的,是h(对象):</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;"><img src="http://www.shnenglu.com/images/cppblog_com/zhenglinbo/2.jpg" border="0" alt="" width="600" height="776" /><br /></span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">引用和对象分;引用指向对象</span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">管引用和对象是分离的,但我们所有通往对象的访问必ȝq引用这?#8220;大门”Q比如以 引用.Ҏ() 的方式访问对象的Ҏ。在Java中,我们不能跌引用ȝ接接触对象。再比如Q对象a的数据成员如果是一个普通对象bQa的数据成员保存的是指向对象b的引?(如果是基本类型变量,那么a的数据成员保存的是基本类型变量本w了)?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">在Java中,引用起到了指针的作用Q但我们不能直接修改指针的|比如像C语言那样指针值加1。我们只能通过引用执行对对象的操作。这L设计避免了许多指针可能引L错误?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">引用的赋?/span></div><div><span style="font-size: 12px;">当我们将一个引用赋值给另一个引用时Q我们实际上复制的是对象的地址。两个引用将指向同一对象。比?dummyPerson=aPerson;Q将D:</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;"><img src="http://www.shnenglu.com/images/cppblog_com/zhenglinbo/3.png" border="0" alt="" width="279" height="318" /><br /></span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">一个对象可以有多个引用 (一个h可以攑֤个风{?。当E序通过某个引用修改对象Ӟ通过其他引用也可以看到该修改。我们可以用以下TestcL试实际效果:</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">复制代码</span></div><div><span style="font-size: 12px;">public class Test</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">    public static void main(String[] args)</span></div><div><span style="font-size: 12px;">        {</span></div><div><span style="font-size: 12px;">             Human aPerson = new Human(160);</span></div><div><span style="font-size: 12px;">             Human dummyPerson = aPerson;</span></div><div><span style="font-size: 12px;">             System.out.println(dummyPerson.getHeight());</span></div><div><span style="font-size: 12px;">             aPerson.growHeight(20);</span></div><div><span style="font-size: 12px;">             System.out.println(dummyPerson.getHeight());</span></div><div><span style="font-size: 12px;">        }</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;">复制代码</span></div><div><span style="font-size: 12px;">我们对aPerson的修改将影响到dummyPerson。这两个引用实际上指向同一对象?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">所以,一个引用赋值给另一个引用,q不能复制对象本w。我们必d求其他的机制来复制对象?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">垃圾回收</span></div><div><span style="font-size: 12px;">随着Ҏ调用的结束,引用和基本类型变量会被清I。由于对象存zM堆,所以对象所占据的内存不会随着Ҏ调用的结束而清I。进E空间可能很快被不断创徏的对象占满。Java内徏有垃圑֛?garbage collection)机制Q用于清IZ再用的对象Q以回收内存I间?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">垃圾回收的基本原则是Q当存在引用指向某个对象Ӟ那么该对象不会被回收; 当没有Q何引用指向某个对象时Q该对象被清I。它所占据的空间被回收?/span></div><div><span style="font-size: 12px;"><img src="http://www.shnenglu.com/images/cppblog_com/zhenglinbo/4.png" border="0" alt="" width="307" height="464" /><br /></span></div><div><span style="font-size: 12px;">上图假设了某个时刻JVM中的内存状态。Human Object有三个引? 来自栈的aPerson和dummyPersonQ以及另一个对象的数据成员president。而Club Object没有引用。如果这个时候垃圑֛收启动,那么Club Object被清空Q而Human Object来自Club Object的引?president)也随之被删除?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">垃圾回收是Java中重要的机制Q它直接影响了Java的运行效率。我在以后深入其细节?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">参数传?br /><br /></span></div><div><span style="font-size: 12px;">当我们分M引用和对象的概念后,JavaҎ的参C递机制实际上非常清晰: Java的参C递ؓg递。也是_当我们传递一个参数时Q方法将获得该参数的一个拷贝?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">实际上,我们传递的参数Q一个是基本cd的变量,另一个ؓ对象的引用?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">基本cd变量的g递,意味着变量本n被复Ӟq传递给JavaҎ。JavaҎ对变量的修改不会影响到原变量?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">引用的g递,意味着对象的地址被复Ӟq传递给JavaҎ。JavaҎҎ该引用的讉K会影响对象?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">在这里有另一个值得一提的情况: 我们在方法内部用new创徏对象Qƈ该对象的引用返回。如果该q回被一个引用接Ӟ׃对象的引用不?Q对象依然存在,不会被垃圑֛收?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">ȝ</span></div><div><span style="font-size: 12px;">new</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">引用Q对?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">被垃圑֛收的条g</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">参数: g?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><img src ="http://www.shnenglu.com/zhenglinbo/aggbug/203450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhenglinbo/" target="_blank">hoshelly</a> 2013-09-27 08:39 <a href="http://www.shnenglu.com/zhenglinbo/archive/2013/09/27/203450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java socket~程入门Q{Q?/title><link>http://www.shnenglu.com/zhenglinbo/archive/2013/07/05/201533.html</link><dc:creator>hoshelly</dc:creator><author>hoshelly</author><pubDate>Fri, 05 Jul 2013 07:55:00 GMT</pubDate><guid>http://www.shnenglu.com/zhenglinbo/archive/2013/07/05/201533.html</guid><wfw:comment>http://www.shnenglu.com/zhenglinbo/comments/201533.html</wfw:comment><comments>http://www.shnenglu.com/zhenglinbo/archive/2013/07/05/201533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhenglinbo/comments/commentRss/201533.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhenglinbo/services/trackbacks/201533.html</trackback:ping><description><![CDATA[q个|站上讲得很清楚Q就不{载了Q直接脓地址Q?span style="font-size: 12px;"><a >http://www.binarytides.com/java-socket-programming-tutorial/</a></span><img src ="http://www.shnenglu.com/zhenglinbo/aggbug/201533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhenglinbo/" target="_blank">hoshelly</a> 2013-07-05 15:55 <a href="http://www.shnenglu.com/zhenglinbo/archive/2013/07/05/201533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>exec函数http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200259.htmlhoshellyhoshellyTue, 14 May 2013 09:37:00 GMThttp://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200259.htmlhttp://www.shnenglu.com/zhenglinbo/comments/200259.htmlhttp://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200259.html#Feedback0http://www.shnenglu.com/zhenglinbo/comments/commentRss/200259.htmlhttp://www.shnenglu.com/zhenglinbo/services/trackbacks/200259.html用f o r k函数创徏子进E后Q子q程往往要调用一Ue x e c函数以执行另一个程序?/span>当进E调用一Ue x e c函数Ӟ该进E完全由新程序代换,而新E序则从?m a i n函数开始执行?/span>因ؓ调用e x e cq不创徏新进E,所以前后的q程I Dq未改变?/span>e x e c只是用另一个新E序替换?/u>当前q程的正文、数据、堆和栈Dc?/u>
有六U不同的e x e c函数可供使用Q具体参考APUEQ,它们常常被统UCؓe x e c函数。这些e x e c函数都是U N I Xq?/span>E控制原语。用f o r k可以创徏新进E,用e x e c可以执行新的E序。e x i t函数和两个w a i t函数处理l止和等待终止。这些是我们需要的基本的进E控制原语?br />


hoshelly 2013-05-14 17:37 发表评论
]]>
initq程 与僵进E?/title><link>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200258.html</link><dc:creator>hoshelly</dc:creator><author>hoshelly</author><pubDate>Tue, 14 May 2013 09:32:00 GMT</pubDate><guid>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200258.html</guid><wfw:comment>http://www.shnenglu.com/zhenglinbo/comments/200258.html</wfw:comment><comments>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200258.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhenglinbo/comments/commentRss/200258.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhenglinbo/services/trackbacks/200258.html</trackback:ping><description><![CDATA[<div></div><div><span style="font-size: 10pt;">在说明f o r k函数Ӟ一定是一个父q程生成一个子q程。上面又说明了子q程其l止?/span><span style="font-size: 10pt;">态返回给父进E。但是如果父q程在子q程之前l止Q则如何呢Q其回答是对于其父进E已</span><span style="font-size: 10pt;">l终止的所有进E,它们的父q程都改变ؓi n i tq程?/span></div><div><span style="font-size: 10pt;">我们U这些进E由i n i tq程领养。其操作</span><span style="font-size: 10pt;">q程大致是:在一个进E终止时Q内栔R个查所有活动进E,以判断它是否是正要终止的q?/span><span style="font-size: 10pt;">E的子进E,如果是,则该q程的父q程I D更改ؓ1 ( i n i tq程的I D )。这U处理方法保证了?/span><span style="font-size: 10pt;">个进E有一个父q程?br /><br /></span><div><span style="font-size: 10pt;">如果子进E在父进E之前终止,那么父进E又如何能在做相应检</span><span style="font-size: 10pt;">查时得到子进E的l止状态呢Q对此问题的回答是内ؓ每个l止子进E保存了一定量的信</span></div><div><span style="font-size: 10pt;">息,所以当l止q程的父q程调用 w a i t或waitpid Ӟ可以得到有关信息。这U信息至包?/span><span style="font-size: 10pt;">q程I D、该q程的终止状态、以反该q程使用?C P U旉总量。内核可以释攄止进E所?/span><span style="font-size: 10pt;">用的所有存储器Q关闭其所有打开文g。在 U N I X术语中,一个已l终止、但是其父进E尚?/span><span style="font-size: 10pt;">对其q行善后处理Q获取终止子q程的有关信息、释攑֮仍占用的资源Q的q程被称为僵死进E(z o m b i eQ。p s ( 1 )命o僵死进E的状态打Cؓ Z?br /><br /></span><div><span style="font-size: 10pt;">一个由i n i tq程领养的进E终止时会发生什?它会不会变成一</span><span style="font-size: 10pt;">个僵死进E?Ҏ问题的回{是“?#8221;Q因为i n i t被编写成只要有一个子q程l止Q?i n i t׃?/span><span style="font-size: 10pt;">用一个w a i t函数取得其终止状态。这样也防止了在系l中有很多僵死进E。当提及“一个i n i t</span><span style="font-size: 10pt;">的子q程”Ӟq指的是i n i t直接产生的进E,或者是其父</span><span style="font-size: 10pt;">q程已终止,由init 领养的进E?/span></div></div></div><img src ="http://www.shnenglu.com/zhenglinbo/aggbug/200258.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhenglinbo/" target="_blank">hoshelly</a> 2013-05-14 17:32 <a href="http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200258.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fork ?vfork 的区?& exit 和_exit的区?/title><link>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200257.html</link><dc:creator>hoshelly</dc:creator><author>hoshelly</author><pubDate>Tue, 14 May 2013 09:26:00 GMT</pubDate><guid>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200257.html</guid><wfw:comment>http://www.shnenglu.com/zhenglinbo/comments/200257.html</wfw:comment><comments>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhenglinbo/comments/commentRss/200257.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhenglinbo/services/trackbacks/200257.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">1.1<br />fork可以创徏一个新的子q程Q调用一ơ,q回两次Q一ơ返?值给子进E,另一ơ返回新的子q程的IDl父q程 。子q程是父q程的复制品Q拥有父q程的数据空间、堆和栈Q父子进Eƈ不共享存储空_如果正文D|只读的,那么父子q程׃n正文Dc?/span><br /><span style="font-size: 10pt;">一般而言Qfork之后是父q程先执行还是子q程先执行是不确定的Q这取决于内核的调度法?/span><br /><span style="font-size: 10pt;">fork有两U用法:</span><br /><span style="font-size: 10pt;">Q?Q一个父q程希望复制自己Q父、子q程同时执行不同的代码段?/span><span style="font-size: 10pt;">q在|络服务q程</span><span style="font-size: 10pt;">中是常见?#8212;—父进E等待委托者的服务h。当q种h到达Ӟ父进E调?f o r kQ子进</span><span style="font-size: 10pt;">E处理此h。父q程则l等待下一个服务请求?/span><div><span style="font-size: 10pt;">Q?Q?一个进E要执行一个不同的E序。这对s h e l l是常见的情况。在q种情况下,子进E在</span><span style="font-size: 10pt;">从f o r kq回后立卌用e x e c?/span></div><br /><span style="font-size: 10pt;">1.2<br />vfork用于创徏一个新的进E,而新的进E的目的是exec一个新E序Qvforkq不父q程的地址I间复制l子q程Q因为子q程会立卌用execQ_exitQ,于是也就不会讉K地址I间。不q它在调用exec或_exit之前Q它在父q程的空间中q行?br /><br />fork创徏的子q程׃n父进E的数据Dc堆栈段Qvfork创徏的子q程׃n父进E的数据Dc?br /><br />vfork与fork的另一个区别是Qvfork保证子进E先q行Q在它调用exec或exit之后父进E才可能被调度运行,Q如果在调用q两个函C前子q程依赖于父q程的进一步动作,则会D死锁Q?br /><br />2.1<br />exit和_exit都是正常l止q程Q_exit用于vfork时父q程有可能会被调度,它们都不同于异常l止abortQ在异常l止情况下,内核Q不是进E)产生一个指C其l止异常l止原因的终止状态?/span><img src ="http://www.shnenglu.com/zhenglinbo/aggbug/200257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhenglinbo/" target="_blank">hoshelly</a> 2013-05-14 17:26 <a href="http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ourhdr.h~译错误时解军_?/title><link>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200253.html</link><dc:creator>hoshelly</dc:creator><author>hoshelly</author><pubDate>Tue, 14 May 2013 08:03:00 GMT</pubDate><guid>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200253.html</guid><wfw:comment>http://www.shnenglu.com/zhenglinbo/comments/200253.html</wfw:comment><comments>http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhenglinbo/comments/commentRss/200253.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhenglinbo/services/trackbacks/200253.html</trackback:ping><description><![CDATA[|上扄Q摘抄如下:<br /><br /><div><span style="font-size: 12px;">Qinclude "apue.h"</span></div><div><span style="font-size: 12px;">    q个头文件是作者把每个例程中常用的标准头文Ӟ一些常用的出错处理函数Qerr_**Q)之类的函</span></div><div><span style="font-size: 12px;">敎ͼ和一些常用的宏定义给整理在一个头文g中。这个可以省d每个例程中录入较多的重复代码Q这样可</span></div><div><span style="font-size: 12px;">以减每个例E的长度。但l读者带来了不少ȝ。下面给出源代码的编译方法?/span></div><div><span style="font-size: 12px;"><br /></span></div><div> </div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">一Q整体编译:</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">1.APUE2源代码下载:http://www.apuebook.com/src.tar.gz</span></div><div><span style="font-size: 12px;">2.我保存到?home/wx?解压~?tar zxvf src.tar.gz</span></div><div><span style="font-size: 12px;">3.cd apue.2e到apue.2e目录Q查看README,告诉我们linuxpȝ只要修改Make.defines.linux再makeQ?/span></div><div><span style="font-size: 12px;">4.vi Make.defines.linux 修改WKDIR=/home/wx/apue.2e 是说工作目录ؓWKDIR=/home/wx/apue.2e</span></div><div><span style="font-size: 12px;">5.修改/home/wx/apue.2e/std/linux.mk把全部的nawk改ؓawk.因些linux默认没有nawk</span></div><div><span style="font-size: 12px;">6.cd /home/wx/apue.2e</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">   make</span></div><div><span style="font-size: 12px;">7.把生成的apue.2e/lib/libapue.a与apue.2e/include/apue.h拯C~写的源代码目录下?/span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">   Q注Q你可以把libapue.a和apue.h保存在容易找到的文g夹中Q以便用)</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">8.使用gcc -o ls1 ls1.c  libapue.a来编译你的源代码</span></div><div><span style="font-size: 12px;">9.成功<br /><br /><br /></span></div><div style="font-family: Tahoma; font-size: 11px;"></div><img src ="http://www.shnenglu.com/zhenglinbo/aggbug/200253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhenglinbo/" target="_blank">hoshelly</a> 2013-05-14 16:03 <a href="http://www.shnenglu.com/zhenglinbo/archive/2013/05/14/200253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Vim文本的选择http://www.shnenglu.com/zhenglinbo/archive/2013/04/13/199417.htmlhoshellyhoshellySat, 13 Apr 2013 14:57:00 GMThttp://www.shnenglu.com/zhenglinbo/archive/2013/04/13/199417.htmlhttp://www.shnenglu.com/zhenglinbo/comments/199417.htmlhttp://www.shnenglu.com/zhenglinbo/archive/2013/04/13/199417.html#Feedback0http://www.shnenglu.com/zhenglinbo/comments/commentRss/199417.htmlhttp://www.shnenglu.com/zhenglinbo/services/trackbacks/199417.html
在正常模式下Q按ESCq入Q按键vq入可视化模式,然后按键盘左右键或h,l键即可实现文本的选择?/span>
其它相关命oQ?/span>
vQ按字符选择。经怋用的模式Q所以亲自尝试一下它?/span>
VQ按行选择。这在你x贝或者移动很多行的文本的时候特别有用?/span>

CTRLQvQ按块选择。非常强大,只在很少的编辑器中才有这L功能。你可以选择一个矩形块Qƈ且在q个矩Ş里面的文本会被高亮?/span>

值得注意的是如果VIM中用自动换行,那么直到你按ENTER换行前,VIM都会你之前输入的内容视Z行而不是你看到的好几行Q按块选择时就会按VIM中的行来选择块?/span>

在选择模式的时候用上面所q的方向键和命oQmotionQ。比如,vwwwQ会高亮光标前面的三个词。Vjj 会高亮当前行以及下面两行?/span>


hoshelly 2013-04-13 22:57 发表评论
]]>
wait 和waitpid详解http://www.shnenglu.com/zhenglinbo/archive/2013/04/13/199412.htmlhoshellyhoshellySat, 13 Apr 2013 14:05:00 GMThttp://www.shnenglu.com/zhenglinbo/archive/2013/04/13/199412.htmlhttp://www.shnenglu.com/zhenglinbo/comments/199412.htmlhttp://www.shnenglu.com/zhenglinbo/archive/2013/04/13/199412.html#Feedback0http://www.shnenglu.com/zhenglinbo/comments/commentRss/199412.htmlhttp://www.shnenglu.com/zhenglinbo/services/trackbacks/199412.htmlwait的函数原型是Q? 
#include<sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status)     
      q程一旦调用了waitQ就立即d自己Q由wait自动分析?/span>
否当前进E的某个子进E已l退出,如果让它扑ֈ了这样一?/span>
已经变成僵尸的子q程Q?wait׃攉q个子进E的信息Qƈ
把它d销毁后q回Q如果没有找到这样一个子q程Qwait?/span>
会一直阻塞在q里Q直到有一个出Cؓ止。    
      参数status用来保存被收集进E退出时的一些状态,它是
一个指向intcd的指针。但如果我们对这个子q程是如何死?/span>
的毫不在意,只想把这个僵进E消灭掉Q(事实上绝大多?/span>
情况下,我们都会q样惻IQ我们就可以讑֮q个参数?/span>
NULLQ就象下面这P     pid = wait(NULL);
如果成功Qwait会返回被攉的子q程的进EIDQ如果调用进
E没有子q程Q调用就会失败,此时waitq回-1Q同时errno?/span>
|ؓECHILD。 
      waitpid的函数原型是Q?  
waitpidpȝ调用在Linux函数库中的原型是Q?  
#include <sys/types.h>#include <sys/wait.h>

pid_t waitpid(pid_t pid,int *status,int options)
      从本质上Ԍpȝ调用waitpid和wait的作用是完全相同
的,但waitpid多出了两个可qh制的参数pid和optionsQ?/span>
从而ؓ我们~程提供了另一U更灉|的方式?/span>
下面我们来详细介绍一下这两个参数Q     
● pid     从参数的名字pid和类型pid_t中就可以看出Q?/span>
q里需要的是一个进EID。但当pid取不同的值时Q在q里有不
同的意义?    pid>0Ӟ只等待进EID{于pid的子q?/span>
E,不管其它已经有多子q程q行l束退ZQ只要指定的
子进E还没有l束Qwaitpid׃一直等下去。     pid=-
1Ӟ{待M一个子q程退出,没有M限制Q此时waitpid
和wait的作用一模一栗?    pid=0Ӟ{待同一个进E?/span>
l中的Q何子q程Q如果子q程已经加入了别的进E组Q?/span>
waitpid不会对它做Q何理睬?    pid<-1Ӟ{待一?/span>
指定q程l中的Q何子q程Q这个进E组的ID{于pid的绝?/span>
倹{?  
● options   options提供了一些额外的选项来控制waitpidQ?/span>
目前在Linux中只支持WNOHANG和WUNTRACED两个选项Q?/span>
q是两个常数Q可以用"|"q算W把它们q接h使用Q比如:
  ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);   
如果我们不想使用它们Q也可以把options设ؓ0Q如Q?  
ret=waitpid(-1,NULL,0);     如果使用了WNOHANG参数
调用waitpidQ即使没有子q程退出,它也会立卌回,不会?/span>
wait那样永远{下厅R?    而WUNTRACED参数Q由?/span>
涉及C些跟t调试方面的知识Q加之极用刎ͼq里׃?/span>
费笔墨了Q有兴趣的读者可以自行查阅相x料。    ?/span>
到这里,聪明的读者可能已l看出端倪了--wait不就是经q包?/span>
的waitpid吗?没错Q察?lt;内核源码目录>/include/unistd.h?/span>
?49-352行就会发C下程序段Q     static inline
pid_t wait(int * wait_stat)   {    return waitpid(-
1,wait_stat,0);   }      q回值和错误     
waitpid的返回值比waitE微复杂一些,一共有3U情况:  
● 当正常返回的时候,waitpidq回攉到的子进E的q程IDQ?/span>
● 如果讄了选项WNOHANGQ而调用中waitpid发现没有?/span>
退出的子进E可攉Q则q回0Q?     
● 如果调用中出错,则返?1Q这时errno会被讄成相应的
g指示错误所在;当pid所指示的子q程不存在,或此q程?/span>
在,但不是调用进E的子进E,waitpid׃出错q回Q这?/span>
errno被设|ؓECHILD 其它Q?调用 waitQwaitpid 来处理终?/span>
的子q程Q?pid_t wait(int * statloc); pid_t waitpid(pid_t pid,
int *statloc, int options); 两个函数都返回两个|函数的返?/span>
值和l止的子q程IDQ而子q程l止的状态则是通过statloc?/span>
针返回的?waitQwaitpid 的区别是显而易见的Qwait{待W一
个终止的子进E,而waitpid则可以指定等待特定的子进E。这
L区别可能会在下面q种情况时表现得更加明显Q当同时?/span>
5个客戯上服务器Q也是说有五个子进E分别对应了5个客
P此时Q五个客户几乎在同时hl止Q这样一来,几乎?/span>
Ӟ五个FIN发向服务器,同样的,五个SIGCHLD信号到达?/span>
务器Q然而,UNIX的信号往往是不会排队的Q显然这样一来,
信号处理函数只会执行一ơ,D留剩余四个子进E作为僵?/span>
q程ȝ在内核空间。此Ӟ正确的解军_法是利用waitpid(-
1, &stat, WNOHANG)防止留下僵尸q程。其中的pid为-1?/span>
明等待第一个终止的子进E,而WNOHANG选择w知内核?/span>
没有已终止进E项时不要阻塞?/span>
waitQwaitpid 区别 :
waitpid提供了wait函数不能实现?个功? waitpid{待特定?/span>
子进E? 而wait则返回Q一l止状态的子进E? waitpid提供了一
个wait的非d版本; waitpid支持作业控制(以WUNTRACED?/span>
?. 用于查wait和waitpid两个函数q回l止状态的? q两?/span>
函数q回的子q程状态都保存在statloc指针? 用以?个宏?/span>
以检查该状? WIFEXITED(status): 若ؓ正常l止, 则ؓ? ?/span>
时可执行 WEXITSTATUS(status): 取子q程传送给exit或_exit
参数的低8? WIFSIGNALED(status): 若ؓ异常l止, 则ؓ?
此时可执?WTERMSIG(status): 取子进E终止的信号~号.
WIFSTOPPED(status): 若ؓ当前暂停子进E? 则ؓ? 此时?/span>
执行 WSTOPSIG(status): 取子进E暂停的信号~号


hoshelly 2013-04-13 22:05 发表评论
]]>
ݺɫþۺ| þþƷĻ| þAv뾫Ʒϵ| ݺݺݾþ| ŷսպ91ۺһþþ | ݺݸɺݺݾþ| ާѡþþþƷ| þþƷ鶹ҹҹ| aëƬþѲ| ޾Ʒþþþ66| 󽶾þĻ| 97þùۺϾƷŮ| þþƷݲݲ| 99þùۺ| Ʒ˾þþ| þùҹaӰԺ| þùƷ99Ʒ| ձvaҹĻþ| Ʒþþþþþ| þþþþþþþþ| ŷպƷþþþ| ˾Ʒþһav | 99þó˹Ʒ| þþƷAVþþ| þó18վ| 㽶þҹɫƷС˵| þþƷav | þþþAV鶹| Ʒþþþþ| ƷŷƬþùŷ...| þþƷˬ97| ɫۺϾþʮ·| AëƬþþƷ | þˬˬAV| ޹㽶ˬAVƬþ| þþƷһ| ɫۺϾþþþ| þþžžþƷֱ| ܻƺ۵վþmimiɫ| þþþ뾫Ʒapp| þþƷĻ|