- 实验目的:
- 加深对进程概念的理解,明确进程和程序的区别。进一步认识并发执行的实质。
- 了解信号处理
- 认识进程间通信(IPC):进程间共享内存
- 实现shell:了解程序运行
1.实验一:进程的创建实验
程序一:
int main(void) {
int pid1 = fork();
printf("**1**\n");
int psid2 = fork();
printf("**2**\n");
if (pid1 == 0) {
int pid3 = fork();
printf("**3**\n");
} else {
printf("**4**\n");
}
return 0;
}
程序执行过程:
Line 6: 创建子进程1,即主进程与子进程1共存。
Line 7: 主进程输出“**1**”
。
Line 8:主进程继续创建子进程2,即主进程与两个子进程共存。
Line 9:主进程输出“**2**”
。
Line 14:主进程输出“**4**”
。
Line 7:子进程输出“**1**”
。
Line 8:子进程1创建子进程3,即三个子进程共存。
Line 9:子进程1输出“**2**”
。
Line 11:子进程1继续创建子进程4,即四个子进程共存。
Line 12:子进程1输出“**3**”
。
Line 9 :子进程2输出“**2**”
。
Line 14: 由于子进程2的父进程中pid1不为0,所以输出“**4**”
。
Line 9 : 子进程3输出“**2**”
。
Line 11:由于子进程3的父进程中pid1为0,所以创建子进程5。
Line 12:子进程3输出“**3**”
。
Line 12:子进程4输出“**3**”
。
Line 12: 子进程5输出“**3**”
。
输出结果:
**1**
**1**
**2**
**4**
**2**
**3**
**3**
**2**
**3**
**2**
**4**
**3**
输出结果的顺序与我的分析不同,原因是进程的执行是抢占式的,哪个进程抢占到了CPU,哪个进程就执行输出。但是输出的内容是一样的:2个“**1**”
,4个“**2**”
,4个“**3**”
,2个“**4**”
.
截图:
其实也可以画进程树来猜测输出结果:
程序二:
int main(void) {
pid_t pid;
if ((pid = fork()) == -1) { // 生成子进程1
printf("Error");
exit(-1);
}
if (pid != 0) {
pid_t pid1;
if ((pid1 = fork()) == -1) { // 生成子进程2
printf("Error");
exit(-1);
}
if (pid1 != 0) {
printf("a");
} else {
printf("b");
exit(0);
}
} else {
printf("c");
exit(0);
}
wait(0); // 等待子进程执行完毕
wait(0);
exit(0); // 主进程退出
}
该程序是主进程与两个子进程并发执行的过程。其中主程序输出a,子程序分别输出b、c。
输出结果:
cba
截图:
也可用类似于程序一中的进程树进行分析。
程序三:
int main(void) {
int a = 0;
pid_t pid;
if ((pid=fork())) {
a = 1;
}
for (int i = 0; i < 2; i++) {
printf("X");
}
if (pid == 0) {
printf("%d\n", a);
}
return 0;
}
程序的执行过程:
Line 8: 调用fork()生成子进程1,即父进程与子进程1共存;
Line 9: 父进程执行a = 1;
Line 11: 父进程执行两次循环,输出两个“X”;
Line 11: 子进程执行两次循环,输出两个“X”;
Line 15: 子进程输出a的值,即“0”
输出结果:
XXXX0
即输出四个X,一个0
截图:
也可用类似于程序一中的进程树进行分析。
程序四:
int main(void) {
int a = 0;
pid_t pid[2];
for (int i = 0; i < 2; i++) {
if ((pid[i]=fork())) {
a = 1;
}