找回密码
 注册
楼主: bitstream

关于fork()函数的问题

[复制链接]
发表于 2003-5-6 23:37:37 | 显示全部楼层
change this code to :
[code:1]
int main(void)
{
        int x=5;
        printf("%d\n", getpid());
        if(fork())
        {
                x+=30;
                printf("%d:%d\n",getpid(), x);
        }
        else
                printf("%d:%d\n",getpid(),x);
        printf("%d:%d\n",getpid(),x);
        return 0;
}
[/code:1]
then u can see that it first print out the process id. after call fork. the current process(parent process) will execute x+=30, print 35 print 35. the child process will execute the print 5 print 5.
after fork.
if child get cpu, it will print 5, 5. so that is why 5 5 35 35 is possible.
if parent get cpu, it will print 35 35, so that is why 35 35 5 5 is also possible
i also see 35 5 5 35.
the 5 35 5 35, 5 35 35 5, 35 5 35 5, should also be possible. but i never see it. so it should depends on system implementation.

not 16, at most 6.
回复

使用道具 举报

发表于 2003-5-7 01:16:41 | 显示全部楼层
i guess the reason that why not have output like 5 35 5.. is because
linux have time slice 100ms. two printf is much less than this. so linux will not schedule other process once child process get cpu. so that two 5 5 must be print out together.

but for a pure os course, u can have all possibe print out. i am doing some experiements and will report later
回复

使用道具 举报

发表于 2003-5-7 01:47:11 | 显示全部楼层
i use two code to explain the reason, welcome for comments.
code 1 is the fork one.
[code:1]
#include <stdio.h>

int main(void)
{
        int x=5;
        if(fork())
        {
                x+=30;
                printf("%d\n", x);
        }
        else
                printf("%d\n",x);
        printf("%d\n",x);

        return 0;
}
[/code:1]
code 2 is a simple partent process only
[code:1]
#include <stdio.h>

