找回密码
 注册
查看: 2028|回复: 34

关于fork()函数的问题

[复制链接]
发表于 2003-5-6 21:39:02 | 显示全部楼层 |阅读模式
void main(void)
{int x=5;
if(fork())
{x+=30;
printf("%d\n",x);
}
else
printf("%d\n",x);
printf("%d\n",x);
}
可能有几种输出结果?
为什么?

我认为有4*4=16个结果
但是我在mandrake 9.0上编译运行却只得两个结果
35
35
5
5

5
5
35
35
为什么?
为什么不会出现
5
35
35
5
等结果
是我想错了吗
请大家帮帮我,
谢谢
 楼主| 发表于 2003-5-6 22:02:28 | 显示全部楼层
为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?为什么没人理我?
回复

使用道具 举报

发表于 2003-5-6 22:08:50 | 显示全部楼层
这个程序在我的Debian上运行很久只显示一个5
回复

使用道具 举报

发表于 2003-5-6 22:09:18 | 显示全部楼层
和35
回复

使用道具 举报

 楼主| 发表于 2003-5-6 22:10:02 | 显示全部楼层
[code:1]void main(void)
{int x=5;
if(fork())
{x+=30;
printf("%d\n",x);
}
else
printf("%d\n",x);
printf("%d\n",x);
}
[/code:1]
回复

使用道具 举报

发表于 2003-5-6 22:11:50 | 显示全部楼层
35
35
5
5
回复

使用道具 举报

发表于 2003-5-6 22:12:19 | 显示全部楼层
35
5
5
35
回复

使用道具 举报

发表于 2003-5-6 22:15:54 | 显示全部楼层
这两个结果交替出现
回复

使用道具 举报

 楼主| 发表于 2003-5-6 22:17:16 | 显示全部楼层
那就是说有16个答案?
还是其它的?
请说清楚点好吗?
帮帮我啊,我已经弄了四个小时了,我编译运行过不下十次。
我不是随便什么问题就问。我还没吃饭呢。就等解决这个问题了。
回复

使用道具 举报

