进程创建就是一个正在运行的进程去创建出另外一个进程,而这个正在运行的进程被称为父进程,被父进程创建出的进程称为子进程。
在linux中可以通过在父进程中调用系统调用函数fork()或者vfork函数创建出一个子进程,下面是两个系统调用函数的原型:
#include <sys/type.h>
#include <unistd.h>
pid_t fork(void);
返回:子进程中返回0,父进程中返回子进程的进程ID,出错返回-1
pid_t vfork(void);
返回:子进程中返回0,父进程中返回子进程的进程ID,出错返回-1
对于fork创建的新进程称为子进程,该函数被调用一次,但返回2次。两次返回的区别是:在子进程中的返回值是0,而在父进程中的返回值则是新进程的进程ID。
在一个进程调用fork成功之后会有两个进程在运行,一个父进程在运行,一个子进程在运行。至于创建的子进程与父进程哪个先运行根据操作系统的调度,并且子进程复制(linux采用写时复制的技术(copy-on-write)。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候)父进程的虚拟内存空间(代码段、数据段、堆、栈)。
对于vfork创建子进程,但是子进程先运行,且不复制父进程的虚拟内存空间,而时直接共享父进程的虚拟地址空间。vfork也是被调用一次返回2个返回值,父子进程返回值是父进程创建的子进程的进程ID,子进程中的返回值是0。进程创建一般采用fork系统调用,这样创建的子进程与父进程是抢占式的运行方式,哪一个进程先获得CPU的运行权限,这个进行就先运行,而不采取让子进程先运行的方式。
接下来,通过两个实例介绍一下fork函数的使用。
process_fork.c
/*
* process_fork.c
*
* Created on: 2016-11-11
* Author: river
*/
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("pid:%d\n", getpid());
pid_t pid;
pid = fork();//创建子进程
//在fork之后会运行2个进程(父进程、子进程)
if(pid < 0)
{
perror("fork error");
}
else if(pid > 0)
{//父进程(在父进程中fork返回的是子进程的pid)
//父进程执行的代码...
printf("I am parent process pid is %d, ppid is %d, fork return is %d\n",
getpid(), getppid(), pid);
}
else
{//子进程(在子进程中fork返回的是0)
//子进程执行的代码...
printf("I am child process pid is %d, ppid is %d, fork return is %d\n",
getpid(), getppid(), pid);
}
printf("pid: %d\n", getpid());//父子进程都执行
sleep(1);//睡眠1s使得父子进程可以交替运行
exit(0);
}
运行结果:
pid:4344
I am parent process pid is 4344, ppid is 3376, fork return is 4345
pid: 4344
I am child process pid is 4345, ppid is 4344, fork return is 0
pid: 4345
process_fork2.c
/*
* process_fork2.c
*
* Created on: 2016-11-13
* Author: river
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("current pid: %d\n", getpid());
pid_t pid = fork();
if(pid < 0)
{
perror("fork error");
}
else if(pid > 0)
{//父进程
int i;
for(i = 0; i < 10; i++)
{
printf("This is parent process pid is: %d\n", getpid());
sleep(1);
}
}
else
{//子进程
int i;
for(i = 0; i < 10; i++)
{
printf("This is child process pid is: %d\n", getpid());
sleep(1);
}
}
exit(0);
}
输出结果:
current pid: 5677
This is parent process pid is: 5677
This is child process pid is: 5678
This is parent process pid is: 5677
This is child process pid is: 5678
This is parent process pid is: 5677
This is child process pid is: 5678
This is child process pid is: 5678
This is parent process pid is: 5677
This is parent process pid is: 5677
This is child process pid is: 5678
This is child process pid is: 5678
This is parent process pid is: 5677
This is parent process pid is: 5677
This is child process pid is: 5678
This is parent process pid is: 5677
This is child process pid is: 5678
This is parent process pid is: 5677
This is child process pid is: 5678
This is child process pid is: 5678
This is parent process pid is: 5677

本文介绍了在Linux系统中如何使用fork()和vfork()系统调用创建子进程的过程。通过两个实例详细展示了进程创建的方法及子进程与父进程的运行机制。
397

被折叠的 条评论
为什么被折叠?



