简述fork函数的用法

1、fork函数的定义

     头文件:

# include
# include
 
    函数原型:
 
   pid_t fork( void);
(pid_t 是一个 宏定义,其实质是int 被定义在# include< sys/types.h>中)
返回值: 若成功调用一次则返回两个值,子进程返回0, 父进程返回子进程ID;否则,出错返回-1
 
    函数说明:
 
   一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
   子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述 存储空间的“副本”,这意味着父子进程间不共享这些存储空间。
UNIX将复制父进程的 地址空间内容给子进程,因此,子进程有了独立的地址空间。在不同的UNIX (Like)系统下,我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的实现。所以在移植代码的时候我们不应该对此作出任何的假设。
 
2、函数特点和进阶
 
  从上面的函数说明里面可以看到fork函数会有几个特点:
(1)返回两个值不同的值代表不同的意思。
(2)子进程获得父进程的数据空间和堆栈等资源并且独立的。
 
   举个简单的例子如下:
          #include  
          #include  
          int main()
     { 
         pid_t fpid;//fpid表示fork函数返回的值  
         fpid = fork(); 
       if (fpid < 0) 
          printf("error in fork!"); 
       else if (fpid == 0) 
           printf("I am the child process, my process id is %d\n", getpid()); 
       else 
          printf("I am the parent process, my process id is %d\n", getpid()); 
       return 0; 
    }
 
  这个例子最中的结果为:
  I am the parent process, my process id is 11594
  I am the child process, my process id is 11595
 
可以明显看出来个不同进程的不同打印出来了,具体打印什么要看linux系统的调度算法了。main函数在fork之后变成了两个进程。可以各自干各自的事情。
 
第二个例子:
int main()

    pid_t fpid;//fpid表示fork函数返回的值 
    printf("fork!");  
    fpid = fork(); 
    if (fpid < 0) 
        printf("error in fork!"); 
    else if (fpid == 0) 
        printf("I am the child process, my process id is %d\n", getpid()); 
    else 
        printf("I am the parent process, my process id is %d\n", getpid()); 
    return 0; 
}
 
这个例子比第一个例子多了一个printf(fork!");
这个例子的输出结果为:
fork!I am the parent process, my process id is 11852
fork!I am the child process, my process id is 11853
 
 上面的例子你会看到一个现象:子进程继承了父进程的数据空间,导致子进程和父进程都输出了fork!。但是如下如果加上\n
#include  
#include  
int main()

    pid_t fpid;//fpid表示fork函数返回的值 
    printf("fork!\n"); 
    fpid = fork(); 
    if (fpid < 0) 
        printf("error in fork!"); 
    else if (fpid == 0) 
        printf("I am the child process, my process id is %d\n", getpid()); 
    else 
        printf("I am the parent process, my process id is %d\n", getpid()); 
    return 0; 
输出结果:
fork!
I am the parent process, my process id is 11950
I am the child process, my process id is 11951
 
此时结果只有一个fork!打印了,这是为什么呢?这是因为prinf的行数据缓冲问题,在没有加\n的时候数据是在缓冲区中,没有直接输出到stdout,当加上\n的时候数据会刷新输出到stdout。所以出现了上面的情况。
 
再列举一个简单的例子:
#include  
#include   
int main ()  
{  
    pid_t fpid; //fpid表示fork函数返回的值 
    int count=0; 
    fpid=fork();  
    if (fpid < 0)  
        printf("error in fork!\n");  
    else if (fpid == 0) { 
        printf("i am the child process, my process id is %d\n",getpid());  
        printf("child\n");
        count++; 
  } 
    else { 
       printf("i am the parent process, my process id is %d\n",getpid());  
        printf("parent\n"); 
        count++; 
    } 
    printf("%s, %d, %d\n", __FUNCTION__, __LINE__,count); 
    return 0; 
输出结果为:
i am the parent process, my process id is 12163
parent
main, 92, 1
i am the child process, my process id is 12164
child
main, 92, 1
 
这个例子清晰的看到count是子进程从父进程获取到的独立的栈数据,在输出的时候分别都是1,而不是2。
 
3、 fork出错可能有两种原因:
    1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
    2)系统内存不足,这时errno的值被设置为ENOMEM。
 
 
上述简单介绍fork函数的用法,后续继续讲解fork和vfork函数的区别。
 

你可能感兴趣的:(Linux应用)