【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根

文章目录

  • C/C++笔试练习
  • 选择部分
    • (1)缺页中断
    • (2)同步互斥/可重入函数
    • (3)死锁的条件
    • (4)大小端存储
    • (5)CPU执行语句时间
    • (6)计算机缓存
    • (7)地址总线
    • (8)父子进程
    • (9)进程和线程
    • (10)进程调度
  • 编程题 day25
    • 星际密码
    • 数根

C/C++笔试练习

选择部分

(1)缺页中断

  一进程刚获得三个主存块的使用权,若该进程访问页面的次序是{1321215123},采用LRU算法时,缺页数是()次。

  A. 3
  B. 4
  C. 5
  D. 6

  答案:C

  缺页中断: 缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。

  LRU算法 (最近最久未使用和最少使用):当要调入一页而必须淘汰旧页时,将最近最少使用的置换出去。

  缺页数: 即缺页中断次数,就等于进程的物理块数+页面置换次数。

操作 说明
1进入->1 1进入第一个主存块
3进入->3 1 3进入第二个主存块,刚使用的放在前面,未使用的依次后移
2进入->2 3 1 2进入第三个主存块
1进入->1 2 3 1已经在内存,向前调整
2进入->2 1 3 2向前调整
1进入->1 2 3 1向前调整
5进入->5 1 2 5不存在,进行页面置换,淘汰旧页2
1进入->1 5 2 1向前调整
2进入->2 1 5 2向前调整
3进入->3 2 1 3不存在,进行页面置换,淘汰旧页5

  总共进行了两次页面置换,所以缺页数=3+2=5。

  

(2)同步互斥/可重入函数

  以下关于多线程的叙述中错误的是()

  A. 线程同步的方法包括使用临界区,互斥量,信号量等
  B. 两个线程同时对简单类型全局变量进行写操作也需要互斥
  C. 实现可重入函数时,对自动变量也要用互斥量加以保护
  D. 可重入函数不可以调用不可重入函数

  答案:C

  临界区: 指的是一个访问共用资源(同一个全局变量,同一个类对象等等)的程序片段。

  互斥量: 互斥锁的底层就是互斥量,使用互斥锁可以限制多个执行流对临界资源的访问时,只有一个执行流可以访问资源,其他执行流需要等待。从而保证了程序结果没有二义性。

  信号量: 信号量可以描述并且管理一个资源的数量,提供wait/post的接口来保证程序不会产生二义性结果,同时信号量也可以保证线程同步,信号量的底层有一个资源计数器+PCB等待队列。

  根据上面所给的基本概念所以,线程同步的方法包括使用临界区,互斥量,信号量等;两个线程同时对简单类型全局变量进行写操作时,我们一定要保持互斥,避免线程安全问题。

  可重入函数: 在多线程的程序当中,如果一个函数可能同一时刻被多个线程访问,没有导致程序的结果产生二义性,则该函数被称之为可重入函数。

  不可重入函数: 在多线程的程序当中,如果一个函数可能同一时刻被多个线程访问,从而导致程序的结果产生二义性,则该函数被称之为不可重入函数。

  实现可重入函数时,对自动变量也要用互斥量加以保护就是错误的了,因为可重入函数可以同时被多个线程进行访问,不会对程序结构产生二义性,也就不需要对自动变量使用互斥量加以保护了。

  可重入函数不可以调用不可重入函数是正确的,如果可重入函数调用不可重入函数,就会导致可重入函数也会产生二义性。

  

(3)死锁的条件

  系统死锁的可能的原因是()

  A. 进程死循环
  B. 资源循环等待
  C. 程序内存访问越界
  D. 进程释放资源

  答案:B

  死锁的4个必要条件:

  互斥条件: 一个资源每次只能被一个进程使用

  请求与保持条件: 一个进程因请求资源而阻塞时,对已获得的资源保持不放。(程序员可以破坏)

  不剥夺条件: 进程已获得的资源,在未使用完之前,不能强行剥夺。

  循环等待条件: 若干进程之间形成一种头尾相接的循环等待资源关系。(程序员可以破坏)

  所以对于上面的选项,A选项死循环,不满足上面的任意条件,并不能导致程序死锁。B选项是死锁的必要条件之一。C选项内存访问越界,程序有可能崩溃。D选项进程释放资源这个是正常操作。

  

(4)大小端存储

  整数0x12345678,在采用bigendian中内存的排序序列是( )

  A. 12 34 56 78
  B. 78 56 34 12
  C. 87 65 43 21
  D. 21 43 65 87

  答案:A

  big endian(大端字节序):低位存在高地址

  Little Endian(小端字节序):低位存在低地址

