操作系统第三次作业
3.4 使用图3.24所示的程序,说明LINE A可能输出什么。
答:会输出5,在控制回到父进程的时候,子进程会copy父进程的值并更新。
3.5下面设计的优点和缺点分别是什么?系统层次和用户层次都要考虑。
a.同步和异步通信
所谓同步通信,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。
按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等)。
但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。
最常见的例子就是SendMessage。
该函数发送一个消息给某个窗口,在对方处
理完消息之前,这个函数不返回。
当对方处理完毕以后,该函数才把消息处理函数所返回的LRESULT值返回给调用者。
所以由以上可以看出,在系统层次,同步通信会因为等待反馈信息而一直占用内存和系统资源,这是它的缺点所在;但是对于对于用户来说,同步通信保证了用户之间的同时同步性,确保了用户体验。
异步通信的概念和同步相对。
当一个异步过程调用发出后,调用者不能立刻得到结果。
实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
以CAsycSocket类为例(注意,CSocket从CAsyncSocket派生,但是起功能已经由异步转化为同步),当一个客户端通过调用Connect函数发出一个连接请求后,调用者线程立刻可以朝下运行。
当连接真正建立起来以后,socket底层会发送一个消息通知该对象。
所以在系统层面,使用异步通信的优点是可以使系统尽可能快的高效率进行和不同的对象进行通信;但是对于用户来说,在发出信息之后不能立刻得到结果,甚至有可能因为某种错误的发生而不能得到结果,影响用户体验。
b.自动和显式缓冲
自动缓冲包括有限容量和无限容量的消息系统。
在有限容量情况下,队列的长度为有限的n;因此,最多只能有n个消息驻留其中,如果在发送新消息时队列未满,那么该消息可以放在队列中,且发送者可以继续执行而不必等待。
不过,线路容量有限。
如果线路满,必须阻塞发送者知道队列中的空间可用为止。
对于无限容量来说,队列
长度可以无限,因此,不管有多少消息都可以在其中等待,从不阻塞发送者。
所以对用户来说,采用自动缓冲可以流畅的发送信息而不用担心被阻塞而造成的卡顿情况,但是对于系统来说,这样做会消耗或浪费大量的系统资源和内存空间。
采用显式缓冲可能使用户在发送消息时被阻塞而等待一段时间,但是这样只会使用一小部分内存空间,避免了系统资源的浪费。
c.复制传送和引用传送
复制发送不允许接收者改变参数的状态,所以保证了参数的不可更改性,这样对系统来说可以保持通信传输之间的一致性,但是对用户来说不能改变参数的状态会造成一些不便。
与此相比,引用发送是允许的。
引用发送允许的优点之一是它允许程序员写一个分布式版本的一个集中的应用程序。
d.固定大小和可变大小消息
由进程发送的消息可以是定长的或变长的。
如果只能发送定长消息,那么系统级的实现十分简单。
不过,这一限制确实的编程任务更加困难。
相反地,变长消息要求更复杂的系统级实现,但是编程任务变得简单。
这是贯穿整个操作系统设计的一种常见的这种问题。
3.16 Fibonacci 序列是一组数: 0, 1, 1, 2, 3, 5, 8,…,通常它可以表示
为:
fib.0= 0
fib.1= 1
fib.n=fib.n-1 +fib.n-2
使用系统调用fork()编写一个 C 程序,它在其子程序中生成Fibonacci 序列,序列的号码将在命令行中提供。
例如,如果提供的是5 ,Fibonacci 序列中的前5 个数将由于进程输出。
由于父进程和子进程都有它们自己的数据副本,对于进程而言,输出序列是必要的o 退出程序前,父进程调用wait()调用来等待子进程结束。
执行必要的错误检查以保证不会接受命令行传递来的负数号码。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc, char* argv[])
{
pid_t pid;
int i;
int f0,f1.f2;
f0 = 0;
f1 = 1;
int(argv[1] < 0)
{
fprintf(stderr,"requet a nun-negative number");
}
pid = fork();
if(pid < 0)
{
fprintf(stderr,"fork failed");
exit(-1);
}
else if(pid==0)
{
printf("argv[1] = %d\n",atoi(argv[1]));
printf("0 1 ");
for(i=2; i<=atoi(argv[1]);i++)
{
f2=f0+f1;
f0 = f1;
f1 = f2;
printf("%d ",f2);
}
printf("\nchild process completed\n");
}
else
{
wait(NULL);
printf("parent process exited");
}
return 0;
}。