Chinaunix首页 | 论坛 | 博客
  • 博客访问: 986284
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-11-26 17:55:36

8.3 fork function

Fork创建子进程。

Fork后,两个进程的data, stack, heap互相独立,而且采用了copy-on-write的方法,即,fork后,起初,2者共享data, stack, heap区域,所以,如果子进程调用exec去执行别的程序了,那么就加载别的程序就行了,也就是说没有必要将父进程的data, stack, heap拷贝一份给子进程。如果2者一旦有人写某个page,那么该page的内容就首先由父进程copy给子进程,然后再去写。注意,父子进程的代码段是共享的。

父子进程之间处理共享文件的方式:

1.      父子进程之间共享的是打开的文件,即他们有相同的文件descriptors。共享相同的file table entries。由于file table entries里面带有file offset,因此位移也是共享的。

2.      Socket也是共享的,所以一般父进程作为server当接受了一个从client发来的连接请求后,即得到了一个新的socket,然后就fork出一个子进程,让子进程只负责管理那个新的socket,关闭最开始的socket,而父进程关闭新的socket,依旧只关心老的socket

3.      还有一种方式就是父子之间采用同步机制,轮流读写操作。

Fork操作后,父子执行相同的代码段。如下有个有趣的例子,讲述的是实用line-buffered标准输出和采用full buffered标准输出,并使用了fork,同一个程序产生的不同的结果:

Figure 8.1. Example of fork function
#include "apue.h"
 
int     glob = 6;       /* external variable in initialized data */
char    buf[] = "a write to stdout\n";
 
int
main(void)
{
    int       var;      /* automatic variable on the stack */
    pid_t     pid;
 
    var = 88;
    if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
        err_sys("write error");
    printf("before fork\n");    /* we don't flush stdout */
 
    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) {      /* child */
        glob++;                 /* modify variables */
        var++;
    } else {
        sleep(2);               /* parent */
    }
 
    printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
    exit(0);
}

运行结果:

$ ./a.out
a write to stdout
before fork
pid = 430, glob = 7, var = 89      child's variables were changed
pid = 429, glob = 6, var = 88      parent's copy was not changed
$ ./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

 

解释:

1.  标准输出是有缓冲的,即printfbuffered i/o,那么他会在一定的时候才会真正的写到STDOUT上。在写给STDOUT之前,standard library有自己的buffer缓冲着,而是line buffer还是full buffer模式就产生了不同的影响

2.  System call 是无缓冲的,即write是无缓冲的,即write调用后就会立即体现到STDOUT上。

3.由于write是无缓冲得,所以就直接输出了。

4.当程序没有重定向时,标准输出流对应的是terminal 那么标准输出流默认采用line buffered i/o,当遇到写\n换行符时才会将数据真正写到STDOUT_FILENO。在fork之前,我们写了printf(“before fork \n”),遇到了换行,所以“before fork”也写了出去。此时标准输出的缓冲已经空了。然后才进行的fork。然后呢父子进程各自输出各自的数据。

5.当我们的程序被重定向到普通文件后,标准输出就成了默认的full buffered模式,那么,write调用直接输出是没有疑问的,它不经过标准输出的缓冲。而printf操作虽然收到了一行数据,但是它并没有将标准输出的缓冲flush出去,因为输出的缓冲还没有满。然后fork出两个进程,此时2个进程拥有相同的内容的标准库的缓冲,等各自携入各自的数据后,当程序退出时各自flush并关闭各自的输出流,那么“before fork”相当于执行了2遍。所以输出2遍。

 

多数情况下,进程新建一个子进程然后调用exec去执行一个程序,所以为了简化两个操作,产生了一个spawn调用,它将forkexec合并为一个操作了。

 

子进程除了继承父进程的文件,还继承了如下内容:

Besides the open files, there are numerous other properties of the parent that are inherited by the child:

·         Real user ID, real group ID, effective user ID, effective group ID

·         Supplementary group IDs

·         Process group ID

·         Session ID

·         Controlling terminal

·         The set-user-ID and set-group-ID flags

·         Current working directory

·         Root directory

·         File mode creation mask

·         Signal mask and dispositions

·         The close-on-exec flag for any open file descriptors

·         Environment

·         Attached shared memory segments

·         Memory mappings

·         Resource limits

The differences between the parent and child are

·         The return value from fork

·         The process IDs are different

·         The two processes have different parent process IDs: the parent process ID of the child is the parent; the parent process ID of the parent doesn't change

·         The child's tms_utime, tms_stime, tms_cutime, and tms_cstime values are set to 0

·         File locks set by the parent are not inherited by the child

·         Pending alarms are cleared for the child

·         The set of pending signals for the child is set to the empty set

阅读(575) | 评论(0) | 转发(0) |
0

上一篇:8.2 process identifiers

下一篇:8.4 vfork function

给主人留下些什么吧!~~