【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根_第1张图片

  整数:0x12345678,其中12是高位,78是低位,因为是大端存储,所以低位地址存在高位地址处,内存中的排序为12345678。

  

(5)CPU执行语句时间

  使用C语言将一个1G字节的字符数组从头到尾全部设置为字’A’,在一台典型的当代PC上,需要花费的CPU时间的数量级最接近()

  A. 0.001秒
  B. 1秒
  C. 100秒
  D. 2小时

  答案:B

  电脑的主频(GHZ):这个参数代表了CPU在1秒时间内,可以执行的简单指令的数量是xxG条。例如:3.2GHZ,就可以认为CPU执行简单的指令在1秒内可以完成3.2G条。

  CPU执行一条语句大约时间:执行1条语句约1ns即10的-9次方秒。

  因为赋值操作的指令只有一条,所以花费的时间大约为:1G=1024M=1024 * 1024k=1024 * 1024 * 1024byte,每次赋值1byte都要执行一次语句,故至少花费1024 * 1024 * 1024 * 10^-9=1.073741824s。

  

(6)计算机缓存

  对于普通的计算机,对以下事件的平均耗时从小到大排序为____:
  A.读取1KB内存数据 B.从硬盘连续读取1KB数据 C.读取一次L2缓存 D.一次磁盘寻道

  A. C,A,D,B
  B. C,D,A,B
  C. D,C,A,B
  D. D,A,C,B

  答案:A

  计算机缓存的概念:
【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根_第2张图片

  

  机械硬盘的概念:

  磁道:以盘片中心为圆心,用不同的半径,划分出不同的很窄的圆环形区域,称为磁道。

  扇区:磁盘上的每个磁道被等分为若干个弧段,这些弧段便是磁盘的扇区,扇区是磁盘最小的物理存储单元。

  柱面:上下一串盘片中,相同半径的磁道所组成的一个圆柱型的环壁,就称为柱面。

【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根_第3张图片

  存储容量:

  存储容量 = 磁头数 x 磁道(柱面)数 x每道扇区数 x每扇区字节数 图中磁盘是一个 3个圆盘6个磁头,7个柱面(每个盘片7个磁道)的磁盘,图中每条磁道有12个扇区所以此磁盘的容量为:存储容量6712*512=258048。

  

  磁盘读取响应时间:

  寻道时间:磁头从开始移动到数据所在磁道所需要的时间,寻道时间越短,I/0操作越快,目前磁盘的平均寻道时间于般在3-15ms,一般都在10ms左右。

  旋转延迟:盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间,旋转延迟取决于磁盘转2速。普通硬盘一般都是7200rpm,慢的5400rpm。

  数据传输时间:完成传输所请求的数据所需要的时间。

  小结一下:从上面的指标来看、其实最重要的、或者说、我们最关心的应该只有两个:寻道时间;旋转延迟。

  
【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根_第4张图片
  

从CPU到 大约需要的时间
主存 约60-80纳秒
L3 cache 约15ns
L2 cache 约3ns
L1 cache 约1ns

所以:L1 cache < L2 cache < L3 cache < 内存< 一次磁盘寻道 < 磁盘读取数据。

  

(7)地址总线

  现代计算机普遍采用总线结构,包括数据总线、地址总线、控制总线,通常与数据总线位数对应相同的部件是( )

  A. CPU
  B. 存储器
  C. 地址总线
  D. 控制总线

  答案:A

  地址总线:决定内存数据操作的地址。(4G,x00000000-0xFFFFFFFF)
  1、CPU是通过地址总线来指定存储单元的。
  2、地址总线决定了CPU能访问的最大内存空间的大小。
  3、地址总线是地址线数量之和。

  数据总线:决定传输的数据值。(字长大小)
  1、决定一次数据传输可决定的数据大小。
  2、数据总线的宽度决定了CPU和外界的数据传送速度,
  3、每条传输线只能传递1位二进制数据
  4、数据总线是数据线条数之和。

  控制总线:反映了数据的状态和传输方式。
  1、CPU通过控制总线对外部器件进行控制。
  2、控制总线的宽度决定了CPU对外器件的控制能力。
  3、控制总线控制线数量之和。

  地址总线当中每一根地址线都可以模拟01信号, 所以,32位操作系统有32根地址线,64位操作系统有64根地址线。而32位操作系统的地址为x00000000-0xFFFFFFFF(就是32根地址线全为0-32根地址线全为1)。

  