发表于 2003-5-6 22:20:53 | 显示全部楼层
对不起哦,我从来没有用过fork函数写东西
只能帮你测试了
没办法解释问题 :-(
回复

使用道具 举报

发表于 2003-5-6 22:22:41 | 显示全部楼层
每一次显示四个结果

再运行一次就是另外四个结果

我也觉得很奇怪

fork函数功能这么利害?
回复

使用道具 举报

发表于 2003-5-6 22:23:39 | 显示全部楼层
我在man fork里面看到需要[code:1]
       #include <sys/types.h>
       #include <unistd.h>[/code:1]

但是你却没有这一行,是不是原因呢?
回复

使用道具 举报

发表于 2003-5-6 22:25:57 | 显示全部楼层
[code:1]
NAME
       fork - create a child process

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       pid_t fork(void);

DESCRIPTION
       fork  creates a child process that differs from the parent process only
       in its PID and PPID, and in the fact that resource utilizations are set
       to 0.  File locks and pending signals are not inherited.

       Under Linux, fork is implemented using copy-on-write pages, so the only
       penalty incurred by fork is the time and memory required  to  duplicate
       the parent's page tables, and to create a unique task structure for the
       child.

RETURN VALUE
       On success, the PID of the child process is returned  in  the  parent's
       thread  of execution, and a 0 is returned in the child's thread of exe-
       cution.  On failure, a -1 will be returned in the parent's context,  no
       child process will be created, and errno will be set appropriately.

ERRORS
       EAGAIN fork cannot allocate sufficient memory to copy the parent's page
              tables and allocate a task structure for the child.

       ENOMEM fork failed to allocate the necessary kernel structures  because
              memory is tight.

CONFORMING TO
       The fork call conforms to SVr4, SVID, POSIX, X/OPEN, BSD 4.3.

SEE ALSO
       clone(2), execve(2), vfork(2), wait(2)
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2003-5-6 22:26:37 | 显示全部楼层
Linux下的多进程编程

作 者 : 俞磊

(一) 理解Linux下进程的结构
  Linux下一个进程在内存里有三部份的数据,就是“数据段”,“堆栈段”和“代码段”,其实学过汇编语言的人一定知道,一般的CPU象I386,都有上述三种段寄存器,以方便操作系统的运行。“代码段”,顾名思义,就是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。
  堆栈段存放的就是子程序的返回地址、子程序的参数以及程序的局部变量。而数据段则存放程序的全局变量,常数以及动态数据分配的数据空间(比如用malloc之类的函数取得的空间)。这其中有许多细节问题,这里限于篇幅就不多介绍了。系统如果同时运行数个相同的程序,它们之间就不能使用同一个堆栈段和数据段。

(二) 如何使用fork
  在Linux下产生新的进程的系统调用就是fork函数,这个函数名是英文中“分叉”的意思。为什么取这个名字呢?因为一个进程在运行中,如果使用了fork,就产生了另一个进程,于是进程就“分叉”了,所以这个名字取得很形象。下面就看看如何具体使用fork,这段程序演示了使用fork的基本框架:

void main(){
int i;
if ( fork() == 0 ) {
/* 子进程程序 */
for ( i = 1; i <1000; i ++ )
printf("This is child process\n");
}
else {
/* 父进程程序*/
for ( i = 1; i <1000; i ++ )
printf("This is process process\n");
}
}

  程序运行后,你就能看到屏幕上交替出现子进程与父进程各打印出的一千条信息了。如果程序还在运行中,你用ps命令就能看到系统中有两个它在运行了。
  那么调用这个fork函数时发生了什么呢?一个程序一调用fork函数,系统就为一个新的进程准备了前述三个段,首先,系统让新的进程与旧的进程使用同一个代码段,因为它们的程序还是相同的,对于数据段和堆栈段,系统则复制一份给新的进程,这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。而如果两个进程要共享什么数据的话,就要使用另一套函数(shmget,shmat,shmdt等)来操作。现在,已经是两个进程了,对于父进程,fork函数返回了子程序的进程号,而对于子程序,fork函数则返回零,这样,对于程序,只要判断fork函数的返回值,就知道自己是处于父进程还是子进程中。
  读者也许会问,如果一个大程序在运行中,它的数据段和堆栈都很大,一次fork就要复制一次,那么fork的系统开销不是很大吗?其实UNIX自有其解决的办法,大家知道,一般CPU都是以“页”为单位分配空间的,象INTEL的CPU,其一页在通常情况下是4K字节大小,而无论是数据段还是堆栈段都是由许多“页”构成的,fork函数复制这两个段,只是“逻辑”上的,并非“物理”上的,也就是说,实际执行fork时,物理空间上两个进程的数据段和堆栈段都还是共享着的,当有一个进程写了某个数据时,这时两个进程之间的数据才有了区别,系统就将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到最小。
  一个小幽默:下面演示一个足以"搞死"Linux的小程序,其源代码非常简单:

void main()
{
for(;;) fork();
}

  这个程序什么也不做,就是死循环地fork,其结果是程序不断产生进程,而这些进程又不断产生新的进程,很快,系统的进程就满了,系统就被这么多不断产生的进程"撑死了"。用不着是root,任何人运行上述程序都足以让系统死掉。哈哈,但这不是Linux不安全的理由,因为只要系统管理员足够聪明,他(或她)就可以预先给每个用户设置可运行的最大进程数,这样,只要不是root,任何能运行的进程数也许不足系统总的能运行和进程数的十分之一,这样,系统管理员就能对付上述恶意的程序了。





我只想知道我理解得对不对。
回复

使用道具 举报

 楼主| 发表于 2003-5-6 22:35:43 | 显示全部楼层
我没编过程序,刚才第一次用VI,GCC。fork()函数也是刚认识的,也是我认识的LINUX里的第一个函数。
上面这题是一个朋友叫我帮看的,是同济大学1999硕士入学数据库与操作系统试题,我就帮他弄了。
我的理解是:编译没出错,运行会有四个输出,说明fork()函数运行成功,产生了一个进程。
我的问题是:进程应该是同时运行的啊,所以会有16个可能的结果。
但我编译运行得出的却只有两个结果。所以我在怀疑我的想法。到底会有几个可能的结果?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2025-2-25 01:03 , Processed in 0.089193 second(s), 15 queries .

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表