测试:CODE:./test
实验体会:
通过本次实验,我们理解了面向操作命令的接口 Shell,学会了简单的 shell 编码,理解了操作系统调用的运行机制,掌握了创建系统调用的方法。本次实验通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这让我们初步了解了操作系统的生成过程。
实验二:进程管理实验 实验目的
1) 加深对进程概念的理解,明确进程和程序的区别。 2) 进一步认识并发执行的实质。
3) 分析进程争用资源的现象,学习解决进程互斥的方法。 4) 了解Linux系统中进程通信的基本原理。
进程是操作系统中最重要的概念,贯穿始终,也是学习现代操作系统的关键。通过本次实验,要求理解进程的实质和进程管理的机制。在Linux系统下实现进程从创建到终止的全过程,从中体会进程的创建过程、父进程和子进程的关系、进程状态的变化、进程之间的同步机制、进程调度的原理和以信号和管道为代表的进程间通信方式的实现。
实验内容
1) 编制实现软中断通信的程序
1.实验原理:
使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上发出的中断信号(即按delete键),当父进程接收到这两个软中断的某一个后,父进程用系统调用kill()向两个子进程分别发出整数值为16和17软中断信号,子进程获得对应软中断信号,然后分别输出下列信息后终止:
Child process 1 is killed by parent !!
Child process 2 is killed by parent !!
父进程调用wait()函数等待两个子进程终止后,输入以下信息,结束进程执行: Parent process is killed!!
2.实验源码:
#include
int pid1, pid2;
// 定义两个进程号变量
// 或者 signal(14,stop);
signal(3,stop); while((pid1 = fork( )) == -1); if(pid1 > 0) {
// 若创建子进程1不成功,则空循环 // 子进程创建成功,pid1为进程号
while((pid2 = fork( )) == -1); // 创建子进程2 if(pid2 > 0) { wait_flag = 1;
sleep(5); kill(pid1,16);
kill(pid2,17); wait(0); wait(0);
// 父进程等待5秒
// 杀死进程1
// 杀死进程2
// 等待第1个子进程1结束的信号 // 等待第2个子进程2结束的信号
printf(\ exit(0); } else {
wait_flag = 1; signal(17,stop);
// 父进程结束
// 等待进程2被杀死的中断号17
printf(\
exit(0);
}
} else {
wait_flag = 1; signal(16,stop);
// 等待进程1被杀死的中断号16
printf(\ exit(0);
} }
void stop( ) {
wait_flag = 0; }
3.程序运行结果:
或者多次运行,并且Delete键后,会出现如下结果:
4.简要原因分析:
上述结果中“Child process 1 is killed by parent !!” 和“Child process 2 is killed by parent !!”相继出现,当运行几次后,谁在前谁在后是随机的。这是因为:从进程调度的角度看,子进程被创建后处于就绪态。此时,父进程和子进程作为两个独立的进程,共享同一个代码段,分别参加调度、执行,直至进程结束。但是谁会先被调度程序选中执行,则与系统的调度策
略和系统当前的资源状态有关,是不确定的。因此,谁先从fork()函数中返回继续执行后面的语句也是不确定的。
2) 编制实现进程的管道通信的程序
1.实验原理:
使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话: Child process 1 is sending a message! Child process 2 is sending a message!
而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。
要求:父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。 2.程序源码:
#include
int pid1,pid2; // 定义两个进程变量 main( ) { int fd[2];
char OutPipe[100],InPipe[100]; // 定义两个字符数组
pipe(fd); while((pid1 = fork( )) == -1);
// 创建管道
// 如果进程1创建不成功,则空循环
if(pid1 == 0) { // 如果子进程1创建成功,pid1为进程号 lockf(fd[1],1,0);
// 锁定管道
sprintf(OutPipe,\Child process 1 is sending message!\\n\ // 给Outpipe赋值
write(fd[1],OutPipe,50);
sleep(5);
lockf(fd[1],0,0);
// 等待读进程读出数据 // 解除管道的锁定
// 向管道写入数据
exit(0); } else {
// 结束进程1
while((pid2 = fork()) == -1); if(pid2 == 0) {
lockf(fd[1],1,0);
// 若进程2创建不成功,则空循环
sprintf(OutPipe,\ write(fd[1],OutPipe,50); sleep(5);
lockf(fd[1],0,0); exit(0); } else {
wait(0); read(fd[0],InPipe,50); printf(\ wait(0); read(fd[0],InPipe,50); printf(\
exit(0);
} } }
3.运行结果截图:
// 父进程结束
// 等待子进程1 结束
// 从管道中读出数据
// 显示读出的数据
// 等待子进程2 结束
4.简要分析
管道,是指用于连接一个读进程和一个写进程,以实现它们之间信息的共享文件又称pipe文件。向管道(共享文件)提供输入的发送进程(即写进程),以字符流形式将大量的数据送入管道;而接收管道输送的接收进程(读进程),可以从管道中接收数据。