(8)父子进程

  关于子进程和父进程的说法,下面哪一个是正确的()

  A. 一个父进程可以创建若干个子进程,一个子进程可以从属于若干个父进程
  B. 父进程被撤销时,其所有子进程也被相应撤消
  C. 子进程被撤销时,其从属的父进程也被撤销
  D. 一个进程可以没有父进程或子进程

  答案:D

  一个父进程可以创建若干个子进程,但是一个子进程只能从属一个父进程;父进程终止了,子进程还可以正常运行,子进程终止了,父进程也可以正常运行。

  系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。 整个linux系统的所有进程也是一个树形结构。树根是系统自动构造的,即在内核态下执行的0号进程。由0号进程创建1号进程(内核态),1号负责执行内核的初始化工作及进行系统配置,并创建若干个用于高速缓存和虚拟主存管理的内核线程。随后,1号进程调用execve()运行可执行程序init,并演变成用户态1号进程,即init进程。

  

(9)进程和线程

  关于线程和进程,下面说法正确的是()

  A. 终止一个进程比终止一个线程花费的时间少
  B. 进程切换比同一进程内部的线程切换花费的时间少
  C. 线程提高了不同执行程序间的通信效率
  D. 进程和线程都是资源分配和调度的基本单位

  答案:C

  终止一个进程比终止一个线程花费的时间少是错误的,花费的时间多,因为线程只是一个执行流,不会讲进程资源释放掉。进程切换比同一进程内部的线程切换花费的时间少是错误的,线程切换花费的时间少。

  线程提高了不同执行程序间的通信效率,可以让进程的某一个线程执行通信任务,其他的线程做其他事情, 提高程序的运行效率。

  进程和线程都是资源分配和调度的基本单位:进程是操作系统分配资源的基本单位,线程是操作系统调度的基本单位。

  

(10)进程调度

  进程调度时,下列进程状态的变化过程哪一项是不可能发生的()

  A. 阻塞挂起->阻塞
  B. 就绪挂起->就绪
  C. 就绪挂起->阻塞挂起
  D. 阻塞挂起->就绪挂起

  答案:C

【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根_第5张图片

【C/C++笔试练习】缺页中断、同步互斥/可重入函数、死锁的条件、大小端存储、CPU执行语句时间、计算机缓存、地址总线、父子进程、进程和线程、进程调度、星际密码、数根_第6张图片

            

编程题 day25

星际密码

星际密码

  这个题目首先需要明确矩阵是固定的,其次是矩阵相乘的方法,矩阵相乘 |a1 a2| * |c1 c2| = |a1c1 + a2d1 a1c2 + a2d2| |b1 b2| |d1 d2| |b1c1 + b2d1 b1d2 + b2d2| 矩阵是 |1 1|^2 = |1 1|*|1 1|=|2 1| |1 0| |1 0| |1 0| |1 1| n的取值:1 2 3 4 5 6 … 左上角值:1 2 3 5 8 13 … 会发现这是一个变式的斐波那契,我们初始化斐波那契数列,每次获取对应数据,打印最后4位即可。

#include 
#include 

std::vector<int> a = {1, 1};
void data_init() 
{
    int i;
    for (i = 2; i < 10005; i++) 
    {
        a.push_back((a[i - 1] + a[i - 2]) % 10000);
    }
}

int main() 
{
    int n, t;
    data_init();
    while (std::cin >> n) 
    {
        while (n--) 
        {
            std::cin >> t;
            printf("%04d", a[t]);
        }
        printf("\n");
    }
    return 0;
}

  

数根

数根

  解题思路:先接收字符串得到各个数字,并且每位求和(为了得到的数字不大于99),然后循环对大于9的数字进行对10取余和整除操作,将两个结果进行相加得到树根。

#include 
#include 

int numRoot(int num) 
{
    int nroot = 0;
    while (num > 0) 
    {
        /*每次只获取个位数字---个位数+十位数*/
        nroot += num % 10;
        num /= 10;
    }
    while (nroot > 9) 
    {
        nroot = numRoot(nroot);
    }
    return nroot;
}

int main() 
{
    std::string origin;
    while (std::cin >> origin) 
    {
        int sum = 0;
        //先将每一位进行相加得到总和,防止数字过大
        for (int i = 0; i < origin.length(); i++) 
        {
            sum += origin[i] - '0';
        }
        //对总和求树根
        std::cout << numRoot(sum) << std::endl;
    }
    return 0;
}

你可能感兴趣的:(C/C++笔试练习,c语言,c++,linux)