一、fork函数

要创建一个进程,最基本的系统调用是fork,系统调用fork用于派生一个进程,函数原型如下: pid_t fork(void)  若成功,父进程中返回子进程ID,子进程中返回0,若出错返回-1;fork()系统调用的作用是复制一个进程,当一个进程调用它,完成个就出现两个几乎一摸一样的进程,新进程是子进程,原来的进程是父进程。子进程是父进程的一个拷贝,子进程从父进程那里得到了代码段和数据段的拷贝。Fork函数调用一次,但返回两次,两次返回的区别是子进程的返回值是0,父进程的返回值是子进程返回值的进程ID。Fork返回后,子进程和父进程都从调用fork函数的下一条语句开始执行。

程序一是fork调用:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 0;
pid_t pid; /*此时仅有一个进程*/
pid = fork(); /*此时已经有两个进程在同时运行*/
if(pid < 0)
{
printf("error in fork!");
exit(1); /* fork出错退出*/
}
else if(pid==0)
printf("I am the child process, the count is %d, my process ID is %d\n",count,getpid());
else
printf("I am the parent process, the count is %d, my process ID is %d\n",++count,getpid());
return 0;
}

必须了解一个概念:在语句pid = fork();之前,只有一个进程在执行这段代码,该语句之后,就变成两个进程在执行了,且二者代码部分完全相同,将要执行的下一条语句都是 if(pid<0)。

Fork函数的奇妙之处是仅仅被调用一次,却返回了两次,可能有三种取值:

1,在父进程中,fork返回新创建子进程的ID

2,在子进程中,fork返回0

3,出现错误时,返回负值

二、linux下另一个创建进程的方式是vfork,原型如下:pid_t vfork(void);

若成功,父进程中返回子进程ID,子进程中返回0,若出错返回-1;fork与vfork是有区别的,fork要拷贝父进程的数据段,而vfork不需要完全拷贝父进程的数据段,在子进程没有调用exec或者exit函数之前,子进程会与父进程共享数据段。在fork中子进程与父进程的执行顺序不确定,而在vfork中,子进程先运行,父进程挂起,直到子进程调用了exec或者exit函数,父进程才被执行。

程序二说明了vfork创建后父子进程是共享数据段的。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 1;
int child;
printf("Before create son, the father's count is:%d\n", count); /*创建进程之前*/
child = vfork(); /*此时已经有两个进程在同时运行*/
if(child < 0)
{
printf("error in vfork!");
exit(1); /* fork出错退出*/
}
if(child==0) /*子进程*/
{
printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
exit(1);
}
else /*父进程*/
{
printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child);
}
return 0;
}

在子进程中修改了count值,在父进程中输出count时是子进程修改后的值,这说明父进程和子进程是共享count,也就是二者是共享内存区的。

程序三说明由vfork创造出来的子进程是会导致父进程挂起,直到子进程执行xec或者exit函数才会唤醒父进程

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 1;
int child;
printf("Before create son, the father's count is:%d\n", count); /*创建进程之前*/
if(!(child = vfork()))
{ /*这里是子进程执行区*/
int i;
for(i = 0; i < 100; i++)
{
printf("This is son, The i is: %d\n", i);
if(i == 70)
exit(1);
}
printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
exit(1); /*子进程退出*/
}
else
{ /*父进程执行区*/
printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child);
}
return 0;
}

从中可以看书父进程是在等子进程执行完毕后才开始执行的。

最新文章

  1. 记录SQL Server2008日志文件损坏的恢复过程
  2. pythonchallenge 解谜 Level 5
  3. Android声音播放实例代码
  4. [转]在windows环境中使用varnish
  5. Mybatis3.x与Spring4.x整合(转)
  6. 一台独立的服务器是可以可以建立多个网站的,一个ip地址,一个端口
  7. MVVM架构~knockoutjs系列之为validation.js扩展minLength和maxLength
  8. Opensource开源精神
  9. Why we have to use epsg:900913 in OpenLayers
  10. Java Post 数据请求和接收
  11. C#委托的回调机制
  12. hdu 4876 ZCC loves cards(暴力)
  13. window.showModalDialog()的简单用法
  14. MySQL 5.7 安装完成后,立即要调整的性能选项
  15. Android-Dalvik指令集
  16. poj 1012——Toseph
  17. bzoj2237[NCPC2009]Flight Planning 结论题?
  18. DCOM EXCE权限配置问题
  19. jQuery插件之----缓冲运动
  20. left join on +多条件与where区别

热门文章

  1. Apache htaccess 重写假设文件存在!
  2. 关于智普 - 千人免费学|Python培训|国内最权威python培训|html5
  3. HDU1176:免费馅饼(DP)
  4. JMS的样例
  5. Linux下的softlink和hardlink(转)
  6. mysql left join,right join,inner join用法分析
  7. spring-security3.2.5实现中国式安全管理(转)
  8. CentOS 7没有ifconfig命令处理
  9. 组件-------(一)redis系列--安装部署redis+实现redis分布式缓存 java+Spring+redis
  10. zoj3640(概率dp)