0%

  • 自我介绍
  • 华为实习工作
    • 问了开发过哪些规则
    • 定义变量没有初始化会发生生么事
  • 对写代码怎么看
    • 对35岁还在写代码没什么出息怎么看
  • 自己的规划
    • 5年内的规划
  • 觉得哪个项目有亮点
    • 讲了编译器的项目
    • 项目由哪几个模块组成,有哪些难点
  • 对编译原理的理解
  • 对业务和技术的看法以及倾向
    • 业务就是按照来的需求写功能
    • 抖音电商的offer和阿里云编译的offer选哪个
  • 对硬件和芯片的看法和兴趣
  • ACM竞赛的经历
    • 比赛的过程是什么样子
    • 做了哪些贡献
    • 有什么收获
  • 反问环节
    • 问了面试的进度是什么样子,因为后台看不到

总结:一共差不多30分钟,没问太多八股文,主要是问了项目实习以及聊了一些规划和看法之类的。上一次不算一面,只算做意向评估,这次的能算一面吧,后面还有一到两轮技术面,还要HR面,以及笔试挺难的也挺重要的。认为我的优势是ACM经历所以笔试要好好准备。

已通过


  • 上来先手撕三道代码, 题目不难,都算是经典题,但是给的时间稍微有点儿少,而且一上来就撕代码有点儿懵,导致一道很简单的链表翻转题没做好。。

  • 第一题是链表k个一组翻转

    • 一上来有点懵,边界老是处理不好,写了十分钟没写出来就去做后面两道题了,后面两道题比较简单,一会儿就写完了又回来接着做这个。
    • 老是处理不好边界,索性直接把链表存到数组里,在数组里处理,结果最后面试让解释一下代码的时候还是解释的不太清楚。。
  • 第二题是把数组的前k个移到最后

    • 开了个临时数组存,面试官问不定长数组会有什么问题,如果数组很长那么存在哪里
    • 问有没有更小内存开销的方法,问复杂度(这里答得有点儿混乱)
    • 堆栈的区别
    • 为什么要有堆和栈
  • 第三题是最大子数组

  • 问ACM竞赛经历,团队几人,怎么分配工作,过几题能拿牌

  • 问编译器项目,非常详细,一步一步地问

    • 词法分析怎么实现的,有没有比字符串匹配更好的方法,答了字典树,又问字典树为什么更好之类的
    • 文法分析,抽象语法树,递归实现,有没有比递归实现更好的方式,答了可以模仿字典树(这里答的不好,面试官说循环递归的问题字典树解决不了,就建不起来这棵树),除了递归和字典树之外还有没有什么方案(不知道。。)
    • 汇编代码生成是干什么的,为什么是四元式,解释了一下操作数操作符操作结果之类的。
    • 寄存器优化怎么实现的,答了引用计数法,问还有哪些地方会用到(内存页面置换),然后问了一些内存页面置换的问题
  • 虚拟内存,为什么要有虚拟内存,怎么实现的,页表,页和块

  • 进程间通信有哪些,管道是什么,套接字是什么,共享内存是什么,哪个最快(答了共享内存,不知道对不对)

  • 线程同步方式,信号是什么

  • 为什么要有线程,进程是什么

  • B+树是什么,有什么特性(答了叶子结点之间有指针),有什么好处(答了查找比较快和擅长范围查找)

  • TCP和UDP,区别,适用于哪些场景

  • HTTPS是什么,SSL具体怎么实现,为什么,对称加密和非对称加密的区别

  • 问科研项目

    • 持续时间,几个人在做,具体怎么实现,除了超声还有什么方式,wifi可以吗,红外可以吗,摄像头人脸识别怎么样,呼吸和心跳是怎么测得的等等
  • 问了开发的app,觉得哪个最好,讲了一下

  • 工作地点是广州,对于工作地点有没有想法

  • 反问环节

    • 问了面试官觉得我表现怎么样,有哪些方面可以提高,面试官说原理性的东西可以提高一下,比如做的编译器的原理细节等,思考更深入一点儿

总结:问了一个半小时多,是这么多面试里最久的,期间网络很差,换手机热点也很差,断线好几次,后来直接把摄像头关了。面试官问的特别详细,特别深,特别喜欢问为什么。知识点八股文方面答的还行,但是手撕代码和问项目这两个部分出了不少问题,感觉要gg了。。

接到继续面试的电话了,应该算是过了吧


  • 电话面

  • 自我介绍

  • 问华为的实习经历

    做了什么工作,技术难题,工具开源

    规则应用于十万行代码的性能?误报率?华为代码安全重复率啥的。。(这些都不了解。。)

  • 问科研项目

    系统架构,项目持续时间,从事的工作,硬件组成

  • 团队介绍

    原神等的云游戏,可能会跟硬件相关,中心云芯片,高通

