琐记7:关于fork()函数的一些小知识
2017-08-10 10:14
197 查看
首先,fork() 函数的主要功能通俗的说是创建一个子进程。这2个进程是相互独立的两个进制,它们共享的内容只有代码段。这时候就要提到我们之前学到
的一个知识点——内存四区了,在栈,堆,数据段和代码段这四个大块中,它们父子俩的前三个是完全区分开的,像这样一个函数:
它的答案就是两个1,而不是1和2 。
另外就是父子进程的运行先后问题,它们的执行先后是不确定的(虽然笔者在red hat实验了很多次,都是子进程先执行)。
关于这个函数的返回值问题,因为它有2个进程,自然而然的它有也2个返回值,在父进程中,返回值为子进程的ID,在子进程中,返回值为0;我们可以使用getpid()函数来获取它们各自的ID号,如下:
因为每调用一次fork() 函数就会产生一个相应的子进程,所以,很显然的,连续调用三次fork() 就能产生总共8个进程,这不难理解。但,不要觉得这很容易理解,我们来看一下下面这道题,判断一下会有 多少个a被打印出来:
首先,我们很容易理解的是,第3行和第5行代码,就是进程的翻倍,主要就是看第四行代码的意思,我们假设主进程为1,在第三行代码执行结束时,它产生了子进程2,我们分开讨论,判断了1的执行结果翻倍就是总的进程数。
在第四行代码中:2进程在执行完第一个fork() 函数后产生了它的子进程3,2进程的返回值为3进程的ID(一个大于0的正整数),所以就执行&&操作的后半部分第二个fork() 函数,产生子进程4,返回值为4的ID,所以就不执行 || 后面的操作了,到此,2进程结束; 再回来看它的子进程3,它作为子进程,返回值为0,所以&&的后半部分是执行不了了,但&&完之后的结果就是0,可以进行接下来的
|| 操作,于是它又产生了一个子进程5;同样,2进程产生的另一个 子进程4和3进程是一个道理,也要执行||操作的后半部分,产生一个子进程6。
到此,第四行代码全部执行完毕,产生了包括2在内总共5个进程,于是最终的结果就是2*5*2 = 20个进程。
另外,与fork() 函数相类似的还有一个vfork() 函数, 它有这样一些特点:
1) vfork() 函数的子进程必须显式调用;
2)vfork() 函数的父子进程共享数据段;
3)vfork() 函数的子进程要先于父进程执行,即子进程运行结束,CPU才能调度到父进程。
的一个知识点——内存四区了,在栈,堆,数据段和代码段这四个大块中,它们父子俩的前三个是完全区分开的,像这样一个函数:
int main() { int count = 0; pid_t pid = fork(); count++; printf ("count = %d\n", count); return 0; }
它的答案就是两个1,而不是1和2 。
另外就是父子进程的运行先后问题,它们的执行先后是不确定的(虽然笔者在red hat实验了很多次,都是子进程先执行)。
关于这个函数的返回值问题,因为它有2个进程,自然而然的它有也2个返回值,在父进程中,返回值为子进程的ID,在子进程中,返回值为0;我们可以使用getpid()函数来获取它们各自的ID号,如下:
int main() { pid_t pid = fork(); if (pid == -1) { perror ("fork"); return -1; } if (pid > 0) // 父进程 { printf ("我是父进程,pid = %d\n", getpid()); } else if (pid == 0) // 子进程 { printf ("我是子进程,pid = %d\n", getpid()); } return 0; }
因为每调用一次fork() 函数就会产生一个相应的子进程,所以,很显然的,连续调用三次fork() 就能产生总共8个进程,这不难理解。但,不要觉得这很容易理解,我们来看一下下面这道题,判断一下会有 多少个a被打印出来:
int main() { fork(); fork() && fork() || fork(); fork(); printf("a\n"); return 0; }
首先,我们很容易理解的是,第3行和第5行代码,就是进程的翻倍,主要就是看第四行代码的意思,我们假设主进程为1,在第三行代码执行结束时,它产生了子进程2,我们分开讨论,判断了1的执行结果翻倍就是总的进程数。
在第四行代码中:2进程在执行完第一个fork() 函数后产生了它的子进程3,2进程的返回值为3进程的ID(一个大于0的正整数),所以就执行&&操作的后半部分第二个fork() 函数,产生子进程4,返回值为4的ID,所以就不执行 || 后面的操作了,到此,2进程结束; 再回来看它的子进程3,它作为子进程,返回值为0,所以&&的后半部分是执行不了了,但&&完之后的结果就是0,可以进行接下来的
|| 操作,于是它又产生了一个子进程5;同样,2进程产生的另一个 子进程4和3进程是一个道理,也要执行||操作的后半部分,产生一个子进程6。
到此,第四行代码全部执行完毕,产生了包括2在内总共5个进程,于是最终的结果就是2*5*2 = 20个进程。
另外,与fork() 函数相类似的还有一个vfork() 函数, 它有这样一些特点:
1) vfork() 函数的子进程必须显式调用;
2)vfork() 函数的父子进程共享数据段;
3)vfork() 函数的子进程要先于父进程执行,即子进程运行结束,CPU才能调度到父进程。
相关文章推荐
- 关于正则表达式的一些知识和函数总结
- 关于安全方面的一些函数和知识
- 关于fork()函数特性的一些探究
- 关于GetOverlappedResult函数的一些知识
- 关于指针的一些知识,记多维数组指针、指针数组、指针的指针和指向函数的指针
- C语言中关于数组、指针以及函数的一些基本知识
- 关于HTML5的一些基础知识
- 关于 MySQL connections 的一些知识
- 关于const 修饰的一些知识
- 关于hibernate的一些基础知识
- 关于头结点的一些知识!
- 关于#include中的C++头文件的一些知识
- [科普文] 关于浏览器内核的一些小知识,明明白白选浏览器!
- 关于A*算法求解最短路径问题的一些知识
- 关于回调函数和钩子函数基础知识的整理
- 关于Oracle的一些函数
- 关于fork函数生成父子进程变量虚拟地址
- 关于fork()函数的作用
- 关于Android开发自己的一些知识储备