从一道面试题谈linux下fork的运行机制
2015-10-12 20:24
681 查看
原帖地址:从一道面试题谈linux下fork的运行机制
今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译:
要求如下:
已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。
1、请说出执行这个程序后,将一共运行几个进程。
2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。
明显这道题的目的是考察linux下fork的执行机制。下面我们通过分析这个题目,谈谈linux下fork的运行机制。
这里先列出一些必要的预备知识,对linux下进程机制比较熟悉的朋友可以略过。
1、进程可以看做程序的一次执行过程。在linux下,每个进程有唯一的PID标识进程。PID是一个从1到32768的正整数,其中1一般是特殊进程init,其它进程从2开始依次编号。当用完32768后,从2重新开始。
2、linux中有一个叫进程表的结构用来存储当前正在运行的进程。可以使用“ps aux”命令查看所有正在运行的进程。
3、进程在linux中呈树状结构,init为根节点,其它进程均有父进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。
4、fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
有了上面的预备知识,我们再来看看解题的关键。我认为,解题的关键就是要认识到fork将程序切成两段。看下图:
![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121121573496.gif)
上图表示一个含有fork的程序,而fork语句可以看成将程序切为A、B两个部分。然后整个程序会如下运行:
step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。
step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前值。
step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。
step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。
这里有三个点非常关键:
1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)
2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。
3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。
解题
下面利用上文阐述的知识进行解题。这里我把两个问题放在一起进行分析。
1、从shell中执行此程序,启动了一个进程,我们设这个进程为P0,设其PID为XXX(解题过程不需知道其PID)。
2、当执行到pid1 = fork();时,P0启动一个子进程P1,由题目知P1的PID为1001。我们暂且不管P1。
3、P0中的fork返回1001给pid1,继续执行到pid2 = fork();,此时启动另一个新进程,设为P2,由题目知P2的PID为1002。同样暂且不管P2。
4、P0中的第二个fork返回1002给pid2,继续执行完后续程序,结束。所以,P0的结果为“pid1:1001, pid2:1002”。
5、再看P2,P2生成时,P0中pid1=1001,所以P2中pid1继承P0的1001,而作为子进程pid2=0。P2从第二个fork后开始执行,结束后输出“pid1:1001, pid2:0”。
6、接着看P1,P1中第一条fork返回0给pid1,然后接着执行后面的语句。而后面接着的语句是pid2 = fork();执行到这里,P1又产生了一个新进程,设为P3。先不管P3。
7、P1中第二条fork将P3的PID返回给pid2,由预备知识知P3的PID为1003,所以P1的pid2=1003。P1继续执行后续程序,结束,输出“pid1:0, pid2:1003”。
8、P3作为P1的子进程,继承P1中pid1=0,并且第二条fork将0返回给pid2,所以P3最后输出“pid1:0, pid2:0”。
9、至此,整个执行过程完毕。
所得答案:
1、一共执行了四个进程。(P0, P1, P2, P3)
2、另外几个进程的输出分别为:
PO:pid1:1001,pid2:1002
P1:pid1:0, pid2:1003
P2:pid1:1001, pid2:0
P3:pid1:0, pid2:0
进一步可以给出一个以P0为根的进程树:
![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121122414385.gif)
下面我们去linux下实际执行这个程序,来验证我们的答案。 程序如下图:
![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121122515562.png)
用gcc编译、执行后结果如下:
![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121122511552.png)
由于我们不太可能刚巧碰上PID分配到1001的情况,所以具体数值可能和答案有所差别。不过将这里的2710看做基数的话,结果和我们上面的解答是一致的。
应该说这不是一道特别难或特别刁钻的题目,但是由于fork函数运行机制的复杂性,造就了当两个fork并排时,问题就变得很复杂。解这个题的关键,一是要对linux下进程的机制有一定认识,二是抓住上文提到的几个关于fork的关键点。朋友说,这个题给的时间是5分钟,应该说时间还算充裕,但是在面试的场合下,还是很考验一个人对进程、fork的掌握程度和现场推理能力。
希望本文能帮助朋友们对fork的执行机制有一个明晰的认识。
-----------------------------------------------------------------------------------------------------------------------------------------------
在Unix/Linux中用fork函数创建一个新的进程。进程是由当前已有进程调用fork函数创建,分叉的进程叫子进程,创建者叫父进程。该函数的特点是调用一次,返回两次,一次是在父进程,一次是在子进程。两次返回的区别是子进程的返回值为0,父进程的返回值是新子进程的ID。子进程与父进程继续并发运行。如果父进程继续创建更多的子进程,子进程之间是兄弟关系,同样子进程也可以创建自己的子进程,这样可以建立起定义关系的进程之间的一种层次关系。
程序包含位于内存的多个组成部分,执行程序的过程将根据需要来访问这些内容,包括文本段(text segment)、数据段(data segments)、栈(stack)和堆(heap)。文本段中存放CPU所执行的命令,数据段存放进程操作的所有数据变量,栈存放自动变量和函数数据,堆存放动态内存分配情况数据。当进程被创建时,子进程收到父进程的数据副本,包括数据空间、堆、栈和进程描述符。
程序1:创建一个子进程,子进程对继承的数据进行修改,然后分别输出父子进程的信息。程序如下:
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
fork函数执行后程序结构图如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121615133539.png)
子进程与父进程并行执行,因此在父进程中sleep(10),让子进程先执行,然后再执行父进程。
程序执行结果如下所示:
![](http://pic002.cnblogs.com/images/2012/305504/2012121614543678.png)
如何创建多个子进程呢?在开发并发服务器时,用到的进程池模型需要先创建指定书目的子进程。举个例子,假如我们现在需要创建2个子进程,很容易想到的是调用一个循环,执行fork函数2次即可。尝试一下是否可行呢?代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
程序执行结果如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121616162861.png)
从结果来看,子进程的数目不是2而是3,这是为什么呢?先简单的分析一下:从结果看出父进程ID为10669,子进程的ID分别为:10670、10671、10672。
父子进程之间的关系如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121616312349.png)
ID为10670的子进程也调用fork函数,创建了一个进程。因为fork函数创建的进程是父进程的一份拷贝,保存了当前的数据空间、堆、栈及共享代码区域。正确的方式应该是在子进程中跳出,停止继续fork。改进的代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
程序执行结果如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121616415249.png)
从结果可以看出这父进程(ID为10789)创建了两个子进程(ID分别为:10790、10791)。
现有有这样一个面试题,程序如下:
要求如下:
已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。
1、请说出执行这个程序后,将一共运行几个进程。
2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。
这个题目考查fork函数的理解。fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程,父子进程并行的执行剩下的部分。
程序的执行过程如下:
(1)程序开始执行时候系统分配一个进程进行执行,称该进程为主进程P,进程ID题目未给,
(2)主进程执行到第一个fork函数的时候,创建一个新的子进程P1,有题目可知进程ID为1001,fork函数有两个返回值,返回pid=0代表子进程P1,pid1>0代表父进程P。
(3)现在有两个进程P和P1,分别执行剩下部分,
(4)P进程(父进程,所以pid1=1001)调用fork创建子进程P2,返回两个值中pid2=1002表示P2的进程ID返回给父进程P,pid2=0子进程P2本身,所以输出pid1=1001, pid2=1002和pid1=1001,pid2=0。
(5)P1进程(子进程,所以pid1=0)调用fork创建子进程P3,进程ID类推为1003,返回两个值中pid2=1003表示P3的进程ID返回给父进程P1,pid2=0标识进程P3本身。所以输出pid1=0,pid2=1003和pid1=0,pid2=0。
(6)执行整个结束。
根据以上分析可知答案:
1、一共执行了四个进程。(P0, P1, P2, P3)
2、另外几个进程的输出分别为:
pid1:1001, pid2:0
pid1:0, pid2:1003
pid1:0, pid2:0
上机测试如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121622345246.png)
测试结果如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121622374412.png)
测试结果虽然不是1001,但是可以看出理论分析过程是正确的。
题目来自:/content/3549690.html
今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译:
#include "stdio.h" #include "sys/types.h" #include "unistd.h" int main() { pid_t pid1; pid_t pid2; pid1 = fork(); pid2 = fork(); printf("pid1:%d, pid2:%d\n", pid1, pid2); }
要求如下:
已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。
1、请说出执行这个程序后,将一共运行几个进程。
2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。
明显这道题的目的是考察linux下fork的执行机制。下面我们通过分析这个题目,谈谈linux下fork的运行机制。
预备知识
这里先列出一些必要的预备知识,对linux下进程机制比较熟悉的朋友可以略过。1、进程可以看做程序的一次执行过程。在linux下,每个进程有唯一的PID标识进程。PID是一个从1到32768的正整数,其中1一般是特殊进程init,其它进程从2开始依次编号。当用完32768后,从2重新开始。
2、linux中有一个叫进程表的结构用来存储当前正在运行的进程。可以使用“ps aux”命令查看所有正在运行的进程。
3、进程在linux中呈树状结构,init为根节点,其它进程均有父进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。
4、fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
解题的关键
有了上面的预备知识,我们再来看看解题的关键。我认为,解题的关键就是要认识到fork将程序切成两段。看下图:![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121121573496.gif)
上图表示一个含有fork的程序,而fork语句可以看成将程序切为A、B两个部分。然后整个程序会如下运行:
step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。
step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前值。
step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。
step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。
这里有三个点非常关键:
1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)
2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。
3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。
解题
下面利用上文阐述的知识进行解题。这里我把两个问题放在一起进行分析。
1、从shell中执行此程序,启动了一个进程,我们设这个进程为P0,设其PID为XXX(解题过程不需知道其PID)。
2、当执行到pid1 = fork();时,P0启动一个子进程P1,由题目知P1的PID为1001。我们暂且不管P1。
3、P0中的fork返回1001给pid1,继续执行到pid2 = fork();,此时启动另一个新进程,设为P2,由题目知P2的PID为1002。同样暂且不管P2。
4、P0中的第二个fork返回1002给pid2,继续执行完后续程序,结束。所以,P0的结果为“pid1:1001, pid2:1002”。
5、再看P2,P2生成时,P0中pid1=1001,所以P2中pid1继承P0的1001,而作为子进程pid2=0。P2从第二个fork后开始执行,结束后输出“pid1:1001, pid2:0”。
6、接着看P1,P1中第一条fork返回0给pid1,然后接着执行后面的语句。而后面接着的语句是pid2 = fork();执行到这里,P1又产生了一个新进程,设为P3。先不管P3。
7、P1中第二条fork将P3的PID返回给pid2,由预备知识知P3的PID为1003,所以P1的pid2=1003。P1继续执行后续程序,结束,输出“pid1:0, pid2:1003”。
8、P3作为P1的子进程,继承P1中pid1=0,并且第二条fork将0返回给pid2,所以P3最后输出“pid1:0, pid2:0”。
9、至此,整个执行过程完毕。
所得答案:
1、一共执行了四个进程。(P0, P1, P2, P3)
2、另外几个进程的输出分别为:
PO:pid1:1001,pid2:1002
P1:pid1:0, pid2:1003
P2:pid1:1001, pid2:0
P3:pid1:0, pid2:0
进一步可以给出一个以P0为根的进程树:
![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121122414385.gif)
验证
下面我们去linux下实际执行这个程序,来验证我们的答案。 程序如下图:![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121122515562.png)
用gcc编译、执行后结果如下:
![](http://pic002.cnblogs.com/img/leoo2sk/200912/2009121122511552.png)
由于我们不太可能刚巧碰上PID分配到1001的情况,所以具体数值可能和答案有所差别。不过将这里的2710看做基数的话,结果和我们上面的解答是一致的。
总结
应该说这不是一道特别难或特别刁钻的题目,但是由于fork函数运行机制的复杂性,造就了当两个fork并排时,问题就变得很复杂。解这个题的关键,一是要对linux下进程的机制有一定认识,二是抓住上文提到的几个关于fork的关键点。朋友说,这个题给的时间是5分钟,应该说时间还算充裕,但是在面试的场合下,还是很考验一个人对进程、fork的掌握程度和现场推理能力。希望本文能帮助朋友们对fork的执行机制有一个明晰的认识。
-----------------------------------------------------------------------------------------------------------------------------------------------
在Unix/Linux中用fork函数创建一个新的进程。进程是由当前已有进程调用fork函数创建,分叉的进程叫子进程,创建者叫父进程。该函数的特点是调用一次,返回两次,一次是在父进程,一次是在子进程。两次返回的区别是子进程的返回值为0,父进程的返回值是新子进程的ID。子进程与父进程继续并发运行。如果父进程继续创建更多的子进程,子进程之间是兄弟关系,同样子进程也可以创建自己的子进程,这样可以建立起定义关系的进程之间的一种层次关系。
程序包含位于内存的多个组成部分,执行程序的过程将根据需要来访问这些内容,包括文本段(text segment)、数据段(data segments)、栈(stack)和堆(heap)。文本段中存放CPU所执行的命令,数据段存放进程操作的所有数据变量,栈存放自动变量和函数数据,堆存放动态内存分配情况数据。当进程被创建时,子进程收到父进程的数据副本,包括数据空间、堆、栈和进程描述符。
程序1:创建一个子进程,子进程对继承的数据进行修改,然后分别输出父子进程的信息。程序如下:
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 8 int add(int a,int b); 9 //全局变量 10 int global = 99; 11 char buf[] = "Input a string: "; 12 13 int main() 14 { 15 pid_t pid; 16 int val,ret; 17 char *str; 18 val =49; 19 str = (char*)malloc(100*sizeof(char)); 20 memset(str,0,100*sizeof(char)); 21 if((pid = fork()) == -1) 22 { 23 perror("fork() error"); 24 exit(-1); 25 } 26 if(pid == 0) //子进程 27 { 28 printf("Child process start exec.\n"); 29 global++; 30 val++; 31 } 32 if(pid >0) //父进程 33 { 34 sleep(10); //等待子进程执行 35 printf("Parent process start exec.\n"); 36 } 37 printf("pid=%d,ppid=%d,global=%d,val=%d\n",getpid(),getppid(),global,val); 38 write(STDOUT_FILENO,buf,strlen(buf)); 39 read(STDIN_FILENO,str,100); 40 write(STDOUT_FILENO,str,strlen(str)); 41 ret = add(global,val); 42 printf("global+val=%d\n",ret); 43 exit(0); 44 } 45 46 int add(int a,int b) 47 { 48 return (a+b); 49 }
fork函数执行后程序结构图如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121615133539.png)
子进程与父进程并行执行,因此在父进程中sleep(10),让子进程先执行,然后再执行父进程。
程序执行结果如下所示:
![](http://pic002.cnblogs.com/images/2012/305504/2012121614543678.png)
如何创建多个子进程呢?在开发并发服务器时,用到的进程池模型需要先创建指定书目的子进程。举个例子,假如我们现在需要创建2个子进程,很容易想到的是调用一个循环,执行fork函数2次即可。尝试一下是否可行呢?代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 8 int main() 9 { 10 int i; 11 pid_t pid; 12 printf("pid=%d , ppid=%d\n",getpid(),getppid()); 13 //通过一个循环创建对个子进程 14 for(i=0;i<2;++i) 15 { 16 pid = fork(); 17 if(pid == 0) 18 { 19 printf("create child process successfully.\n"); 20 printf("pid=%d , ppid=%d\n",getpid(),getppid()); 21 printf("i=%d\n",i); 22 } 23 else if(pid== -1) 24 { 25 perror("fork() error"); 26 exit(-1); 27 } 28 else 29 { 30 sleep(3); 31 printf("parent process.\n"); 32 printf("pid=%d , ppid=%d\n",getpid(),getppid()); 33 printf("i=%d\n",i); 34 } 35 } 36 37 exit(0); 38 }
程序执行结果如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121616162861.png)
从结果来看,子进程的数目不是2而是3,这是为什么呢?先简单的分析一下:从结果看出父进程ID为10669,子进程的ID分别为:10670、10671、10672。
父子进程之间的关系如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121616312349.png)
ID为10670的子进程也调用fork函数,创建了一个进程。因为fork函数创建的进程是父进程的一份拷贝,保存了当前的数据空间、堆、栈及共享代码区域。正确的方式应该是在子进程中跳出,停止继续fork。改进的代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 8 int main() 9 { 10 int i; 11 pid_t pid; 12 printf("pid=%d , ppid=%d\n",getpid(),getppid()); 13 for(i=0;i<2;++i) 14 { 15 pid = fork(); 16 if(pid == 0) 17 { 18 printf("create child process successfully.\n"); 19 printf("pid=%d , ppid=%d\n",getpid(),getppid()); 20 printf("i=%d\n",i); 21 //子进程跳出循环,防止子进程继续创建子进程 22 break; 23 } 24 else if(pid== -1) 25 { 26 perror("fork() error"); 27 exit(-1); 28 } 29 else 30 { 31 sleep(3); 32 printf("parent process.\n"); 33 printf("pid=%d , ppid=%d\n",getpid(),getppid()); 34 printf("i=%d\n",i); 35 //父进程继续创建子进程 36 continue; 37 } 38 } 39 40 exit(0); 41 }
程序执行结果如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121616415249.png)
从结果可以看出这父进程(ID为10789)创建了两个子进程(ID分别为:10790、10791)。
现有有这样一个面试题,程序如下:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <sys/types.h> 5 6 int main() 7 { 8 pid_t pid1; 9 pid_t pid2; 10 11 pid1 = fork(); 12 pid2 = fork(); 13 14 printf("pid1=%d,pid2=%d\n",pid1,pid2); 15 exit(0); 16 }
要求如下:
已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。
1、请说出执行这个程序后,将一共运行几个进程。
2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。
这个题目考查fork函数的理解。fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程,父子进程并行的执行剩下的部分。
程序的执行过程如下:
(1)程序开始执行时候系统分配一个进程进行执行,称该进程为主进程P,进程ID题目未给,
(2)主进程执行到第一个fork函数的时候,创建一个新的子进程P1,有题目可知进程ID为1001,fork函数有两个返回值,返回pid=0代表子进程P1,pid1>0代表父进程P。
(3)现在有两个进程P和P1,分别执行剩下部分,
(4)P进程(父进程,所以pid1=1001)调用fork创建子进程P2,返回两个值中pid2=1002表示P2的进程ID返回给父进程P,pid2=0子进程P2本身,所以输出pid1=1001, pid2=1002和pid1=1001,pid2=0。
(5)P1进程(子进程,所以pid1=0)调用fork创建子进程P3,进程ID类推为1003,返回两个值中pid2=1003表示P3的进程ID返回给父进程P1,pid2=0标识进程P3本身。所以输出pid1=0,pid2=1003和pid1=0,pid2=0。
(6)执行整个结束。
根据以上分析可知答案:
1、一共执行了四个进程。(P0, P1, P2, P3)
2、另外几个进程的输出分别为:
pid1:1001, pid2:0
pid1:0, pid2:1003
pid1:0, pid2:0
上机测试如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121622345246.png)
测试结果如下:
![](http://pic002.cnblogs.com/images/2012/305504/2012121622374412.png)
测试结果虽然不是1001,但是可以看出理论分析过程是正确的。
题目来自:/content/3549690.html
相关文章推荐
- Ubuntu 15.10将发布 采用 Linux Kernel 4.2内核
- 如何成为一名出色的黑客
- Centos/RedHat7破解密码
- 第 二 十 八 天 :LB 负 载 均 衡 搭 建 之 LVS
- Linux 使用信号分别在两个进程中打印AAA和BBB
- CENTOS安装部署zabbix
- Xilinx Zynq Linux内核源码编译
- Linux 使用信号量在两个进程中分别打印AAA和BBB
- Linux系统vmwaretools安装之后无法进入图形界面的问题
- linux 程序开发打印 debug()
- 每天一个linux命令(12):more命令
- linux下实现指定目录的简单遍历输出
- Linux系统编程---文件I/O思想
- centos7下安装 python2.7.10
- Linux lookback驱动分析
- linux命令概论
- CentOS 6.5 部署 Horizon
- centos 笔记
- linux内核之trap.c文件分析
- linux虚拟机共享文件查找,手动升级vmware tools