int main(void)
{
        int x=5;
        x+=30;
        printf("%d\n", x);
        printf("%d\n", x);
}
[/code:1]
here is the output from code 1 with 'strace ./code1'
======================
execve("./t2", ["./t2"], [/* 48 vars */]) = 0
uname({sys="Linux", node="dragonfly", ...}) = 0
brk(0)                                  = 0x8049534
open("/etc/ld.so.preload", O_RDONLY)    = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
close(3)                                = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=84744, ...}) = 0
mmap2(NULL, 84744, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40014000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\20_\1\000"..., 1024) = 1024
fstat64(3, {st_mode=S_IFREG|0755, st_size=1422891, ...}) = 0
mmap2(NULL, 1244260, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40029000
mprotect(0x40150000, 35940, PROT_NONE)  = 0
mmap2(0x40150000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x127) = 0x40150000
mmap2(0x40155000, 15460, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40155000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40159000
munmap(0x40014000, 84744)               = 0
fork()                                  = 18126
5
5
--- SIGCHLD (Child exited) ---
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000
write(1, "35\n", 335
)                     = 3
write(1, "35\n", 335
)                     = 3
munmap(0x40014000, 4096)                = 0
_exit(0)                                = ?
=================================
here is the output from code 2 with strace ./code2
=================================
execve("./t", ["./t"], [/* 48 vars */]) = 0
uname({sys="Linux", node="dragonfly", ...}) = 0
brk(0)                                  = 0x80494e0
open("/etc/ld.so.preload", O_RDONLY)    = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
close(3)                                = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=84744, ...}) = 0
mmap2(NULL, 84744, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40014000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\20_\1\000"..., 1024) = 1024
fstat64(3, {st_mode=S_IFREG|0755, st_size=1422891, ...}) = 0
mmap2(NULL, 1244260, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40029000
mprotect(0x40150000, 35940, PROT_NONE)  = 0
mmap2(0x40150000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x127) = 0x40150000
mmap2(0x40155000, 15460, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40155000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40159000
munmap(0x40014000, 84744)               = 0
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000
write(1, "35\n", 335
)                     = 3
write(1, "35\n", 335
)                     = 3
munmap(0x40014000, 4096)                = 0
_exit(3)                                = ?
==========================================
回复

使用道具 举报

发表于 2003-5-7 01:53:20 | 显示全部楼层
this is the output with  strace -c ./code1
=============================
execve("./t2", ["./t2"], [/* 48 vars */]) = 0
5
5
35
35
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
60.21    0.000174          87         2           write
10.73    0.000031          31         1           fork
  9.00    0.000026           4         6           mmap2
  5.54    0.000016           5         3           open
  3.81    0.000011           3         4           fstat64
  3.46    0.000010           5         2           munmap
  2.42    0.000007           2         3           close
  1.73    0.000005           5         1           mprotect
  1.38    0.000004           4         1           read
  1.04    0.000003           3         1           uname
  0.69    0.000002           2         1           brk
------ ----------- ----------- --------- --------- ----------------
100.00    0.000289                    25           total
=======================================
here is the output with strace -c ./code2
=====================================
execve("./t", ["./t"], [/* 48 vars */]) = 0
35
35
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
70.69    0.000234         117         2           write
  8.46    0.000028           5         6           mmap2
  5.74    0.000019           6         3           open
  3.63    0.000012           6         2           munmap
  3.32    0.000011           3         4           fstat64
  3.02    0.000010           3         3           close
  1.51    0.000005           5         1           read
  1.51    0.000005           5         1           mprotect
  1.21    0.000004           4         1           uname
  0.91    0.000003           3         1           brk
------ ----------- ----------- --------- --------- ----------------
100.00    0.000331                    24           total
=====================================


so we can find that one fork() and one printf() statement will use that time slice up, that is why it is possible to printf a 35 then print 5 5. but once the child process get cpu, it printf 5 and still have cpu time available, it can still do the sceond printf operation.
回复

使用道具 举报

发表于 2003-5-7 02:00:06 | 显示全部楼层
the cost results reported from strace is not so accurate. but the reason should be the same.
回复

使用道具 举报

发表于 2003-5-7 04:24:18 | 显示全部楼层
太长了, 拒绝翻译.  
回复

使用道具 举报

发表于 2003-5-7 04:28:32 | 显示全部楼层
[quote:7025e01e06="CNOOC"]太长了, 拒绝翻译.  [/quote]
most are code and screen display. need not be translated.
btw, do u have interest on kernel code reading? if so, i wonder if u can help me to translate some comments from me to chinese. axin and i want to setup a special site for kernel code reading. i believe most of people want to see chinese comments. so...
回复

使用道具 举报

发表于 2003-5-7 04:49:18 | 显示全部楼层
我是很想参加的, 但有两个因素制约了我:
第一是我对LINUX才刚刚接触, 玩的也不是很多, 所以在一些地方可能会翻译的有出入.
第二, 你知道我的情况的, 对中文的术语和名词都不清楚. 就算我知道那段话的英文意思, 未必能找出约定成俗或恰当的中文来描述它.
我在最近可能无法参加到那么光荣的行动中去, 希望以后能够实现. 最后还是要祝你们的工作顺利, 快点释译出来, 这样子我们就轻松多了.      
回复

使用道具 举报

发表于 2003-5-7 08:36:19 | 显示全部楼层
ic. thx anyway.
回复

使用道具 举报

发表于 2003-5-7 10:32:17 | 显示全部楼层
fork失败,还会有一种输出
回复

使用道具 举报

发表于 2003-5-7 10:45:34 | 显示全部楼层
[code:1]
#include <stdio.h>
#include <unistd.h>

int main()
{
  int x;
  for(;;)
    {
      x=5;
      if(fork())
        {
          x+=30;
          printf("%d\t",x);
        }
      else
        printf("%d\t",x);
      printf("%d\n",x);
    }
  return 0;
}
[/code:1]

刚开始正常,最后fork失败时居然只打印35
郁闷!
回复

使用道具 举报

发表于 2003-5-7 10:48:10 | 显示全部楼层
不对!
应该是父进程和子进程的打印重叠了!最后打印的全部是子进程的输出
回复

使用道具 举报

发表于 2003-5-7 10:48:44 | 显示全部楼层
hehe, of course, u are right.
回复

使用道具 举报

发表于 2003-5-7 10:52:40 | 显示全部楼层
[quote:0ff7227a37="吴文官"]不对!
应该是父进程和子进程的打印重叠了!最后打印的全部是子进程的输出[/quote]

no, even fork is fail, the parent still runs. but there are some many child process keep printing 5. so u feel that only see child process. but i bet parent process is still there. u can check the pid.
回复

使用道具 举报

发表于 2003-5-7 20:37:58 | 显示全部楼层
有什么问题么?我想这是一个进程轮转的问题 理想情况下会发生的任意抢占cpu的情况 但实际中对于这样的小程序总是一个进程基本上跑完了才轮到下一个
如果你把两个printf中间加上足够长的sleep 你就会看到其他的几种情况了
回复

使用道具 举报

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

本版积分规则

GMT+8, 2025-2-25 07:47 , Processed in 0.039413 second(s), 12 queries .

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

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