第八章课下测试
- C语言通过( BC )函数提供非本地跳转。
A .try ...catch
B .longjmp
C .setjmp
D .signal
这道题在书上P547,非本地跳转是C语言提供的一种用户级异常控制流形式。将控制直接从一个函数转移到另一个当前正在执行的函数,不需要经过正常的调用——返回程序。
- Linux信号处理说法正确的是( A B D E F )
A .可以用signal()处理信号
B .一个信号最多只能被接收一次
C .kill(1)用来杀死进程
D .kill(1)用来发送信号
E .可以通过键盘发送信号
F .可以用sigaction()处理信号
解析:P528:一个发出而没有被接受的信号叫待处理信号,一个待处理信号最多只能被接收一次。
P529:也可以用键盘发送信号(比如Ctrl+C)。
P530:kill命令用来发送信号。
P531:进程可以通过使用signal函数修改和信号相关联的默认行为。
P540:为了解决不同系统有不同的信号处理语义的问题,Posix标准定义了sigaction函数。
- 有关exec系列函数,下面说法正确的是(CE)
A .可以用char[][] 来传递argv
B .进程调用了exec系列函数后,pid会变
C .进程调用了exec系列函数后,代码会改变。
D .system()和exec系列等价。
E .exec系列函数中带e的要传入环境变量参数
F .exec系列函数中带v的要传入环境变量参数
不能用char[][] 来传递argv,结尾的0(null)无法处理;
fork创建一个新的进程就产生了一个新的PID,exec启动一个新程序,替换原有的进程,因此这个新的被 exec 执行的进程的PID不会改变(和调用exec的进程的PID一样)。
system=fork+exec+wait;
- 有关wait类系统调用,说法正确的是(ACD)
A .wait(&status) 等价于waitpid(-1, &status, 0)
B .父进程中执行waitpid, 等待集合中的所有子进程结束了才返回
C .父进程中执行waitpid, 等待集合中的任一子进程结束了才返回
D .子进程中的退出状态在wait的status参数返回
p518:wait函数是waitpid函数的简单版本。waitpid的第一个参数是-1,等待任意一个子进程终止。
- 关于图中代码,说法正确的是(B)
A .程序执行2个printf
B .程序执行3个printf
C .程序执行5个printf
D .程序执行4个printf
这是书上练习题8.2,,P514示例程序大致相同,具体分析可以看书上514页。我对结果进行了验证,和预期一致:
- 有关fork(),下面说法正确的是(A C D)
A .一次调用,两次返回
B .子进程中,fork()返回子进程PID
C .子进程可以读写父进程中打开的文件
D .子进程和父进程的用户级虚拟地址空间相同但独立
p514:fork函数返回两次,一次是返回到父进程,一次是返回到新建的子进程。
新建的子进程和父进程几乎完全一样,最大的区别是不同的PID。子进程得到与父进程用户级虚拟地址空间相同的(但是独立)一份副本,包括任何打开文件描述符相同的副本,所以可以读写父进程中打开的文件。
- 关于代码 int main(){} 说法正确的是(A C E )
A .返回值是0
B .返回值不确定
C .会调用exit(0)
D .返回值大于0
E .上面代码运行完,在命令行中运行echo $? 的值是0
main中不调用exit,会补上exit(0);
echo $? :每个命令完成后,会返回其状态值,通过$? 可以得到返回值。
- 从程序员角度看进程状态有( A C D )
A .运行
B .就绪
C .停止
D .终止
运行:在CPU执行或等待被内核调度去执行。
停止:进程被挂起,不会被调度。
终止:进程永远地停止了,有三种原因:收到一个信号,该信号的默认行为是终止进程;从主程序中返回;调用exit函数
- Unix/Linux中通过调用( D )可以获取子进程PID。
A .getpid()
B .getppid()
C .getcpid()
D .fork()
fork在父进程中,返回子进程的PID,在子进程中,返回0.
- Unix/Linux中通过调用( B )获取父进程ID。
A .getppid()
B .getppid()
C .getbpid()
D .getmpid()
getpid函数返回调用进程的PID,getppid函数返回它的父进程的PID。
- 进程调度由内核中的( C )处理完成
A .上下文切换
B .中断服务程序
C .调度器
D .异常处理程序
在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占了的进程。这种决策就叫调度,有内核中称为调度器的代码处理。
- 进程调度中的上下文切换包括( A B D )
A .保存当前进程的上正文
B .恢复某个先前被抢占的进程被保存的上下文
C .让当前进程休眠
D .将控制传递给这个新恢复的进程
进程调度时,使用一种称为上下文切换的机制将控制转移到新的进程。
上下文切换(1)、保存当前进程的上下文(2)、恢复某个先前被抢占的进程被保存的上下文(3)、将控制传递给这个新恢复的进程
- 用户进程可以通过(B)访问内核代码和数据
A .特权指令
B .系统调用
C .模式位
D .程序计数器
用户程序必须通过系统调用接口间接地访问内核代码和数据。
- x86-64 Linux中,用户模式进程无法访问内核数据结构的内容。(B)
A .正确
B .错误
C .不确定
/proc文件系统允许用户模式进程访问内核数据结构的内容。
/sys文件系统输出关于系统总线和设备的额外的低层信息。
- x86-64 Linux进程中,代码段是从( C )开始的。
A .0
B .2^48-1
C .0x400000
D .2^64-1
见P510进程空间图。
参考Linux下C程序进程地址空间布局
- 三个进程的起始和结束时间如下图,互为并发的是( A C )
A .AB
B .AC
C .BC
D .以上都是
AB、BC进程的执行是重叠的,一个进程在另一个进程结束前开始。A在C开始之前就结束了,所以AC不是并发的。
- 进程提供给应用程序的关键抽象让我们的程序感觉独占了处理器和内存。(C)提供了独占处理器的假象。
A .地址空间
B .虚拟内存
C .逻辑控制流
D .指令控制流
单步执行程序,看到一系列程序计数器的值(PC)值,PC值序列叫逻辑控制流。逻辑控制流提供了独占处理器的假象。
- 有关异常,下面说法正确的是(CD)
A .系统中的异常由异常名唯一确定
B .异常表中存放的是异常处理程序
C .异常表的起始地址存放在异常表基址寄存器中
D .异常处理程序运行在内核模式下
解析:A、异常由异常号唯一确定。B、异常表存放的是异常处理程序的地址。
- 进程上下文包括程序的( A B C D E F)
A .代码和数据
B .栈
C .通用寄存器中的内容
D .程序计数器
E .环境变量
F .打开的文件描述符的集合
上下文切换时,就是切换进程的这些状态。
- X86-64结构,Linux中系统调用(函数调用)的返回值放在(C)
A .%rcx
B .%r11
C .%rax
D .%rbx
Linux系统调用的参数是通过寄存器传递的。%rax包含返回值。
- 图中第(D)行给出write(2)要写的字节数
A .9
B .10
C .11
D .12
write函数的三个参数分别表示:将输出发送到stdout,要写的字节序列,要写的字节数。
- 图中代码用到的系统调用是(C)
A .open(2)
B .read(2)
C .write(2)
D .close(2)
从第9行,将write的编号1放入%rax可以看出来。
- x86-64中,Linux系统调用的系统调用号是通过(B)传递的。
A .栈
B .%rax
C .%rdi
D .%rbp
E .%rsp
%rax包含系统调用号
- 调用fork(2)的系统调用号是(D)
A .0
B .2
C .3
D .57
通过查看P507上,图8-10常见系统调用号,fork对应编号为57
- C语言中有(A)函数可以直接调用任何系统调用
A .syscall
B .syscalls
C .system
D .main
C语言中用syscall可以直接调用任何系统调用
- 异步异常是同处理器外部的I/O设备中的事件产生的(硬件产生),同步异常是执行一条指令的直接产物(软件产生)。下面是同步异常的是(B C D )
A .中断
B .陷阱
C .故障
D .终止
中断属于异步异常。
- 系统调用属于异常中的(B)
A .中断
B .陷阱
C .故障
D .终止
陷阱是有意的异常,陷阱最重要的用途是在用户程序和内核之间提供一个像过程一样的接口。
- Linux中,信号(Signal)是一种(C)异常控制流。
A .硬件层
B .操作系统层
C .用户层
D .网络层
在应用层,一个进程可以发送信号到另一个,而接收者会将控制突然转移到他的信号处理程序。
- 中断是(A)的异常控制流。
A .硬件层
B .操作系统层
C .应用层
D .网络层
中断是异步发生的,是来自处理器外部的I/O设备的信号的结果。通过检测到中断引脚电压变高了,属于硬件层异常控制流。