本文研究的主要是Linux进程函数fork(),vfork(),execX()的相关内容,具体介绍如下。
函数fork()
fork函数:创建一个新进程
1、fork()成功后,将为子进程申请PCB和用户内存空间。
2、子进程会复制父进程用户空间的所有数据(代码段、数据段、BSS、堆、栈),文件描述符。
3、复制父亲进程PCB中绝大多数信息。
4、虽然子进程复制了文件描述符,而对于文件描述符相关的文件表项(struct file结构),则采用共享的方式。
一个实例:
#include <unistd.h> //fork fuction
#include <fcntl.h> //file operator
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h> //exit fuction
#include <string.h>
int main() {
pid_t pid;
int i=1;
int status;
char *ch1="hello",*ch2="world",*ch3="IN";
int fd;
if ((fd=open("fork.txt",O_RDWR|O_CREAT,0644))==-1) {
perror("not open");
exit(EXIT_FAILURE);
}
if (write(fd,ch1,strlen(ch1))==-1) { //write in fork.txt
perror("not write");
exit(EXIT_FAILURE);
}
if ((pid=fork())==-1) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if(pid==0) { //son process
int i=2; //change i
printf("child:i=%dn",i);
if (write(fd,ch2,strlen(ch2))==-1)
perror("child write");
return 0;
}
else {
sleep(1);
printf("parent:i=%dn",i);
if (write(fd,ch3,strlen(ch3))==-1)
perror("child write");
wait(&status);
return 0;
}
}
运行:
[root@localhost linux]# gcc -o fork fork.c [root@localhost linux]# ./fork child:i=2 parent:i=1
可以看到在子进程中改变了i的值,然而父进程i仍为1,所以说子进程和父进程有自己的用户空间。而打开所创建的fork.txt可以得到hellowordIN,父子进程共同对一个文件操作写入的数据是不交叉覆盖的,说明父子进程共享文件偏移,一次共享文件表项。
函数vfork()
与fork()函数不同,vfork()函数在创建进程是并不复制父进程的地址空间,而是在必要的时候才申请新的存储空间,因此使得vfork()更有效率。
特别注意的是vfork()是共享父进程的代码以数据段。
一个例子:
#include <unistd.h> //fork fuction
#include <fcntl.h> //file operator
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h> //exit fuction
#include <string.h>
int i=10;
int main() {
pid_t pid;
if ((pid=fork())==-1) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if(pid==0) { //son process
i++;
printf("child:i=%dn",i);
_exit(0);
}
else {
sleep(1);
printf("parent:i=%dn",i);
return 0;
}
}
注意:上面的代码中回收子进程用的是_exit(0),如果用return 0;的话它会回收用户空间,因此在父进程调用的时候会出现段错误。
下面是调用输出结果:








