分类: LINUX
2008-10-28 13:18:38
|
fork将子进程ID返回给父进程的理由是:因为一个进程的子进程可以多于一个,所以没有一个函数使一个进程可以获得其所有子进程的进程ID。
fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID (进程ID 0总是由交换进程使用,所以一个子进程的进程ID不可能为0 )。
父、子进程并不共享这些存储空间部分。如果正文段是只读的,则父、子进程共享正文段。
程序清单1 fork的函数实例
|
这段代码注意点:
1.fork之后是父进程先执行还是子进程先执行是不确定的,程序在父进程中调用sleep,作用就是让子进程先执行,但这不是一定的。
2.sizeof(buf)为什么要减一,因为sizeof计算的包括终止null字节的缓冲区长度,如果用strlen计算就不包括这个null字节。两者还有个区别,strlen需进行一次函数调用,而sizeof编译时计算缓冲区长度。
3.缓冲方式的问题,先看下面的执行结果:
$ a . o u t
a write to stdout
before fork
pid = 430, glob = 7, var = 89 子 进 程 的变量值改变了
pid = 429, glob = 6, var = 88 父 进 程 的变量值没有改变
$ a.out > temp.out
$ cat temp.out
a write to stdout
before fork
pid = 432, glob = 7, var = 89
before fork
pid = 431, glob = 6, var = 88
标准输出连到终端设备时是行缓冲,所以printf“before fork”后由换行符冲洗
标准输出重定向一个文件时是全缓冲,所以printf“before fork”一直留在缓冲区中,子进程复制时把这部分缓冲区内容也复制过去了,所以父子俩进程都会输出before fork。
这里为了比较还特地用write函数,write不是标准IO函数,所以是没有缓冲的,所以两种情况下,write都只是输出一次。
vfork:与fork差不多,就是在复制方面和fork很不一样,vfork在调用exec或者exit之前,他是在父空间中运行的。可以通过下面这个代码理解。
程序清单2 vfork的函数实例
|
从这段代码得到的信息:
1、由于想测试vfork是直接在父进程中运行的,所以我比书上多加一个else,测试证明这段代码是不会运行到这里的。
2、由于vfork实在父进程中运行,所以子进程一定是在父进程之前运行。
3、而且也由于vfork是在父进程中运行,所以子进程改变数据,会影响父进程中的输出,输出如下:
$ a . o u t
before vfork
pid = 607, glob = 7, var = 89
3、这里子进程中用_exit(0),是因为exit(0)会冲洗标准io流,而且有些系统会关闭标准io流,所以为了父进程中最后的printf能够正常输出,所以用_exit(0)。