您的位置:首页 > 其它

琐记7:关于fork()函数的一些小知识

2017-08-10 10:14 197 查看
首先,fork() 函数的主要功能通俗的说是创建一个子进程。这2个进程是相互独立的两个进制,它们共享的内容只有代码段。这时候就要提到我们之前学到
的一个知识点——内存四区了,在栈,堆,数据段和代码段这四个大块中,它们父子俩的前三个是完全区分开的,像这样一个函数:

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才能调度到父进程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: