嵌入式软件工程师面试题——2025校招社招通用(十九)

发布时间:2024年01月16日

说明:

  • 面试群,群号: 228447240
  • 面试题来源于网络书籍,公司题目以及博主原创或修改(题目大部分来源于各种公司);
  • 文中很多题目,或许大家直接编译器写完,1分钟就出结果了。但在这里博主希望每一个题目,大家都要经过认真思考,答案不重要,重要的是通过题目理解所考知识点,好应对题目更多的变化;
  • 博主与大家一起学习,一起刷题,共同进步;
  • 写文不易,麻烦给个三连!!!

1.有抢占式和非抢占式的区别

答案:

非抢占式优先权算法:?在这种方式下,系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成。
抢占式优先权调度算法:在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。

2.并发和并行

答案:
并发:?是对于单个cpu来说,在一个时刻只能一个进程运行,但是线程的切换时间则是减少到纳秒数量级,多个任务不停的来回切换。
并行:是对于多个CPU来说,多个进程可以同时运行。

区别
并行的"同时"是同一时刻可以多个任务在运行(处于running),并发的"同时"是经过不同线程快速切换。

3.进程间的通信中的管道通信实现原理是什么

答案:

操作系统在内核中开辟一块缓冲区(称为管道)用于通信。

编程步骤:

  1. 互斥条件进程对所分配的资源不允许其他进程访问,若其他进程需要访问,只能等待,知道该进程使用完毕后释放资源
  2. 请求保持条件:进程获得一定资源后,有对其他资源发出请求,但该资源被其他进程占用,此时请求阻塞,而且这个进程不会释放自己已经占有的资
  3. 不可剥夺条件进程获得资源,只能自己释放,不可剥夺
  4. 环路等待条件若干进程之间形成一种头尾相接等待资源关系
#include<unistd.h>     
#include<stdio.h>     
#include<stdlib.h>     
#include<string.h>     
#define INPUT  0  //读数据fd    
#define OUTPUT 1   //发数据fd  
     
int main(){     
//创建管道     
    int fd[2];     
    pipe(fd);     
    //创建子进程     
    pid_t pid = fork();     
    if (pid < 0){     
        printf("fork error!\n");     
        exit(-1);     
    }     
    else if (pid == 0){//执行子进程   
        printf("Child process is starting...\n");    
        //子进程向父进程写数据,关闭管道的读端    
        close(fd[INPUT]);   
        write(fd[OUTPUT], "hello douya!", strlen("hello douya!"));   
        exit(0);   
    }   
    else{//执行父进程   
        printf ("Parent process is starting......\n");   
        //父进程从管道读取子进程写的数据 ,关闭管道的写端     
        close(fd[OUTPUT]);     
        char buf[255];   
        int output = read(fd[INPUT], buf, sizeof(buf));   
        printf("%d bytes of data from child process: %s\n", output, buf);   
    }   
    return 0;     
}

?4.说说什么是死锁,产生的条件,如何解决?

答案:

死锁:?是指多个进程在执行过程中,因争夺资源而造成互相等待,此时系统产生了死锁。

产生条件:

  1. 互斥条件:进程对所分配的资源不允许其他进程访问,若其他进程需要访问,只能等待,知道该进程使用完毕后释放资源。
  2. 请求保持条件:进程获得一定资源后,有对其他资源发出请求,但该资源被其他进程占用,此时请求阻塞,而且这个进程不会释放自己已经占有的资源。
  3. 不可剥夺条件:进程获得资源,只能自己释放,不可剥夺。
  4. 环路等待条件:若干进程之间形成一种头尾相接等待资源关系

解决:

  1. 资源一次性分配,从而解决请求保持的问题
  2. 可剥夺资源:当进程新的资源未得到满足时,释放已有的资源;
  3. 资源有序分配:资源按序号递增,进程请求按递增请求,释放则相反

5.单核机械上写多线程程序,是否考虑加锁,为什么?

答案:

需要。

因为线程锁只要是用来实现线程的同步和通信,在抢占是操作系统中,通常为每个线程分配一个时间片,当某个线程时间片耗尽时,操作系统会将其挂起,然后运行另一个线程。如果这两个线程共享某些数据,不使用线程锁的前提下,可能会导致共享数据修改引起冲突。

6.互斥锁机制,互斥锁和读写的区别?

答案:

互斥锁机制:mutex,用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒。

互斥锁和读写锁:

(1) 读写锁区分读者和写者,而互斥锁不区分;

(2)互斥锁同一时间只允许一个线程访问该对象,无论读写;读写锁同一时间内只允许一个写者,但是允许多个读者同时读对象;

函数 acquire() 获取锁,而函数 release() 释放锁

7.说说什么是信号量,有什么作用?

答案:

由于信号量只能进行两种操作,等待和发送信号,即P(sv)和V(sv)

(1)P(sv)操作:如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行(信号量的值为正,进程获得该资源的使用权,进程将信号量减1,表示它使用了一个资源单位)。

(2)V(sv)操作:如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1(若此时信号量的值为0,则进程进入挂起状态,直到信号量的值大于0,若进程被唤醒则返回至第一步)。

作用:用于多进程对共享数据对象的读取,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。

8.进程、线程的中断切换的过程是怎样的?

答案:

上下文切换:?指的是内核(操作系统的核心)在CPU上对进程或者线程进行切换。

进程上下文切换:

(1)保护被中断进程的处理器现场信息;

(2)修改被中断进程的进程控制块有关信息,如进程状态等;

(3)把被中断打断的进程控制块加入有关队列;

(4)选择下一个占有处理器运行的进程;

(5)根据被选中进程设置操作系统用到的地址转换和存储保护信息;

(6)根据被选中进程恢复处理器现场。

9.多线程和单线程有什么区别,多线程编程要注意什么,多线程加锁需要注意什么?

答案:

  1. 区别:

    • 单线程:程序按照顺序执行,一次只能执行一个任务。当某个任务需要等待 I/O 操作或者其他耗时操作时,整个程序会停止执行,直到该任务完成。
    • 多线程:程序可以同时执行多个任务,每个任务对应一个线程。多线程可以实现并发执行,提高程序的响应速度和效率。
  2. 注意事项:

    • 线程同步:多线程编程需要特别注意线程同步,即协调不同线程访问共享资源的问题。如果多个线程同时读写共享数据,可能导致数据不一致或冲突。可以使用锁、信号量等机制来进行线程同步。
    • 竞态条件(Race Condition):当多个线程同时竞争访问和修改共享数据时,可能会出现竞态条件。为避免竞态条件,需要使用互斥锁、条件变量等机制来保护共享资源的访问。
    • 死锁:在多线程编程中,如果多个线程相互等待对方释放资源,而导致程序无法继续执行,就会发生死锁。避免死锁的方法包括避免循环等待、按序申请资源等。
    • 资源消耗:多线程编程需要更多的系统资源,包括内存和处理器资源。因此,在设计多线程程序时需要考虑系统的资源限制,并合理利用线程池等技术来管理线程。
  3. 多线程加锁注意事项:

    • 锁粒度:锁的粒度应尽量小,只保护必要的共享资源,以减少锁的竞争和影响程序性能。
    • 死锁风险:过多的锁使用可能导致死锁问题,因此需要仔细设计锁的获取和释放顺序,避免出现循环等待的情况。
    • 锁的性能:锁的过多使用也会影响程序的性能,因为获取和释放锁会引入额外的开销。因此,需要权衡锁的使用频率和性能之间的平衡。

10.为什么要创建线程池?线程池的设计思路,线程池中线程的数量由什么确定?

答案:

原因:

创建和销毁线程的花销是比较大的,这些时间可能比处理业务时间还要长,这样频繁的创建和销毁线程,再加上业务工作的线程,消耗系统资源的时间,可能导致系统资源不足,线程池可以提升系统效率。

实现线程池步骤:

  1. 设置一个生产者消费者队列,作为临时资源;
  2. 初始化n个线程,并让其运行起来,加锁去队列里去任务运行;
  3. 当任务队列为空时,所有线程阻塞;
  4. 当生产者队列来了一个任务后,先对队列加锁,把任务挂到队列上,然后使用条件变量通知阻塞中的线程来处理。

线程的数量:

与CPU、IO/并发、并行有关。

如果是CPU密集型应用,则线程池大小设置为:CPU数目+1;

如果是IO密集型应用,则线程池大小设置为:2*CPU数目+1;

最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目;

文章来源:https://blog.csdn.net/weixin_45257157/article/details/135618665
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。