一、单项选择题 19. 以下程序会打印出______个“-”。
for(int i=0;i<2;i++)
{
fork();
printf("-\n");
}
A B C D
C
[解析] 要弄明白本题的输出结果,就必须弄懂fork函数的运行机理。
fork()函数是Unix操作系统下以自身进程创建子进程的系统调用,通过系统调用创建一个与原来进程几乎完全相同的进程,一个是子进程,一个是父进程,该子进程拥有与父进程相同的堆栈空间,也就是说,两个进程可以做完全相同的事,可以理解为它们俩是双胞胎兄弟,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。在fork()函数的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令、变量值、程序调用栈、环境变量和缓冲区等。
fork()函数的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,且可能有三种不同的返回值:
1)在父进程中,fork()函数返回新创建子进程的进程ID。
2)在子进程中,fork()函数返回0。
3)如果出现错误,fork()函数返回一个负值。
所以,可以通过fork()函数的返回值来判断当前进程是子进程还是父进程。
当printf函数遇到了换行符“\n”,或EOF,或缓冲区满,或文件描述符关闭,或主动flush,或程序退出时,就会把数据刷出缓冲区。对于本题而言,printf("-\n")中有换行,因此会马上输出而不会缓存,所以,此时会打印6个“-”。
执行过程如图所示。
程序执行过程
如果将上述代码中的printf("-\n")语句改为printf("-")语句,结果就大相径庭了。由于printf("-")语句有缓冲区,所以,prinft("-")把字符“-”放到了缓存中,并没有真正地输出,在执行fork()函数的时候,缓存被复制到子进程空间,所以,输出“-”的个数就变为8个,比6个多2个。所以,选项C正确。
所以,本题的答案为C。
如果将printf()和fork()这两句顺序调换会怎样呢?
此时,对于printf("-")的情况,由于“-”在缓冲区中没有实际输出,所以,printf()函数和fork()函数的顺序调换没有影响,都是8个。
对于printf("-\n")的情况,因为有实际输出调换顺序printf()在前,所以,fork()函数在后输出为3个“-”。
20. 有如下代码:
int main()
{
fork()||fork();
}
以上程序创建的进程个数是______。
A B C D
B
[解析] 逻辑或运算符||具有短路功能,即如果第一个表达式的值为真,那么运算符||后面的表达式将不再执行,如果第一个表达式的返回值为假,就会继续判断右边的表达式的值是否为真。
fork()函数的作用是创建一个新的进程,一个现有进程可以调用fork()函数创建一个新进程。由函数fork()创建的新进程被称为子进程(Child Process)。fork()函数被调用一次但会返回两次,两次返回的唯一区别是子进程中返回0而父进程中返回子进程ID。子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。
本题中,fork()||fork()语句的执行流程为,在父进程中,左边的fork()函数返回一个非零值(子进程ID),根据逻辑或运算符||的短路原则,前面的表达式为真时,后面的表达式不再执行。
在子进程中,左边fork()函数的返回值为0,因此会继续执行后面的fork()函数,又创建一个新的进程,因此一共创建了3个进程,分别为main进程->子进程->子进程。
如图所示,相同形状的为同一进程,共有三种进程。
进程创建过程
所以,本题的答案为B。
三、论述题 1. Internet物理地址和IP地址转换采用什么协议?
2. 数字签名和加密的区别是什么?
数字签名使用发送方的密钥对,发送方使用自己的私有密钥进行加密,而接收方只需要发送方的公开密钥就可以解密,是一种一对多的关系,只要持有发送方公开密钥的人都可以验证数字签名的正确性。 加密是一种以密码方式发送信息的方法,指的是如下这样一个过程:发送方利用接收方的公钥对要发送的明文进行加密,接收方利用自己的私钥进行解密,其中公钥和私钥是相对的,任何一个作为公钥,则另一个就为私钥。所以,加密使用的是接收方的密钥对,这是一种多对一的关系,任何知道接收方公开密钥的人都可以向接收方发送加密信息,只有唯一拥有接收方私有密钥的人才能对信息解密。 另外,数字签名采用的是非对称密钥加密算法,它能保证发送信息的完整性、身份认证和不可否认性,而数字加密采用的是对称密钥加密算法和非对称密钥加密算法相结合的方法。
3. IP地址的编码分为哪几个部分?
IP地址由两部分组成:网络号和主机号。要想区别哪些是网络位,哪些是主机位,需要与“子网掩码”执行按位与(&)操作。
4. 动态链接库和静态链接库的优缺点是什么?
所谓库指的是把一些常用函数的目标文件打包在一起,提供相应函数的接口,便于程序员使用。具体而言,它是别人写好的、现有的、成熟的、可以复用的代码,只需要知道其接口如何定义,便可以简单方便地使用。而静态链接库(Static Link Library,LIB)与动态链接库(Dynamic Link Library,DLL)都是共享代码的方式。以下将分别对这两种方式进行介绍与对比分析。 动态链接库:在Windows操作系统中动态链接库的后缀为.dll,其中有3个最重要的DLL,分别是Ketaael32.dll、User32.dll和GDI32.dll。Linux操作系统中动态链接库的后缀为.so。动态链接库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单地引用,因此,它的代码体积较小。动态链接库的使用方式分为两种:一种是静态加载,即在应用程序启动时加载;一种是动态加载,即该动态链接库在被使用时才被应用程序加载。 通常,动态链接库的优点很多,主要有以下几点: 1)更加节省内存,并减少页面交换。多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可。 2)开发模块好,可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分,具有很强的可维护性和可扩展性。例如,有一个大型网络游戏,如果把整个数百MB甚至数GB游戏的代码都放在一个应用程序里,未来的修改工作将会非常费时,而如果把不同功能的代码分别放在数个动态链接库中,则无须重新生成或安装整个程序就可以应用更新,但前提是要求设计者对功能划分得比较好。 3)不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数。 动态链接库的缺点如下: 1)不能解决引用计数。 2)使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败。 3)可能造成DLL地狱。DLL地狱(DLL Hell)指的是在微软的Windows系统中,因为动态链接库的版本或兼容性的问题而造成程序无法正常运行的情况。 静态链接库:函数和数据被编译进一个二进制文件(通常扩展名为.lib)。静态链接库的代码在编译过程中已经被载入可执行程序,因此,它的体积较大。在使用静态链接库的情况下,编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.exe文件)。静态链接库作为代码的一部分,在编译时被链接。 静态链接库的优点有以下两点:①代码的装载速度快,因为编译时它只会把需要的那部分内容链接进去,所以,其执行速度比动态链接库略快;②只需保证在开发者的计算机中有正确的.lib文件即可,在以二进制形式发布程序时不需考虑在用户的计算机上.lib文件是否存在及版本问题,可避免DLL地狱等问题。 当然,静态链接库的缺点也是很明显的:如果一个静态链接库被多个应用程序使用,则会被装载多次,浪费内存。
5. 实时操作系统的基本特性是什么?
实时操作系统(Real-Time Operating System,RTOS)是指当外界事件或数据产生时,能够接受并以足够快地速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统做出快速响应,调度一切可利用的资源完成实时任务,并控制所有实时任务协调一致运行的操作系统。 通过上述定义可知,实时操作系统具有以下基本特性:响应及时,处理事务的能力较强、速度较快,可靠性高。