进程同步

  1. 管道

    管道分为命名管道和匿名管道,命名管道可以用于两个或任意多个进程间通信,匿名管道则只能用于有血缘关系(父子进程、兄弟进程、爷孙进程等)的进程间通信。Linux中的“|”命令就是匿名管道,表示把一个进程的输出作为另一个进程的输入。管道就是内核里的一段缓存,从管道一端写入的数据实际上是缓存在内核中,从另一端读取也就是从内核中读取这段数据。管道是半双工的,数据只能向一个方向流动,双方需要互相通信时,需要建立起两个管道。

  2. 消息队列

    多个不相干的进程可以通过一个消息队列来传递数据,且传递的是一个有意义的数据结构,而管道只能传递没有意义的字节流,还需要在接收端做解析。

  3. 共享内存

    共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的一种IPC方式,因为没有内存拷贝的操作,但需要依靠互斥锁或信号量来实现同步。

  4. socket

    可用于不同主机之间的进程间通信。

  5. 信号

    信号是Linux系统中的进程间通信方式,信号可以在任何时候发给某一进程,用于通知该进程某个事件已经发生。比如kill -9命令就可以向指定的进程发送一个终止信号从而杀死进程。

  6. 信号量

    信号量本质就是一个计数器,记录资源能被多少个进程同时访问,用来实现进程之间的互斥与同步,信号量的引入的是为了解决共享内存通信方式造成的进场安全问题。

进程同步和进程通信

  • 进程同步是进程之间按照一定顺序执行,进程通信是进程之间传输信息。

  • 进程通信是一种手段,而进程同步是目的。即为了达到进程同步的目的,需要让进程进行通信,传输一些同步所需要的信息。

线程同步

  1. 互斥锁

    互斥锁是线程同步最常用的一种方式,通过互斥锁可以锁定一个代码块,对于被锁定的这个代码块,所有的线程只能串行处理,不能并行处理。

  2. 读写锁

    读写锁是互斥锁的升级版,所有线程的读操作都是并行的,只有写操作是串行的。程序中的读操作越多,读写锁性能就越高,相反,若程序中全是写操作,那么读写锁会退化成互斥锁。

  3. 条件变量

    条件变量的主要作用不是处理线程同步,而是进行线程的阻塞。常常和互斥锁一起用在生产者和消费者模型中。举个例子:当任务队列为空时,消费者无法消费,使用条件变量把消费者线程阻塞住,等待生产者生产出任务后,再唤醒一个或多个被条件变量阻塞的消费者线程;反过来也可以控制生产者生产的上限,当任务队列达到一个上限值时用条件变量阻塞住生产者线程,直到消费者把任务消费后再唤醒被条件变量阻塞的生产者线程。

  4. 信号量

    信号量可以实现线程同步也可以实现进程同步,它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。信号量主要阻塞线程,不能完全保证线程安全,如果要保证线程安全,需要和互斥锁一起使用。信号量也可以用来实现生产者消费者模型,在用条件变量实现生产者消费者模型时需要自己做条件判断,而使用信号量就不需要。举个例子:初始化生产者的信号量为5,消费者的信号量为0,因为消费者信号量为0所以会被阻塞,生产者进行一次生产后会将自己的信号量减1,将消费者信号量加1,这时消费者解除阻塞,进行消费后再将自己的信号量减1生产者信号量加1。

  5. 自旋锁

    自旋锁与互斥锁类似,但它不是通过休眠使进程阻塞,而是在获取锁之前一直处于忙等(自旋)阻塞状态。自旋锁可用于一下情况:锁被持有的时间短,而且线程并不希望在重新调度上花费太多成本。

  6. 屏障

    屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后从该点继续执行。pthread_join函数就是一种屏障,允许一个线程等待,直到另一个线程退出,但屏障允许任意数量的线程等待,直到所有的线程完成处理工作,而线程不需要退出,所有线程达到屏障后可以接着工作。

信号量和互斥锁

  • 互斥锁是由一个线程持有的,加锁和解锁操作在一个线程中执行。而信号量可以由不同线程进行PV操作。
  • 互斥锁用于控制多个线程对于一个共享资源的互斥访问,而信号量用于协调多个线程对于一系列资源的访问。
  • 信号量本质上是一个计数器,其正值代表资源的可用数量,负值代表还有多少个线程在等待资源。

条件变量和信号量

  • 信号量利用条件变量、互斥锁、计数器实现,计数器就是信号量的核心,信号量是条件变量的高级抽象。
  • 使用条件变量可以一次唤醒所有等待者,而这个信号量没有的功能,感觉是最大区别。
  • 信号量是有一个值(状态的),而条件变量是没有的,没有地方记录唤醒(发送信号)过多少次,也没有地方记录唤醒线程(wait返回)过多少次。从实现上来说一个信号量可以是用mutex + counter + condition variable实现的。因为信号量有一个状态,如果想精准的同步,那么信号量可能会有特殊的地方。信号量可以解决条件变量中存在的唤醒丢失问题。