赞
踩
fork是UNIX系统中产生新进程的唯一办法
fork的作用是复制当前进程,生成子进程,子进程从fork的位置继续执行。fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中 各返回一次。fork就像一个叉子,把顺序执行的程序变成了两个分支,并发执行。
fork调用失败返回-1,子进程中fork的返回值是0,而父进程中fork的 返回值则是子进程的id
在父进程调用fork以后要用变量记录返回值即子进程的pid,否则就找不到子进程了,而子进程可以通过getppid找到父进程。
#include <stdio.h> #include <unistd.h> int main() { pid_t pid; pid = fork(); if(-1 == pid){ perror("fork"); exit(1); } if(0 == pid){ printf("i am child, %d\n",getpid()); } else if(pid >0){ printf("i am parent, %d\n",getpid()); } }
i am child, 5909
[root@192 ~]# i am parent, 5910
一般情况下,子进程和父进程共享地址空间,当有一方需要对数据内容进行修改的话,对各自拷贝一份副本(拷贝修改数据的页表)。由于代码段肯定是不会改变的,所以代码段一直享用同一块地址空间。
int g_val = 0; int main() { pid_t pid = fork(); if(pid == 0){ //子进程 g_val = 100; printf("child val=%d, &val = %d\n", g_val, &g_val); } else{ sleep(3); printf("parent val=%d, &val = %d\n", g_val, &g_val); } }
child val=100, &val = 134518596
parent val=0, &val = 134518596
运行结果说明:
int main()
{
int r = 10;
pid_t pid = vfork();
if(pid == 0){
sleep(1);
r = 1;
printf("child %d\n", r);
exit(0);
}
else{
printf("parent %d\n", r);
}
}
child 1
parent 1
原进程pcb中信息是通过三级映射将虚拟空间映射在内存空间,exec删除进程pcb信息,从磁盘把新代码调入内存,再形成pcb里的映射。
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
调用成功就执行新代码,调用失败返回-1.
例参考博客文章,简易shell。
调用exec后,原来打开的文件描述符仍然是打开的。
解释:在Unix/Linux中,父进程调用fork出一个子进程,父进程打开的文件描述符会被复制到子进程中,这样子进程通过父进程复制过来的文件描述符和父进程共享打开文件的文件表项。
而exec则会继承子进程的文件描述符,也就是说在子进程中打开的文件流都可以在exec后的新进程中使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。