fork函数小结

来源:互联网 发布:html js添加class 编辑:程序博客网 时间:2024/06/01 18:53

在Unix系统中,只有一个系统调用可以用来创建新进程:fork。

由fork创建的新进程被称为子进程。fork函数被调用一次,但返回2次。2次返回的区别是子进程的返回值是0,而父进程的返回值是新创建的额子进程的进程ID。
子进程和父进程继续执行fork调用之后的指令。子进程是父进程的副本。例如,子进程获得父进程数据空间、堆和栈的副本。注意,这是子进程所拥有的副本。父进程和子进程并不共享这些存储空间。

例如

#include<unistd.h>#include<stdio.h>#include<errno.h>#include<stdlib.h>#include<string.h>int main(){    int n=0;;    pid_t pid;    if((pid=fork())<0)    {        fprintf(stderr,"fork error:[%s]\n",strerror(errno));        exit(1);    }    else if(pid>0)      //父进程    {             sleep(2);       //为了保证子进程先执行,父进程睡眠2s    }    else                //子进程    {        n++;    }    printf("pid = %ld, n = %d\n",(long)getpid(),n);    exit(0);}

运行的结果为
这里写图片描述

可以看到,子进程的变量值改变了,父进程的变量值没有改变

文件共享

fork的一个特性是父进程的所有打开文件描述符都被复制到子进程中。我们说“复制”是因为对每个文件描述符来说,就好像执行了dup函数。父进程和子进程每个相同的打开描述符共享同一个文件表项。
这里写图片描述

重要的一点是, 父进程和子进程共享同一个文件偏移量。考虑下述情况: 一个进程fork了一个子进程, 然后等待子进程终止. 假定,作为普通处理的一部分, 父进程和子进程都向标准输出进行写操作。如果父进程的标准输出己重定向(很可能是由shell实现的), 那么子进程写到该标准输出时, 它将更新与父进程共亭的该文件的偏移量. 在这个例子中, 当父进程等待子进程时, 子进程写到标准输出:而在子进程终止后, 父进程也写到标准输出上, 并且知道其输出会追加到子进程所写数据之后。如果父进程和子进程不共享同一文件偏移量,要实现这种形式的交互就要困难得多。

#include<unistd.h>#include<stdio.h>#include<sys/wait.h>#include<errno.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#define MAXLEN 1024int main(){    int n;    int fd[2];    pid_t pid;    char buf[MAXLEN];    int file_fd;    file_fd=open("test.txt",O_RDWR|O_CREAT|O_TRUNC);   //打开一个文件    if((pid=fork())<0)    {        fprintf(stderr,"fork error:[%s]\n",strerror(errno));        exit(1);    }    else if(pid>0)    {        sleep(2);        write(file_fd,"parent:hello world\n",19);   //父进程写入    }    else    {        write(file_fd,"child:hello world\n",18);    //子进程写入    }    exit(0);}

运行结果

这里写图片描述

可以看到,父进程的写入的数据在子进程写入的数据之后。