软件学院2004级第一学期《一级实践》期末试题
学号 姓名 分数 注:所有答案必须写在答题纸上,否则无效。 一、 简答题(共50分)
1. 简述进程和线程的异同点。(5分)
进程:是程序的一次动态执行过程,它对应了从代码加载、执行到执行完毕的一个完整过程,也是进程本身从产生、发展至消亡的过程。
线程:比进程更小的执行单位。一个进程在执行过程中,为了同时完成多项操作,可以产生多个线程,形成多条执行线索。每个线程都有它自身的产生、存在和消亡的过程。
进程和线程都是操作系统的概念。
进程是系统进行资源分配和调度的一个独立的单位。
进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。 进城分为系统进程和用户进程
线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。
多进程环境中每一个进程既包括其所要执行的指令, 也包括执行指令所需的任何系统资源, 如CPU、内存空间、I/O端口等,不同进程所占用的系统资源相对独立;
线程是比进程单位更小的执行单位,多线程环境中每一个线程都隶属于某一进程,由进程触发执行,在系统资源的使用上,属于同一进程的所有线程共享该进程的系统资源;
与进程不同的是线程本身即没有入口,也没有出口,其自身也不能独立运行,它栖身于某个进程之中,由进程启动运行,完成其任务后,自动终止,也可以由进程使之强制终止。
2. 列举三种进程间的通信方式,并分别说明其应用场合。(5分)
无名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
1
高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。
有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
3. 简述设置C++虚拟继承的目的是什么?(3分)
虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。 虚继承的目的是令某个类作出声明,承诺愿意共享它的基类。其中,共享的基类子对象称为虚基类。在这种机制下,不论虚基类在继承体系中出现多少次,在派生类中都只包含唯一一个共享的虚基类子对象。
4. 简述C/C++堆和堆栈两种内存使用方式的异同。(4分)
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
栈内存:由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。若分配失败,则提示栈溢出错误。注意,const局部变量也储存在栈区内,栈区向地址减小的方向增长。
堆内存:程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,
2
地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则则导致内存泄露。
5. 简述传输层和应用层协议的主要功能,请各举两例并比较TCP和UDP
的异同。(5分)
传输层
这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在同一主机上对不同应用的数据流的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能。示例:TCP,UDP,SPX。 应用层
与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作的程序员也不关心OSI的第7层。但是,如果添加了一个传输文件的选项,那么字处理器的程序员就需要实现OSI的第7层。示例:TELNET,HTTP,FTP,NFS,SMTP等。
相同点:TCP和UDP都处于网络层(NETWORK LAYER)之上,都是传输层协议,功能都属于保证网络层数据的传输。双方的通信无论是用TCP还是DUP都是要开放端口的。
– TCP,向连接的通信协议。
? 使 TCP协议进 数据传输时,两个进程之间会建1个连接,数据以流的形式顺序传输。
– UDP,是无连接通信协议。
? 使 UDP协议进 数据传输时,两个进程之间 建 特定 的连接, 对数据到达的顺序进 检查。
6. 简述new和malloc的异同。(3分)
1、new 是c++中的操作符,malloc是c 中的一个函数
2、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数
3、内存泄漏对于malloc或者new都可以检查出来的,区别在于new可以指明是那个文件的那一行,而malloc没有这些信息。
4.new可以看成两个动作:1。分配内存(相当于malloc)2。引发构造函数。 new 是个操作符,和什么\有一样的地位. malloc是个分配内存的函数,供你调用的.
3
new是保留字,不需要头文件支持. malloc需要头文件库函数支持. new 建立的是一个对象, malloc分配的是一块内存.
new建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间
malloc分配的是一块内存区域,就用指针访问好了,而且还可以在里面移动指针. new可以认为是malloc加构造函数的执行。 new出来的指针是直接带类型信息的。 而malloc返回的都是void指针。
7. 简述进程(线程)间的同步和互斥的作用,请列举三种Winodws的同步
和互斥对象,并分别说明其应用场合。(5分)
线程同步与互斥:即当有一个线程在对内存进行操 作时,其他线程都不可以对这个内存地址进行操作, 直到该线程完成操作,其他线程才能对该内存地址 进行操作,而其他线程处于等待状态。
最常用的四种同步方式和机制:
– 临界区(CCriticalSection/CriticalSection)
通过对多线程的串行化来访问公共资源或一段代码, 速度快,适合控制数据访问。
– 事件(Cevent/Event)
事件:该机制允许一个线程在某种情况发生时,唤 醒另外一个线程的同步对象。
– 互斥量(Cmutex/Mutex)
互斥对象可 以在进程间使用,而临界区对象只能在同一进程的 各线程间使用。
– 信号量(Csemaphore/Semaphore) PV操作
8. 简述你所知道的const的各种用法。(5分)
(1)定义常量 (2)修饰函数的参数 (3)修饰函数的返回值 (4)修饰函数的定义体
9. 简述异质链表的特点,给出一种实现方法(包括节点增删操作函数)并
简要说明你采用这种实现方法的原因。(10分)
4
异质链表是指可以链表指针所指向的数据类型并不一致,比如一个链表中可以既存储整形数据,又可以存储浮点性的数据。在面向对象的语言中甚至就是可以指向不同的对象。
扩展性好,既可以链表元素既可以是类,也可以是某种类型的数据,操作过程简单。
由节点类模板的一系列实例构成的链表就可用于保存不同类型的值,构成一种异质链表。 类模板代码如下:
template
T value; N* next;
hetero_node(T const &v, N *n) : value(v), next(n) {} };
类模板hetero_node有两个模板参数,T定义节点所保存数据类型,而N则定义链表中下一个节点的类型。假设需要一个数据结构保存三个数据分别为int、char及std::string类型,则用hetero_node类模板可以构造出一个拥有三个节点分别保存以上三个数据的异质链表。具体构造方法如下所示: typedef hetero_node
typedef hetero_node
typedef hetero_node
// 忽略中间申请空间及赋值过程 p1->next = p0; p2->next = p1;
经过这样处理后,只需要保存p2就可以保存整个链表及其上的数据。而访问该链表上的数据也很简单,通过一系列的next找到相应指针后读取其所指value值即可,例如:
std::string s = p2->value; char c = p2->next->value; int i = p2->next->next->value;
5