进程特性
父进程和子进程并发运行
- 父进程创建子进程后,父子进程都处于运行状态中
- 两个进程的输出结果是交织在一起的
两者的代码段内容相同
- 父进程从fork()返回处执行,fork()返回为子进程的PID
- 子进程从fork()返回处执行,fork()返回0
fork的实现细节
- 操作系统为子进程创建PCB(进程控制块),把父进程的大部分属性复制到子进程的PCB中
- 不复制PID属性,父子进程拥有不同的PID
- 操作系统为子进程创建地址空间,把父进程的代码和数据复制到子进程的地址空间中
隔离特性
- 进程的地址空间是互相隔离的,每个进程拥有自己的地址空间,进程仅能访问自己的地址空间
- 如果出现非法内存访问,仅仅当前进程受到影响
全局变量 - 全局变量存在于两个地址空间中,并非被两个进程共享
父进程和子进程访问的是自己的全局变量,互相不影响
并发例子
#include <stdio.h>
#include <unistd.h>
void child()
{
int i;
for (i = 0; i < 3; i++)
puts("child");
sleep(1);
}
}
void parent()
{
int i;
for (i = 0; i < 3; i++)
puts("parent");
sleep(1);
}
}
int main()
{
pid_t pid;
pid = fork();
if (pid == 0)
child();
else
parent();
return 0;
}
输出:
$ cc concurr.c
$ ./a.out
parent
child
parent
child
parent
child
$ _
隔离例子
#include <stdio.h>
#include <unistd.h>
int global = 0;
void child()
{
for (int i = 0; i < 3; i++) {
global++;
printf("In child, global = %d\n", global);
sleep(1);
}
}
void parent()
{
for (int i = 0; i < 3; i++) {
global++;
printf("In parent, global = %d\n", global);
sleep(1);
}
}
int main()
{
pid_t pid;
pid = fork();
if (pid == 0)
child();
else
parent();
return 0;
}
输出:
$ cc isolate.c
$ ./a.out
In parent, global = 1
In child, global = 1
In parent, global = 2
In child, global = 2
In parent, global = 3
In child, global = 3
$ _