fork函数,fork函数是什么
朋友们,你是否曾想过深入了解fork函数和fork函数是什么的内涵?在本文中,我将为你详细解析这两个话题,希望能给你带来全新的视角和思考。
计算机操作系统实验!fork()的意思
在linux中,只有一个函数可以创建子进程:fork。
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
由f o r k创建的新进程被称为子进程( child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程I D。将子进程I D返回给父进程的理由是:因为一个进程的子进程可以多于一个,所以没有一个函数使一个进程可以获得其所有子进程的进程I D。f o r k使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用g e t p p i d以获得其父进程的进程I D(进程ID 0总是由交换进程使用,所以一个子进程的进程I D不可能为0)。
子进程和父进程共享很多资源,除了打开文件之外,很多父进程的其他性质也由子进程继承:
•实际用户I D、实际组I D、有效用户I D、有效组I D。
•添加组I D。
•进程组I D。
•对话期I D。
•控制终端。
•设置-用户- I D标志和设置-组- I D标志。
•当前工作目录。
•根目录。
•文件方式创建屏蔽字。
•信号屏蔽和排列。
•对任一打开文件描述符的在执行时关闭标志。
•环境。
•连接的共享存储段。
•资源限制。
父、子进程之间的区别是:
• fork的返回值。
•进程I D。
•不同的父进程I D。
•子进程的t m s _ u t i m e, t m s _ s t i m e, t m s _ c u t i m e以及t m s _ u s t i m e设置为0。
•父进程设置的锁,子进程不继承。
•子进程的未决告警被清除。
•子进程的未决信号集设置为空集。
使f o r k失败的两个主要原因是:( a)系统中已经有了太多的进程(通常意味着某个方面出了问题),或者( b)该实际用户I D的进程总数超过了系统限制。回忆表2- 7,其中C H I L D _ M A X规定了每个实际用户I D在任一时刻可具有的最大进程数。
f o r k有两种用法:
(1)一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待委托者的服务请求。当这种请求到达时,父进程调用f o r k,使子进程处理此请求。父进程则继续等待下一个服务请求。
(2)一个进程要执行一个不同的程序。这对s h e l l是常见的情况。在这种情况下,子进程在从f o r k返回后立即调用e x e c。
我们从一个例子程序中可以看到fork函数的作用,子进程与父进程之间的资源共享。
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
int glob= 6;
char buf[]="a write to stdout\n";
int main()
{
int var;
pid_t pid;
var= 88;
fprintf(stderr,"%s", buf);
printf("before fork\n");
if(( pid= fork())< 0)
{
fprintf(stderr,"fork error\n");
}
else if(pid== 0)
{
glob++;
var++;
printf("child process\n");
printf("pid=%d, father pid=%d, glob=%d, var=%d\n", getpid(), getppid(), glob, var);
exit(0);
}
else
{
sleep(2);
printf("father process\n");
printf("pid=%d, father pid=%d, glob=%d, var=%d\n", getpid(), getppid(), glob, var);
}
return 0;
}
fork()问题
1.基础知识:
1)fork函数总是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。fork在子进程中的返回值是0,而在父进程中的返回值则是子进程的id。
2)子进程在创建的时候会复制父进程的当前状态(PCB信息相同,用户态代码和数据也相同)。
3)程序运行的结果基本上是父子进程交替打印,但这也不是一定的,取决于系统中其它进程的运行情况和内核的调度算法。
2.第一个fork:
子进程A被创建,之后从fork函数往下执行与父进程相同的代码,即后一个fork和printf会被父进程和子进程A分别执行一次:
父进程打印的pid1和pid2是两个子进程的pid,即结果的第一行:pid1:3411, pid2:3412
子进程A打印的pid1和pid2是这个fork在子进程A中的返回(0)和子进程A中调用fork返回的pid,即结果的第二行:pid1:0, pid2:3413
3.第二个fork:
这个fork会被父进程和子进程A都执行一遍。假设子进程B被主进程创建,子进程C被子进程A创建。子进程A也可以说是子进程C的父进程,为了避免混淆,我这里改叫主进程而不再使用父进程的概念。
子进程B的打印即结果的第三行:pid1:3411, pid2:0。其中,其中,pid1为复制的主进程的数据,pid2为该fork在子进程B中的返回。
子进程C的打印,即结果的最后一行:pid1:0, pid2:0。其中,pid1为复制的进程A的数据,pid2为该fork在子进程C内部的返回。
不能再多说,写得太多,我自己都快晕了。
关于fork()函数
fork函数是计算机程序设计中的分叉函数。返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。
fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。
函数原型
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之后是子进程先运行还是父进程先运行,这依赖于系统的实现。所以在移植代码的时候我们不应该对此作出任何的假设。
fork函数是什么
Fork:创建一个和当前进程映像一样的进程可以通过fork()系统调用:
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
成功调用fork()会创建一个新的进程,它几乎与调用fork()的进程一模一样,这两个进程都会继续运行。在子进程中,成功的fork()调用会返回0。在父进程中fork()返回子进程的pid。如果出现错误,fork()返回一个负值。
最常见的fork()用法是创建一个新的进程,然后使用exec()载入二进制映像,替换当前进程的映像。这种情况下,派生(fork)了新的进程,而这个子进程会执行一个新的二进制可执行文件的映像。这种“派生加执行”的方式是很常见的。
在早期的Unix系统中,创建进程比较原始。当调用fork时,内核会把所有的内部数据结构复制一份,复制进程的页表项,然后把父进程的地址空间中的内容逐页的复制到子进程的地址空间中。但从内核角度来说,逐页的复制方式是十分耗时的。现代的Unix系统采取了更多的优化,例如Linux,采用了写时复制的方法,而不是对父进程空间进程整体复制。
OK,关于fork函数和fork函数是什么的内容到此结束了,希望对大家有所帮助。