【C 语言】1、 C 和 C++有什么不同?
1)C语言面向过程编程,重程序的实现;C++面向对象编程,重程序的设计;
2)C是C++的一个子集;C++全面兼容C;
3)C++相对于C引入了重载、内联函数、异常处理、类的封装/继承/多态、以及STL/容器类等…
2、进程和线程的异同、关系?
1)进程:是系统资源分配和调度的基本单位,有自己的pid;
线程:是运行的基本单位,有自己的tid。
2)进程:一个进程至少拥有1个线程,为主线程;
线程:同一个进程中的线程可以并发,且共享进程的资源,拥有自己独立的栈空间和执行序列。
3)进程有独立的地址空间,多进程程序要比多线程程序健壮,但进程切换时,需要复制PCB,资源开销大,效率稍低;
线程没有独立地址空间,必须依赖具体的进程才能执行,线程的切换不需要复制PCB资源开销小,效率比进程高;
4)进程能实现跨机器迁移;
线程适合于SMP(对称多处理器)机器上运行。
3、进程间通信都有哪几种机制?其中最快的机制为哪种?
1)管道(pipe):
管道用于具有亲缘关系的进程间通信,其中有名管道可实现无亲缘关系的进程间通信;
2)信号(signal):
软中断机制,进程收到信号相当于处理器收到中断请求,用于通知进程对应的事件处理;
IPC通信>>
3)消息队列(message queue)
克服了管道和信号中量有限的缺点,利用内存中公共消息缓冲区实现进程间通信;
4)共享内存(shared memory)——【最快的IPC通信形式】因为进程可以直接读写内存,不需要数据的拷贝。
内核维护一块由多个进程均可访问的内存,实现进程通信,需要互斥锁或信号量集配合实现同步;
5)信号量集(semaphore)
多进程之间或同一进程内的多线程之间实现同步和互斥的手段;
socket网络通信>>
6)套接字(socket):
实现网络中不同机器之间的进程间通信,应用广泛。
4、请简述 socket 编程中 client 和 server 的大致步骤?
以基于TCP的编程模型为例。
server:
1) 创建通讯端(套接字) - socket
2) 初始化服务器的地址空间 - sockaddr_in成员
3) 将套接字和服务器地址空间绑定 - bind
4) 监听通讯端- listen
5) 等待客户端连接的到来,到来返回连接描述符 - accept
6) 通过连接描述符进行读取客户端数据 - read //data
7) 通过连接描述符给客户端响应 - write
8) 关闭连接描述符 – close
client:
1) 创建通讯端(套接字) - socket
2) 初始化服务器的地址空间(ip转换) - sockaddr_in成员/inet_pton
3) 连接服务器,成功返回即连接成功 - connect
4) 向服务器发送请求信息 - write
5) 从服务器获取响应信息 - read
6) 对响应信息做相关的数据处理 - //data
7) 关闭通讯端(套接字) – close
5、进程之间通信的途径?进程死锁的原因?死锁的 4 个必要条件?
进程通信途径:管道、信号、消息队列、共享内存、信号量集、套接字。
死锁:多个进程循环等待它方占有的资源而无限期地僵持下去的一种程序运行情况。
进程死锁原因:
1)系统提供资源有限;
2)系统资源分配不当;
3)多进程中进程运行推进顺序不合理;
解除死锁条件:
1)互斥条件:1个资源每次只能被1个进程使用。
2)请求与保持条件:1个进程因请求资源阻塞时,对已获得的资源保持不放。
3)不抢占条件:进程已获得的资源在未使用完之前,不能强行抢占。
4)循环等待条件:多进程之间形成一种头尾相接的循环等待资源关系。
6、死锁的处理?操作系统中进程调度策略有哪几种?
死锁的处理方法:
1)最简单最常用的是:系统重新启动。但代价大,进程已完成的运算都付之东流。
2)撤销进程,剥夺资源。一次性终止参与死锁的进程,或者逆序逐步撤销参与死锁的进程,需考虑优先级及代价。
进程调度的策略:
1)先来先服务(FCFS)
2)优先级
3)时间片轮转
4)分级调度
5)多级反馈轮转
【区别于】常用的作业调度算法有:先来先服务算法(FCFS)、最短作业优先算法(SJF)、最高响应比优先算法(HRRN)、优先级调度算法、均衡调度算法等。
7、 TCP 和 UDP 的区别?简述 3 次握手协议?
TCP和UDP的区别:
1)TCP面向连接;UDP面向无连接;
2)TCP传输无差错不丢失,安全可靠,效率不如UDP;UDP传输容易丢包,安全性较差,传输效率高于TCP;
3)TCP连接点对点;UDP支持多对多交互通信;
4)TCP首部开销20字节;UDP首部开销8字节;
5)TCP是全双工可靠信道;UDP是不可靠信道。
8、什么是字节对齐,为什么要对齐?怎么样实现字节对齐?
字节对齐概念:
各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放。
字节对齐原因:
1)减少CPU访存次数,提高CPU的访问效率;
2)提高对于不同硬件平台下代码的可移植性;
3)合理利用可以有效节省存储空间。
字节对齐方法:
C编译器默认为每个变量或数据单元按其自然对界条件分配空间。也可以通过以下2中方式改变对齐方式:
1)#PRagma pack
· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使用伪指令#pragma pack ( ),取消自定义字节对齐方式。
2)__attribute( )
· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
· __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
9、多线程编程中要注意什么问题 ?
1)明确使用线程的目的。是对不同的资源(例如SOCKET连接)进行管理,考虑多个线程;
2)控制线程的调度和阻塞。如利用事件的触发来控制线程的调度和阻塞,也有用消息来控制的;
3)不能出现死锁问题。线程中如果用到公共资源,要考虑公共资源的线程安全。一般用互斥锁机制来控制。
4)合理使用sleep。何时Sleep,Sleep的大小要根据具体项目,做出合理安排。一般原则非阻塞状态下每个循环都要有SLeep,这样保证减少线程对CPU的抢夺。
5)线程的终止。一般要使线程体在完成一件工作的情况下终止,一般不要直接使用抛出线程异常的方式终止线程。
6)线程的优先级。一定根据程序的需要要有整体的规划。
10、什么是预编译,何时需要预编译?
预编译又称为预处理,是做些代码文本的替换工作。
处理以# 开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段。
何时需要预编译:
总是使用不经常改动的大型代码体。
11、 typedef 和 #define 有什么区别?
1)作用不同:
typedef:给已有的类型起一个类型别名。
#define:宏定义,给使用到定义的标识符进行替换。
2)执行时间不同:
typedef在编译阶段,具有类型检查动能;#define在预处理阶段,不做类型检查。
3)作用域不同:
typedef有自己的作用域;#define没有作用域限制。
4)修饰指针有差异:
typedef定义指针可以同时定义多个指针;#define宏定义的指针只能对第一个变量定义为指针。
13、谈谈内存分配方式?
物理内存映射到CPU虚拟地址空间分配方式:
内核空间1G(3G ~ 4G-1)
用户空间3G(0 ~ 3G-1):
栈stack:临时局部变量存放区。栈帧数据岁函数结束而消失。——后进先出
堆heap:动态内存区。程序运行时malloc和new动态申请的区域。——手动申请/释放
BSS:静态内存分配区。存放未初始化的全局变量。——可读可写
数据段data:静态内存分配区。存放已初始化的全局变量、静态局部变量。——可读可写
代码段text:存放程序执行代码、只读常量区域。——只读
14、Unix 中进程间通信,资源的共享,加锁机制?
进程间通信:
管道、信号、消息队列、共享内存、信号量集、套接字。
共享资源:
硬件(如uart)、文件、共享内存、线程见可见的全局变量等...
加锁机制:
多进程或多线程在同一时刻访问相同的共享资源时,需要加锁。
内核的驱动模块在运行时访问相同的共享资源时,需要加锁。
15、全局变量和局部有什么区别?是怎样实现的?操作系统和编译器是怎样知道的?
1)作用域不同:全局变量为整个程序;局部变量为当前函数或者循环;
2)生命周期不同:全局变量随程序的结束而结束,局部变量随函数或者循环的退出而释放;
3)存储方式不同:全局变量在数据段;局部变量在栈区;
4)使用方式不同:函数内部会优先使用与全局变量同名的局部变量。
怎样实现:
全局变量在编译时,由编译器分配了虚拟地址在数据段。
局部变量在程序运行时,对应使用该局部变量的函数被调用时才真正分配虚拟地址在栈区。
操作系统和编译器怎么知道:
操作系统和编译器从变量地址所属的存放区域分辨局部变量和全局变量。
16、谈谈你对大端模式,小端模式的理解
1)大小端是数据在内存中的存储方式。
大端:数据的高字节存放在内存的低地址,低字节存放在内存的高地址。
小端:数据的高低字节与内存的高低地址存放一致。
2)因为数据类型所占的bit位不同,在16bit、32bit、64位这样不同的处理器上,寄存器宽度已经大于1个字节,就要考虑如何去将多个字节安排存放的问题,因此有了大小端模式。
3)目前intel的x86平台是小端模式;
ARM平台默认是小端模式,可切换为大端;
在C语言中一般都默认是小端;
在网络中传输的数据统一是大端模式。
17、static的作用? const 作用?volatile含义?
static:
1)修饰局部变量。生命周期:当前文件<也有限定当前文件可用的效果>,作用域:当前函数
2)修饰全局变量。生命周期和作用域:当前文件 <该变量只能在本文件使用>
3)修饰函数。生命周期和作用域:当前文件 <限制函数为本模块可用>
const:
1)被const修饰的变量或者函数等,使其变为只读属性,其内容会被放在内存的代码段区域;
2)修饰指针的时候稍有不同,*号前代表指针指向的内容为只读,*号后面代表指针本身只读,不可改变指向;
3)const合理使用可以保护不希望被修改的参数,一定程度减少bug的出现。
volatile:
表示一个变量也许会被后台程序意想不到的修改。
变量如果加了volatile修饰,则会从内存重新装载内容,而不是直接从寄存器拷贝内容。
volatile可以保证对特殊地址的稳定访问。
寄存器地址要加volatile修饰,主要是因为寄存器里面的值是随时变化的。
主要用在3种情况:
1) 并行设备的硬件寄存器;
2) 中断服务子程序中会访问到的非自动变量;
3) 多线程应用中被几个任务共享的变量;
18、链表和数组有什么区别?数组与指针的区别?
数组 vs 链表:
数组的数据是顺序存储的,存储大小固定。
链表的数据可以随机存储,存储大小可以动态的改变。
数组 vs 指针:(以字符型指针变量和字符数组最能说明问题)
1)分配内存数
数组:<数据类型所占内存×下标>的字节数。指针:32bit系统,默认分配4字节存放内存地址。
2)初始化赋值
数组:将字符串放到数组分配的存储空间去。指针:先将字符串放到内存,再将该内存首地址放到指针里。
3)赋值方式
数组:数组名不能用字符串字面值直接赋值。指针:可以直接用字符串字面值赋值。
4)输入方式
数组:字符串可以直接输入到字符数组中。指针:不能将字符串直接输入指针变量,需要指针指向1块内存。
5)值的改变
数组:数组名代表的数组首地址不能改变。指针:指针变量的值可以改变,即指针改变指向。
19、队列和栈的异同?
相同点:只允许在端点处插入和删除元素的数据结构。
不同点:栈遵循后进先出原则(LIFO),队列遵循先进先出原则(FIFO)。
20、谈谈你对堆栈的理解?
1)堆栈是两种数据结构。
2)堆栈都是一种数据项按序排列的数据结构,只能在一端对数据项进行插入和删除。
3)堆:是共有的空间,全局堆和局部堆,由程序员手动分配和释放,程序结束时由系统回收。
栈:是线程独有的,保存其运行状态和局部变量的区域,由编译器自动分配和释放。
21、简述 BSS段,数据段,代码段,堆,栈中分别存储的是什么数据?
栈(stack):是用户存放程序临时创建的非静态局部变量。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
BSS段:BSS段通常是用来存放程序中未初始化的全局变量。
数据段(data):通常是用来存放程序中已初始化的全局变量。
代码段(text):通常是用来存放程序执行代码、只读常量。
22、所有的程序都要系统调用吗?不系统调用可以实现程序运行吗?
不是。如ARM裸板开发。
不系统调用可以实现系统运行,如ARM裸板下的shell程序,使用无限循环的方式实现指令输入对应调用独立实现的函数功能。
24、创建子进程的函数是什么?谈谈你对父进程和子进程间的理解?
pid_t fork (void);
成功:在父进程里子进程的pid==0被返回;
失败:在父进程里返回pid==-1,子进程没有被创建,errno被设置。
父子进程的理解:
1)【ID】父子进程ID不同;
2)【异步】子进程创建后,父子进程的执行是异步的,即调度先后顺序并不确定;
3)【代码区共享】子进程是父进程的不完全副本,代码区与父进程共享,其他数据从父进程拷贝;
4)【孤儿进程】父进程退出,但子进程还在,子进程为孤儿进程,就被1号进程收养。如系统的一些守护进程;
5)【僵尸进城】子进程结束,父进程还没来收尸,子进程就成僵尸进程,占用系统资源,直到父进程回收才释放;
25、谈谈你对排序算法的认识?你接触过那些排序算法?
排序算法认识:
即把一组数字按照某种重复执行的代码算法进行顺序排列的解决方法。
冒泡排序,快速排序。目前已掌握冒泡排序。
【嵌入式】0、你为什么学习嵌入式?嵌入式软件开发的基本模式?谈谈对嵌入式linux 系统的认识?
为什么学习:
从小喜欢四驱车之类的带电的小玩具,到如今社会的发展让智能硬件开始进入个人消费者,才真正接触到这些智能硬件的让我热血的初衷,没有什么比“使用软件来控制一个硬件”的感觉更让我有成就感。
1、系统调用与 API的区别?2、简单说一下对嵌入式的理解?对嵌入式软件开发的理解?3、简单说一下移植的流程?4、简单说一下驱动的框架结构?5、什么是中断?中断发生时 CPU做什么工作?6、简述 UART协议?7、简述 IIC协议?8、简述 1-wire协议?9、谈谈对 GPIO的认识?10、简述同步通信和异步通信?11、中断(interrupt,如键盘中断)与异常(exception,如除零异常)有何区别?12、中断和轮询哪个效率高?怎样决定是采用中断方式还是采用轮询方式去实现驱动?13、 U-boot的启动过程?14、简述 ARM-linux启动过程?15、在 linux内核中希望你的中断处理程序执行时间越短越好,但是中断处理程序要完成的功能不变,内核是通过什么机制解决矛盾?16、 Linux设备中字符设备、块设备和网络设备有什么主要的区别?17、请简述主设备号和次设备号的用途?19、驱动里面为什么要有并发、互斥的控制?如何实现?20、 Linux内核互斥机制都有哪些?21、裸版的中断和 Linux系统下的中断以及 UC 所讲的中断的异同?22、 CISC体系与 RISC 体系分别指什么?23、谈谈对中断的顶半部底半部机制的理解?24、 谈谈 ARM裸板程序怎么编程?25、 谈谈 NorFlash和 Nandflash 的区别?26、 谈谈对 ARM处理器的理解?27、 linux内核分离思想?【C++】1、谈谈你对面向对象的认识 ?2、指针和引用的区别?谈谈你对指针和引用的理解?常引用有什么作用?3、 C++中的 class和 struct 的区别?4、类成员函数的重载、覆盖和隐藏区别?5、面向对象的三个基本特征,并简单叙述乊?6、谈谈对设计模式的理解?7、关联、聚合(Aggregation)以及组合(Composition)的区别?8、谈谈你对拷贝构造函数和赋值运算符的认识?9、什么是浅拷贝?什么是深拷贝?10、 C++容器的分类及各自的特性?
新闻热点
疑难解答
图片精选