Unix Fork()函数

 

unix fork()

#include <sys/types.h>

#include<unistd.h>

pid_t fork(void);

返回值:

  负数:如果出错,则fork()返回-1,此时没有创建新的进程。最初的进程仍然运行。

  零:在子进程中,fork()返回0

  正数:在父进程中,fork()返回正的子进程的PID  

实例:

   pid_t child;

  if((child =fork())<0)

  //错误处理

  else if(child ==0)

  //新进程执行代码

  else

  //最初父进程执行代码

说明:

  fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0,

  这是因为父进程可能存在很多过子进程,所以必须通过这个返回的子进程ID来跟踪子进程,

  而子进程只有一个父进程,他的ID可以通过getppid取得。

point:

   在语句pid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的代码部分完全相同。

   

注解:

The new process created by fork iscalled the child process. This function is called once but returnstwice. The only difference in the returns is that the return valuein the child is 0, whereas the return value in the parent is theprocess ID of the new child. The reason the child's process ID isreturned to the parent is that a process can have more than onechild, and there is no function that allows a process to gain theprocess IDs of its children. The reason fork returns 0 to the childis that a process can have only a single parent, and the child canalways call getppid to gain the process ID of its parent. (ProcessID 0 is reserved for use by the kernel, so it's not possible for 0to be the process ID of a child.)

  Both the child and theparent continue executing with the instruction that follows thecall to fork. The child is a copy of the parent. Forexample, the child gets a copy of the parent's data space,heap, and stack. Note that this is a copy for the child;the parent and the child do not share these portions ofmemory. The parent and the child share the text segment(Section 7.6).

 

fork()不仅创建出与父进程代码相同的子进程,而且父进程在fork执行点的所有上下文场景也被自动复制到子进程中,包括:全局和局部变量、打开的文件句柄、共享内存、消息等同步对象。



   pid_t fork(void) :create a new process

   1>.Fork 被调用一次,但返回两次,两次返回的唯一的区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。将子进程ID返回给父进程的理由是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。子进程返回0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID。

  2>.子进程和父进程继续执行fork之后的指令。子进程是父进程的复制品。例如,子进程获得父进程数据空间、堆和栈的复制品。注意,这是子进程所拥有的拷贝。父、子进程并不共享这些存储空间部分。如果正文段是只读的,则父、子进程共享正文段,现在很多的实现并不做一个父进程数据段和堆的完全拷贝,因为在fork之后经常跟随着exec。作为替代,使用了在写时复制( Copy-On-Write, COW)的技术。这些区域由父、子进程共享,而且内核将它们的存取许可权改变为只读的。如果有进程试图修改这些区域,则内核为有关部分,典型的是虚存系统中的“页”,做一个拷贝 

  3>.一般来说,在fork之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法。如果要求父、子进程之间相互同步,则要求某种形式的进程间通信 

  4>.文件共享:在fork之后处理文件描述符有两种常见的情况:
  a.父进程等待子进程完成。在这种情况下,父进程无需对其描述符做任何处理。当子进程终止后,它曾进行过读、写操作的任一共享描述符的文件位移量已做了相应更新。
        b. 
父、子进程各自执行不同的程序段。在这种情况下,在f o r k之后,父、子进程各自关闭它们不需使用的文件描述符,并且不干扰对方使用的文件描述符。

E:使f o r k失败的两个主要原因是:(1)系统中已经有了太多的进程(通常意味着某个方面出了问题),或者(2)该实际用户I D的进程总数超过了系统限制。回忆表2 - 7,其中CHILD_MAX规定了每个实际用户I D在任一时刻可具有的最大进程数。 

5>.f o r k有两种用法:
a. 
一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待委托者的服务请求。当这种请求到达时,父进程调用 fork,使子进程处理此请求。父进程则继续等待下一个服务请求。
b. 
一个进程要执行一个不同的程序。这对 shell是常见的情况。在这种情况下,子进程在从fork返回后立即调用exec。某些操作系统将a中的两个操作(fork之后执行exec)组合成一个,并称其为spawn。UNIX将这两个操作分开,因为在很多场合需要单独使用fork,其后并不跟随exec。另外,将这两个操作分开,使得子进程在fork和exec之间可以更改自己的属性。例如I/O重新定向、用户ID、信号排列等。


要搞清楚fork的执行过程,就必须先讲清楚操作系统中的“进程(process)”概念。一个进程,主要包含三个元素:

o. 一个可以执行的程序;
o. 和该进程相关联的全部数据(包括变量,内存空间,缓冲区等等);
o. 程序的执行上下文(execution context)。

Unix操作系统使用 fork 系统调用

fork(2) 系统调用创建一个新进程。清单 2 显示了一个简单 C 代码片段中使用的 fork。

清单 2. 简单的 fork(2) 用法
          
 

  
  
  1. sunbox$ cat fork1.c  
  2. #include <unistd.h> 
  3. #include <stdio.h> 
  4. int main (void) {  
  5. pid_t p; /* fork returns type pid_t */  
  6. p = fork();  
  7. printf("fork returned %d\n", p);}  
  8. sunbox$ gcc fork1.c -o fork1  
  9. sunbox$ ./fork1  
  10. fork returned 0  
  11. fork returned 698 


 
fork1.c 中的代码不过就是发出 fork 调用,并通过一个 printf 调用来打印整数结果。Unix操作系统虽然只发出了一个调用,但是打印了两次输出。这是因为在 fork 调用中创建了一个新进程。现在有两个单独的进程在从该调用返回结果。这通常被描述为“调用一次,返回两次”。

fork 返回的值非常有趣。其中一个返回 0;另一个返回一个非零值。获得 0 的进程称为子进程,非零结果属于Unix操作系统原始进程,即父进程。您将使用返回值来确定哪个是父进程,哪个是子进程。由于两个进程都在同一空间中继续运行,唯一有实际意义的区别是从 fork 返回的值。

0 和非零返回值的基本原理在于,子进程始终可以通过 getppid(2) 调用来找出其父进程是谁,但是父进程要找出它的所有子进程却很困难。因此,要告诉父进程关于其新的子进程的信息,而子进程可在需要时查找其父进程。

对Unix操作系统中的父进程的基本知识的介绍就到这里。希望对大家对Unix操作系统的学习有所帮助。



当进程调用一种e x e c函数时,该进程完全由新程序代换,而新程序则从其m a i n函数开始执行。
因为调用e x e c并不创建新进程,所以前后的进程I D并未改变。e x e c只是用另一个新程序替换了
当前进程的正文、数据、堆和栈段。

v f o r k用于创建一个新进程,而该新进程的目的是e x e c一个新程序
它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用e x e c (或e x i t ),于
是也就不会存访该地址空间。不过在子进程调用e x e c或e x i t之前,它在父进程的空间中运行
v f o r k保证子进程先运行,在它调用e x e c或e x i t之后父进
程才可能被调度运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会
导致死锁。)

摘至《UNIX环境高级编程》


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值