fork函数和vfork函数
2020-05-13 16:00:41来源:博客园 阅读 ()
fork函数和vfork函数
fork函数
在诸多应用中,创建多个进程是任务分解时行之有效的方法。例如,某一网络服务器进程可在侦听客户端请求的同时,为处理每---请求而创建一新的子进程,与此同时,服务器进程会继续侦听更多的客户端连接请求。以此类手法分解任务,通常会简化应用程序的设计,同时提高了系统的并发性。(即,可同时处理更多的任务或请求。)
1 #include <sys/types.h> 2 #include <unistd.h> 3 pid_t fork(void); //返回:子进程中为0,父进程中为子进程I D,出错为-1
执行调用后将存在两个进程,且每个进程都会从fork()的返回处继续执行。
这两个进程将执行相同的程序文本段,但却各自拥有不同的栈段、数据段以及堆段拷贝。子进程的栈、数据以及栈段开始时是对父进程内存相应各部分的完全复制。执行fork()之后,每个进程均可修改各自的栈数据、以及堆段中的变量,而并不影响另一进程。
注:现在很多的实现并不做一个父进程数据段和堆的完全拷贝,因为在fork之后经常跟随着exec。作为替代,使用了在写时复制( Copy-On-Write, COW)的技术。这些区域由父、子进程共享,而且内核将它们的存取许可权改变为只读的。(详见Linux|Unix系统编程手册)
程序代码则可通过fork()的返回值来区分父、子进程。在父进程中,fork()将 返回新创建子进程的进程ID。
当无法创建子进程时,fork()将返回-1。 失败的原因可能在于,进程数量要么超出了系统针对此真实用户(realuser ID)在进程数量.上所施加的限制(RLIMIT_ NPROC),要么是触及允许该系统创建的最大进程数这一系统级上限。
一般来说,在fork之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法。如果要求父、子进程之间相互同步,则要求某种形式的进程间通信。
例子:
1 #include<stdio.h> 2 #include<sys/types.h> 3 #include<unistd.h> 4 #include<sys/wait.h> 5 #include<stdlib.h> 6 #include<errno.h> 7 #include<string.h> 8 9 int main() 10 { 11 pid_t childPid; 12 /* if((childPid=fork())==-1) 13 { 14 printf("Fork error %s\n",strerror(errno)); 15 exit(1); 16 } 17 else 18 if(childPid==0) 19 { 20 printf("I am the child : %d\n",getpid()); 21 exit(0); 22 } 23 else 24 { 25 printf("I am the father : %d\n",getpid()); 26 exit(0); 27 } */ 28 switch(childPid=fork()){ 29 case -1: 30 printf("Fork error %s\n",strerror(errno)); 31 exit(1); 32 case 0: 33 printf("I am the child : %d\n",getpid()); 34 exit(0); 35 default: 36 printf("I am the father : %d\n",getpid()); 37 exit(0); 38 39 } 40 return 0; 41 }View Code
结果:
vfork函数
类似于fork(), vfork()可以为调用进程创建一个新的子进程。然而,vfork()是为子进程立即执行exec()的程序而专门设计的。
#include <sys/types.h> #include <unistd.h> pid_t vfork(void); //返回:子进程中为0,父进程中为子进程I D,出错为-1
vfork()与fork()一样都创建一个子进程, 但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用 exec (或exit),于是也就不会存访该地址空间。不过在子进程调用 exec或exit之前,它在父进程的空间中运行。vfork()和fork()之间的另一个区别是:vfork()保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)
例子:
1 #include<stdio.h> 2 #include<sys/types.h> 3 #include<unistd.h> 4 #include<sys/wait.h> 5 #include<stdlib.h> 6 #include<errno.h> 7 #include<string.h> 8 9 int main() 10 { 11 pid_t childPid; 12 if((childPid=vfork())==-1) 13 { 14 printf("Fork error %s\n",strerror(errno)); 15 exit(1); 16 } 17 else 18 if(childPid==0) //子进程 19 { 20 sleep(1); //子进程睡眠一秒 21 printf("I am the child : %d\n",getpid()); 22 exit(0); 23 } 24 else //父进程 25 { 26 printf("I am the father : %d\n",getpid()); 27 exit(0); 28 } 29 /* switch(childPid=vfork()){ 30 case -1: 31 printf("Fork error %s\n",strerror(errno)); 32 exit(1); 33 case 0: //子进程 34 sleep(1); //子进程睡眠一秒 35 printf("I am the child : %d\n",getpid()); 36 exit(0); 37 default: //父进程 38 printf("I am the father : %d\n",getpid()); 39 exit(0); 40 41 } */ 42 return 0; 43 }vfork_pid.c
结果:
运行程序时可以看到,程序会停一秒然后分别打印出父子进程的ID.也就是说子进程进来就阻塞一秒,但也没有先去运行父进程,而是让子进程运行完了之后才运行父进程。
参考资料
Linux/Unix系统编程手册
Unix环境高级编程
Linux程序设计
原文链接:https://www.cnblogs.com/mumu597/p/12880710.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- shell脚本之八:函数知识与实践 2020-04-28
- linux--access函数与mkdir函数 2020-04-26
- dup与dup2函数 2020-03-20
- Bash脚本编程学习笔记08:函数 2020-01-17
- Shell(五):函数 2019-12-16
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash