嵌入式筆試面試題目系列(匯總)
本系列按類別對題目進行分類整理,這樣有利于大家對嵌入式的筆試面試考察框架有一個完整的理解。
一、進程與線程
1、什么是進程、線程,有什么區(qū)別?
進程是資源(CPU、內存等)分配的基本單位,線程是CPU調度和分配的基本單位(程序執(zhí)行的最小單位)。同一時間,如果CPU是單核,只有一個進程在執(zhí)行,所謂的并發(fā)執(zhí)行,也是順序執(zhí)行,只不過由于切換速度太快,你以為這些進程在同步執(zhí)行而已。多核CPU可以同一時間點有多個進程在執(zhí)行。
2、多進程、多線程的優(yōu)缺點
說明:一個進程由進程控制塊、數(shù)據(jù)段、代碼段組成,進程本身不可以運行程序,而是像一個容器一樣,先創(chuàng)建出一個主線程,分配給主線程一定的系統(tǒng)資源,這時候就可以在主線程開始實現(xiàn)各種功能。當我們需要實現(xiàn)更復雜的功能時,可以在主線程里創(chuàng)建多個子線程,多個線程在同一個進程里,利用這個進程所擁有的系統(tǒng)資源合作完成某些功能。
優(yōu)缺點:1)一個進程死了不影響其他進程,一個線程崩潰很可能影響到它本身所處的整個進程。2) 創(chuàng)建多進程的系統(tǒng)花銷大于創(chuàng)建多線程。3)多進程通訊因為需要跨越進程邊界,不適合大量數(shù)據(jù)的傳送,適合小數(shù)據(jù)或者密集數(shù)據(jù)的傳送。多線程無需跨越進程邊界,適合各線程間大量數(shù)據(jù)的傳送。并且多線程可以共享同一進程里的共享內存和變量。
3、什么時候用進程,什么時候用線程
1)創(chuàng)建和銷毀較頻繁使用線程,因為創(chuàng)建進程花銷大。2)需要大量數(shù)據(jù)傳送使用線程,因為多線程切換速度快,不需要跨越進程邊界。3)安全穩(wěn)定選進程;快速頻繁選線程;
4、多進程、多線程同步(通訊)的方法
進程間通訊:
(1)有名管道/無名管道(2)信號(3)共享內存(4)消息隊列(5)信號量(6)socket
線程通訊(鎖):
(1)信號量(2)讀寫鎖(3)條件變量(4)互斥鎖(5)自旋鎖
5、進程線程的狀態(tài)轉換圖
(1)就緒狀態(tài):進程已獲得除CPU外的所有必要資源,只等待CPU時的狀態(tài)。一個系統(tǒng)會將多個處于就緒狀態(tài)的進程排成一個就緒隊列。
(2)執(zhí)行狀態(tài):進程已獲CPU,正在執(zhí)行。單處理機系統(tǒng)中,處于執(zhí)行狀態(tài)的進程只一個;多處理機系統(tǒng)中,有多個處于執(zhí)行狀態(tài)的進程。
(3)阻塞狀態(tài):正在執(zhí)行的進程由于某種原因而暫時無法繼續(xù)執(zhí)行,便放棄處理機而處于暫停狀態(tài),即進程執(zhí)行受阻。(這種狀態(tài)又稱等待狀態(tài)或封鎖狀態(tài))
通常導致進程阻塞的典型事件有:請求I/O,申請緩沖空間等。
一般,將處于阻塞狀態(tài)的進程排成一個隊列,有的系統(tǒng)還根據(jù)阻塞原因不同把這些阻塞集成排成多個隊列。

(1) 就緒→執(zhí)行
處于就緒狀態(tài)的進程,當進程調度程序為之分配了處理機后,該進程便由就緒狀態(tài)轉變成執(zhí)行狀態(tài)。
(2) 執(zhí)行→就緒
處于執(zhí)行狀態(tài)的進程在其執(zhí)行過程中,因分配給它的一個時間片已用完而不得不讓出處理機,于是進程從執(zhí)行狀態(tài)轉變成就緒狀態(tài)。
(3) 執(zhí)行→阻塞
正在執(zhí)行的進程因等待某種事件發(fā)生而無法繼續(xù)執(zhí)行時,便從執(zhí)行狀態(tài)變成阻塞狀態(tài)。
(4) 阻塞→就緒
處于阻塞狀態(tài)的進程,若其等待的事件已經(jīng)發(fā)生,于是進程由阻塞狀態(tài)轉變?yōu)榫途w狀態(tài)。
6、父進程、子進程
父進程調用fork()以后,克隆出一個子進程,子進程和父進程擁有相同內容的代碼段、數(shù)據(jù)段和用戶堆棧。父進程和子進程誰先執(zhí)行不一定,看CPU。所以我們一般我們會設置父進程等待子進程執(zhí)行完畢。
7、說明什么是上下文切換?
你可以有很多角度,有進程上下文,有中斷上下文。
進程上下文:一個進程在執(zhí)行的時候,CPU的所有寄存器中的值、進程的狀態(tài)以及堆棧中的內容,當內核需要切換到另一個進程時,它需要保存當前進程的所有狀態(tài),即保存當前進程的進程上下文,以便再次執(zhí)行該進程時,能夠恢復切換時的狀態(tài),繼續(xù)執(zhí)行。
中斷上下文:由于觸發(fā)信號,導致CPU中斷當前進程,轉而去執(zhí)行另外的程序。那么當前進程的所有資源要保存,比如堆棧和指針。保存過后轉而去執(zhí)行中斷處理程序,快讀執(zhí)行完畢返回,返回后恢復上一個進程的資源,繼續(xù)執(zhí)行。這就是中斷的上下文。
二、C/C++題目
1、new和malloc
做嵌入式,對于內存是十分在意的,因為可用內存有限,所以嵌入式筆試面試題目,內存的題目高頻。
1)malloc和free是c++/c語言的庫函數(shù),需要頭文件支持stdlib.h;new和delete是C++的關鍵字,不需要頭文件,需要編譯器支持;
2)使用new操作符申請內存分配時,無需指定內存塊的大小,編譯器會根據(jù)類型信息自行計算。而malloc則需要顯式地支持所需內存的大小。
3)new操作符內存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無需進行類型轉換,故new是符合類型安全性的操作符。而malloc內存分配成功則是返回void*,需要通過強制類型轉換將void*指針轉換成我們需要的類型。
4)new內存分配失敗時,會拋出bad_alloc異常。malloc分配內存失敗時返回NULL。
2、在1G內存的計算機中能否malloc(1.2G)?為什么?(2021浙江大華二面問題)
答:是有可能申請1.2G的內存的。
解析:回答這個問題前需要知道m(xù)alloc的作用和原理,應用程序通過malloc函數(shù)可以向程序的虛擬空間申請一塊虛擬地址空間,與物理內存沒有直接關系,得到的是在虛擬地址空間中的地址,之后程序運行所提供的物理內存是由操作系統(tǒng)完成的。
3 、extern”C” 的作用
我們可以在C++中使用C的已編譯好的函數(shù)模塊,這時候就需要用到extern”C”。也就是extern“C” 都是在c++文件里添加的。
extern在鏈接階段起作用(四大階段:預處理--編譯--匯編--鏈接)。
4、strcat、strncat、strcmp、strcpy哪些函數(shù)會導致內存溢出?如何改進?(2021浙江大華二面問題)
strcpy函數(shù)會導致內存溢出。
strcpy拷貝函數(shù)不安全,他不做任何的檢查措施,也不判斷拷貝大小,不判斷目的地址內存是否夠用。
- char *strcpy(char *strDest,const char *strSrc)
strncpy拷貝函數(shù),雖然計算了復制的大小,但是也不安全,沒有檢查目標的邊界。
- strncpy(dest, src, sizeof(dest));
strncpy_s是安全的
strcmp(str1,str2),是比較函數(shù),若str1=str2,則返回零;若str1
strncat()主要功能是在字符串的結尾追加n個字符。
- char * strncat(char *dest, const char *src, size_t n);
strcat()函數(shù)主要用來將兩個char類型連接。例如:
- char d[20]="Golden";
- char s[20]="View";
- strcat(d,s);
- //打印d
- printf("%s",d);
輸出 d 為 GoldenView (中間無空格)
延伸:
memcpy拷貝函數(shù),它與strcpy的區(qū)別就是memcpy可以拷貝任意類型的數(shù)據(jù),strcpy只能拷貝字符串類型。
memcpy 函數(shù)用于把資源內存(src所指向的內存區(qū)域)拷貝到目標內存(dest所指向的內存區(qū)域);有一個size變量控制拷貝的字節(jié)數(shù);
函數(shù)原型:
- void *memcpy(void *dest, void *src, unsigned int count);
5 、static的用法(定義和用途)(必考)
1)用static修飾局部變量:使其變?yōu)殪o態(tài)存儲方式(靜態(tài)數(shù)據(jù)區(qū)),那么這個局部變量在函數(shù)執(zhí)行完成之后不會被釋放,而是繼續(xù)保留在內存中。
2)用static修飾全局變量:使其只在本文件內部有效,而其他文件不可連接或引用該變量。
3)用static修飾函數(shù):對函數(shù)的連接方式產(chǎn)生影響,使得函數(shù)只在本文件內部有效,對其他文件是不可見的(這一點在大工程中很重要很重要,避免很多麻煩,很常見)。這樣的函數(shù)又叫作靜態(tài)函數(shù)。使用靜態(tài)函數(shù)的好處是,不用擔心與其他文件的同名函數(shù)產(chǎn)生干擾,另外也是對函數(shù)本身的一種保護機制。
6、const的用法(定義和用途)(必考)
const主要用來修飾變量、函數(shù)形參和類成員函數(shù):
1)用const修飾常量:定義時就初始化,以后不能更改。
2)用const修飾形參:func(const int a){};該形參在函數(shù)里不能改變
3)用const修飾類成員函數(shù):該函數(shù)對成員變量只能進行只讀操作,就是const類成員函數(shù)是不能修改成員變量的數(shù)值的。
被const修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。
參考一個大佬的回答:
我只要一聽到被面試者說:"const意味著常數(shù)",我就知道我正在和一個業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什么和不能做什么.如果你從沒有讀到那篇文章,只要能說出const意味著"只讀"就可以了。盡管這個答案不是完全的答案,但我接受它作為一個正確的答案。如果應試者能正確回答這個問題,我將問他一個附加的問題:下面的聲明都是什么意思?
- const int a;
- int const a;
- const int *a;
- int * const a;
- int const * a const;
前兩個的作用是一樣,a是一個常整型數(shù)。
第三個意味著a是一個指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。
第四個意思a是一個指向整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。
最后一個意味著a是一個指向常整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是不可修改的,同時指針也是不可修改的)。
7、volatile作用和用法
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量在內存中的值,而不是使用保存在寄存器里的備份(雖然讀寫寄存器比讀寫內存快)。
回答不出這個問題的人是不會被雇傭的。這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問題。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量。不懂得volatile的內容將會帶來災難。
以下幾種情況都會用到volatile:
1、并行設備的硬件寄存器(如:狀態(tài)寄存器)2、一個中斷服務子程序中會訪問到的非自動變量3、多線程應用中被幾個任務共享的變量
8、const常量和#define的區(qū)別(編譯階段、安全性、內存占用等)
用#define max 100 ; 定義的常量是沒有類型的(不進行類型安全檢查,可能會產(chǎn)生意想不到的錯誤),所給出的是一個立即數(shù),編譯器只是把所定義的常量值與所定義的常量的名字聯(lián)系起來,define所定義的宏變量在預處理階段的時候進行替換,在程序中使用到該常量的地方都要進行拷貝替換;
用const int max = 255 ; 定義的常量有類型(編譯時會進行類型檢查)名字,存放在內存的靜態(tài)區(qū)域中,在編譯時確定其值。在程序運行過程中const變量只有一個拷貝,而#define所定義的宏變量卻有多個拷貝,所以宏定義在程序運行過程中所消耗的內存要比const變量的大得多
9、變量的作用域(全局變量和局部變量)
全局變量:在所有函數(shù)體的外部定義的,程序的所在部分(甚至其它文件中的代碼)都可以使用。全局變量不受作用域的影響(也就是說,全局變量的生命期一直到程序的結束)。
局部變量:出現(xiàn)在一個作用域內,它們是局限于一個函數(shù)的。局部變量經(jīng)常被稱為自動變量,因為它們在進入作用域時自動生成,離開作用域時自動消失。關鍵字auto可以顯式地說明這個問題,但是局部變量默認為auto,所以沒有必要聲明為auto。
局部變量可以和全局變量重名,在局部變量作用域范圍內,全局變量失效,采用的是局部變量的值。
10、sizeof 與strlen (字符串,數(shù)組)
1.如果是數(shù)組
- #include<stdio.h>
- int main()
- {
- int a[5]={1,2,3,4,5};
- printf(“sizeof 數(shù)組名=%d\n”,sizeof(a));
- printf(“sizeof *數(shù)組名=%d\n”,sizeof(*a));
- }
運行結果
- sizeof 數(shù)組名=20
- sizeof *數(shù)組名=4
2.如果是指針,sizeof只會檢測到是指針的類型,指針都是占用4個字節(jié)的空間(32位機)。
sizeof是什么?是一個操作符,也是關鍵字,就不是一個函數(shù),這和strlen()不同,strlen()是一個函數(shù)。
那么sizeof的作用是什么?返回一個對象或者類型所占的內存字節(jié)數(shù)。我們會對sizeof()中的數(shù)據(jù)或者指針做運算嗎?基本不會。例如sizeof(1+2.0),直接檢測到其中類型是double,即是sizeof(double) = 8。如果是指針,sizeof只會檢測到是指針的類型,指針都是占用4個字節(jié)的空間(32位機)。
- char *p = "sadasdasd";
- sizeof(p):4
- sizeof(*p):1//指向一個char類型的
除非使用strlen(),僅對字符串有效,直到'\0'為止了,計數(shù)結果不包括\0。
要是非要使用sizeof來得到指向內容的大小,就得使用數(shù)組名才行, 如
- char a[10];
- sizeof(a):10 //檢測到a是一個數(shù)組的類型。
關于strlen(),它是一個函數(shù),考察的比較簡單:
- strlen “\n\t\tag\AAtang”
答案:11
11、經(jīng)典的sizeof(struct)和sizeof(union)內存對齊
內存對齊作用:
1.平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。
2.性能原因:數(shù)據(jù)結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。
結構體struct內存對齊的3大規(guī)則:
1.對于結構體的各個成員,第一個成員的偏移量是0,排列在后面的成員其當前偏移量必須是當前成員類型的整數(shù)倍;
2.結構體內所有數(shù)據(jù)成員各自內存對齊后,結構體本身還要進行一次內存對齊,保證整個結構體占用內存大小是結構體內最大數(shù)據(jù)成員的最小整數(shù)倍;
3.如程序中有#pragma pack(n)預編譯指令,則所有成員對齊以n字節(jié)為準(即偏移量是n的整數(shù)倍),不再考慮當前類型以及最大結構體內類型。
- #pragma pack(1)
- struct fun{
- int i;
- double d;
- char c;
- };
sizeof(fun) = 13
- struct CAT_s
- {
- int ld;
- char Color;
- unsigned short Age;
- char *Name;
- void(*Jump)(void);
- }Garfield;
1.使用32位編譯,int占4, char 占1, unsigned short 占2,char* 占4,函數(shù)指針占4個,由于是32位編譯是4字節(jié)對齊,所以該結構體占16個字節(jié)。(說明:按幾字節(jié)對齊,是根據(jù)結構體的最長類型決定的,這里是int是最長的字節(jié),所以按4字節(jié)對齊);
2.使用64位編譯 ,int占4, char 占1, unsigned short 占2,char* 占8,函數(shù)指針占8個,由于是64位編譯是8字節(jié)對齊(說明:按幾字節(jié)對齊,是根據(jù)結構體的最長類型決定的,這里是函數(shù)指針是最長的字節(jié),所以按8字節(jié)對齊)所以該結構體占24個字節(jié)。
- //64位
- struct C
- {
- double t; //8 1111 1111
- char b; //1 1
- int a; //4 0001111
- short c; //2 11000000
- };
- sizeof(C) = 24; //注意:1 4 2 不能拼在一起
char是1,然后在int之前,地址偏移量得是4的倍數(shù),所以char后面補三個字節(jié),也就是char占了4個字節(jié),然后int四個字節(jié),最后是short,只占兩個字節(jié),但是總的偏移量得是double的倍數(shù),也就是8的倍數(shù),所以short后面補六個字節(jié)
聯(lián)合體union內存對齊的2大規(guī)則:
1.找到占用字節(jié)最多的成員;
2.union的字節(jié)數(shù)必須是占用字節(jié)最多的成員的字節(jié)的倍數(shù),而且需要能夠容納其他的成員
- //x64
- typedef union {
- long i;
- int k[5];
- char c;
- }D
要計算union的大小,首先要找到占用字節(jié)最多的成員,本例中是long,占用8個字節(jié),int k[5]中都是int類型,仍然是占用4個字節(jié)的,然后union的字節(jié)數(shù)必須是占用字節(jié)最多的成員的字節(jié)的倍數(shù),而且需要能夠容納其他的成員,為了要容納k(20個字節(jié)),就必須要保證是8的倍數(shù)的同時還要大于20個字節(jié),所以是24個字節(jié)。
引申:位域(大疆筆試題)
C語言允許在一個結構體中以位為單位來指定其成員所占內存長度,這種以位為單位的成員稱為“位段”或稱“位域”( bit field) 。利用位段能夠用較少的位數(shù)存儲數(shù)據(jù)。一個位段必須存儲在同一存儲單元中,不能跨兩個單元。如果第一個單元空間不能容納下一個位段,則該空間不用,而從下一個單元起存放該位段。
1.位段聲明和結構體類似
2.位段的成員必須是int、unsigned int、signed int
3.位段的成員名后邊有一個冒號和一個數(shù)字
- typedef struct_data{
- char m:3;
- char n:5;
- short s;
- union{
- int a;
- char b;
- };
- int h;
- }_attribute_((packed)) data_t;
答案12
m和n一起,剛好占用一個字節(jié)內存,因為后面是short類型變量,所以在short s之前,應該補一個字節(jié)。所以m和n其實是占了兩個字節(jié)的,然后是short兩個個字節(jié),加起來就4個字節(jié),然后聯(lián)合體占了四個字節(jié),總共8個字節(jié)了,最后int h占了四個字節(jié),就是12個字節(jié)了
attribute((packed)) 取消對齊
GNU C的一大特色就是__attribute__機制。__attribute__可以設置函數(shù)屬性(Function Attribute)、變量屬性(Variable Attribute)和類型屬性(Type Attribute)。
__attribute__書寫特征是:__attribute__前后都有兩個下劃線,并且后面會緊跟一對括弧,括弧里面是相應的__attribute__參數(shù)。
跨平臺通信時用到。不同平臺內存對齊方式不同。如果使用結構體進行平臺間的通信,會有問題。例如,發(fā)送消息的平臺上,結構體為24字節(jié),接受消息的平臺上,此結構體為32字節(jié)(只是隨便舉個例子),那么每個變量對應的值就不對了。
不同框架的處理器對齊方式會有不同,這個時候不指定對齊的話,會產(chǎn)生錯誤結果
12、inline函數(shù)
在C語言中,如果一些函數(shù)被頻繁調用,不斷地有函數(shù)入棧,即函數(shù)棧,會造成棧空間或棧內存的大量消耗。為了解決這個問題,特別的引入了inline修飾符,表示為內聯(lián)函數(shù)。
大多數(shù)的機器上,調用函數(shù)都要做很多工作:調用前要先保存寄存器,并在返回時恢復,復制實參,程序還必須轉向一個新位置執(zhí)行C++中支持內聯(lián)函數(shù),其目的是為了提高函數(shù)的執(zhí)行效率,用關鍵字 inline 放在函數(shù)定義(注意是定義而非聲明)的前面即可將函數(shù)指定為內聯(lián)函數(shù),內聯(lián)函數(shù)通常就是將它在程序中的每個調用點上“內聯(lián)地”展開。
內聯(lián)是以代碼膨脹(復制)為代價,僅僅省去了函數(shù)調用的開銷,從而提高函數(shù)的執(zhí)行效率。
13、內存四區(qū),什么變量分別存儲在什么區(qū)域,堆上還是棧上。


文字常量區(qū),叫.rodata,不可以改變,改變會導致段錯誤
- int a0=1;
- static int a1;
- const static a2=0;
- extern int a3;
- void fun(void)
- {
- int a4;
- volatile int a5;
- return;
- }
a0 :全局初始化變量;生命周期為整個程序運行期間;作用域為所有文件;存儲位置為data段。
a1 :全局靜態(tài)未初始化變量;生命周期為整個程序運行期間;作用域為當前文件;儲存位置為BSS段。
a2 :全局靜態(tài)變量
a3 :全局初始化變量;其他同a0。
a4 :局部變量;生命周期為fun函數(shù)運行期間;作用域為fun函數(shù)內部;儲存位置為棧。
a5 :局部易變變量;
14、使用32位編譯情況下,給出判斷所使用機器大小端的方法。

聯(lián)合體方法判斷方法:利用union結構體的從低地址開始存,且同一時間內只有一個成員占有內存的特性。大端儲存符合閱讀習慣。聯(lián)合體占用內存是最大的那個,和結構體不一樣。
a和c公用同一片內存區(qū)域,所以更改c,必然會影響a的數(shù)據(jù)
- #include<stdio.h>
- int main(){
- union w
- {
- int a;
- char b;
- }c;
- c.a = 1;
- if(c.b == 1)
- printf("小端存儲\n");
- else
- printf("大端存儲\n");
- return 0;
- }
指針方法
通過將int強制類型轉換成char單字節(jié),p指向a的起始字節(jié)(低字節(jié))
- #include <stdio.h>
- int main ()
- {
- int a = 1;
- char *p = (char *)&a;
- if(*p == 1)
- {
- printf("小端存儲\n");
- }
- else
- {
- printf("大端存儲\n");
- }
- return 0;
- }
15、用變量a給出下面的定義
- a) 一個整型數(shù);
- b)一個指向整型數(shù)的指針;
- c)一個指向指針的指針,它指向的指針是指向一個整型數(shù);
- d)一個有10個整型的數(shù)組;
- e)一個有10個指針的數(shù)組,該指針是指向一個整型數(shù);
- f)一個指向有10個整型數(shù)數(shù)組的指針;
- g)一個指向函數(shù)的指針,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù);
- h)一個有10個指針的數(shù)組,該指針指向一個函數(shù),該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)
- 答案:
- a)int a
- b)int *a;
- c)int **a;
- d)int a[10];
- e)int *a [10];
- f) int a[10], *p=a;
- g)int (*a)(int)
- h) int( *a[10])(int)
16、與或非,異或。運算符優(yōu)先級
sum=a&b<
其中a=3,b=5,c=4(先加再移位再&再異或)答案4

第三章網(wǎng)絡編程
1 、TCP、UDP的區(qū)別
TCP---傳輸控制協(xié)議,提供的是面向連接、可靠的字節(jié)流服務。當客戶和服務器彼此交換數(shù)據(jù)前,必須先在雙方之間建立一個TCP連接,之后才能傳輸數(shù)據(jù)。
UDP---用戶數(shù)據(jù)報協(xié)議,是一個簡單的面向數(shù)據(jù)報的運輸層協(xié)議。UDP不提供可靠性,它只是把應用程序傳給IP層的數(shù)據(jù)報發(fā)送出去,但是并不能保證它們能到達目的地。
1)TCP是面向連接的,UDP是面向無連接的
2)UDP程序結構較簡單
3)TCP是面向字節(jié)流的,UDP是基于數(shù)據(jù)報的
4)TCP保證數(shù)據(jù)正確性,UDP可能丟包
5)TCP保證數(shù)據(jù)順序到達,UDP不保證
2 、TCP、UDP的優(yōu)缺點
TCP優(yōu)點:可靠穩(wěn)定
TCP的可靠體現(xiàn)在TCP在傳輸數(shù)據(jù)之前,會有三次握手來建立連接,而且在數(shù)據(jù)傳遞時,有確認、窗口、重傳、擁塞控制機制,在數(shù)據(jù)傳完之后,還會斷開來連接用來節(jié)約系統(tǒng)資源。
TCP缺點:慢,效率低,占用系統(tǒng)資源高,易被攻擊
在傳遞數(shù)據(jù)之前要先建立連接,這會消耗時間,而且在數(shù)據(jù)傳遞時,確認機制、重傳機制、擁塞機制等都會消耗大量時間,而且要在每臺設備上維護所有的傳輸連接。然而,每個連接都會占用系統(tǒng)的CPU,內存等硬件資源。因為TCP有確認機制、三次握手機制,這些也導致TCP容易被利用,實現(xiàn)DOS、DDOS、CC等攻擊。
UDP優(yōu)點:快,比TCP稍安全
UDP沒有TCP擁有的各種機制,是一種無狀態(tài)的傳輸協(xié)議,所以傳輸數(shù)據(jù)非常快,沒有TCP的這些機制,被攻擊利用的機會就少一些,但是也無法避免被攻擊。
UDP缺點:不可靠,不穩(wěn)定
因為沒有TCP的這些機制,UDP在傳輸數(shù)據(jù)時,如果網(wǎng)絡質量不好,就會很容易丟包,造成數(shù)據(jù)的缺失。
3 、TCP UDP適用場景
TCP:傳輸一些對信號完整性,信號質量有要求的信息。
UDP:對網(wǎng)絡通訊質量要求不高時,要求網(wǎng)絡通訊速度要快的場景。
4、 TCP為什么是可靠連接?
因為tcp傳輸?shù)臄?shù)據(jù)滿足3大條件,不丟失,不重復,按順序到達。
5、OSI典型網(wǎng)絡模型,簡單說說有哪些

6、三次握手、四次揮手
三次握手

1、TCP服務器進程先創(chuàng)建傳輸控制塊TCB,時刻準備接受客戶進程的連接請求,此時服務器就進入了LISTEN(監(jiān)聽)狀態(tài);
2、TCP客戶進程也是先創(chuàng)建傳輸控制塊TCB,然后向服務器發(fā)出連接請求報文,這是報文首部中的同部位SYN=1,同時選擇一個初始序列號 seq=x ,此時,TCP客戶端進程進入了 SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)。TCP規(guī)定,SYN報文段(SYN=1的報文段)不能攜帶數(shù)據(jù),但需要消耗掉一個序號。
3、TCP服務器收到請求報文后,如果同意連接,則發(fā)出確認報文。確認報文中應該 ACK=1,SYN=1,確認號是ack=x+1,同時也要為自己初始化一個序列號 seq=y,此時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態(tài)。這個報文也不能攜帶數(shù)據(jù),但是同樣要消耗一個序號。
4、TCP客戶進程收到確認后,還要向服務器給出確認。確認報文的ACK=1,ack=y+1,自己的序列號seq=x+1,此時,TCP連接建立,客戶端進入ESTABLISHED(已建立連接)狀態(tài)。TCP規(guī)定,ACK報文段可以攜帶數(shù)據(jù),但是如果不攜帶數(shù)據(jù)則不消耗序號。
5、當服務器收到客戶端的確認后也進入ESTABLISHED狀態(tài),此后雙方就可以開始通信了。
四次揮手

1、客戶端進程發(fā)出連接釋放報文,并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報文首部,F(xiàn)IN=1,其序列號為seq=u(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個字節(jié)的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態(tài)。TCP規(guī)定,F(xiàn)IN報文段即使不攜帶數(shù)據(jù),也要消耗一個序號。
2、服務器收到連接釋放報文,發(fā)出確認報文,ACK=1,ack=u+1,并且?guī)献约旱男蛄刑杝eq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態(tài)。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處于半關閉狀態(tài),即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是服務器若發(fā)送數(shù)據(jù),客戶端依然要接受。這個狀態(tài)還要持續(xù)一段時間,也就是整個CLOSE-WAIT狀態(tài)持續(xù)的時間。
3、客戶端收到服務器的確認請求后,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態(tài),等待服務器發(fā)送連接釋放報文(在這之前還需要接受服務器發(fā)送的最后的數(shù)據(jù))。
4、服務器將最后的數(shù)據(jù)發(fā)送完畢后,就向客戶端發(fā)送連接釋放報文,F(xiàn)IN=1,ack=u+1,由于在半關閉狀態(tài),服務器很可能又發(fā)送了一些數(shù)據(jù),假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最后確認)狀態(tài),等待客戶端的確認。
5、客戶端收到服務器的連接釋放報文后,必須發(fā)出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態(tài)。注意此時TCP連接還沒有釋放,必須經(jīng)過2∗ *∗MSL(最長報文段壽命)的時間后,當客戶端撤銷相應的TCB后,才進入CLOSED狀態(tài)。
6、服務器只要收到了客戶端發(fā)出的確認,立即進入CLOSED狀態(tài)。同樣,撤銷TCB后,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些。
第四章常見算法
十種常見排序算法可以分為兩大類:
非線性時間比較類排序:通過比較來決定元素間的相對次序,由于其時間復雜度不能突破O(nlogn),因此稱為非線性時間比較類排序。
線性時間非比較類排序:不通過比較來決定元素間的相對次序,它可以突破基于比較排序的時間下界,以線性時間運行,因此稱為線性時間非比較類排序。

算法優(yōu)劣評價術語
穩(wěn)定性:
穩(wěn)定:如果 a 原本在 b 前面,而 a = b,排序之后 a 仍然在 b 的前面;
不穩(wěn)定:如果 a 原本在 b 的前面,而 a = b,排序之后 a 可能會出現(xiàn)在 b 的后面;
排序方式:
內排序:所有排序操作都在內存中完成,占用常數(shù)內存,不占用額外內存。
外排序:由于數(shù)據(jù)太大,因此把數(shù)據(jù)放在磁盤中,而排序通過磁盤和內存的數(shù)據(jù)傳輸才能進行,占用額外內存。
復雜度:
時間復雜度: 一個算法執(zhí)行所耗費的時間。
空間復雜度: 運行完一個程序所需內存的大小。


至于各種算法的原理以及代碼實現(xiàn),由于太多并且比較復雜,不在本文列出。但推薦兩本入門的書:《啊哈!算法》、《大話數(shù)據(jù)結構》。電子版我會發(fā)在交流群里。
排序算法很多,嵌入式要求的不會太多,你會冒泡排序、快速排序、插入排序就可以解決很多問題。難的比如動態(tài)規(guī)劃問題,圖的路徑問題,嵌入式考的比較少,純軟才會考這些。(大公司和獨角獸公司考的會相對難一些)
第五章Linux操作系統(tǒng)題目
1、 Linux內核的組成部分
Linux內核主要由五個子系統(tǒng)組成:進程調度,內存管理,虛擬文件系統(tǒng),網(wǎng)絡接口,進程間通信。

2、Linux系統(tǒng)的組成部分
Linux系統(tǒng)一般有4個主要部分:
內核、shell、文件系統(tǒng)和應用程序。

3、用戶空間與內核通信方式有哪些?
1)系統(tǒng)調用。用戶空間進程通過系統(tǒng)調用進入內核空間,訪問指定的內核空間數(shù)據(jù);
2)驅動程序。用戶空間進程可以使用封裝后的系統(tǒng)調用接口訪問驅動設備節(jié)點,以和運行在內核空間的驅動程序通信;
3)共享內存mmap。在代碼中調用接口,實現(xiàn)內核空間與用戶空間的地址映射,在實時性要求很高的項目中為首選,省去拷貝數(shù)據(jù)的時間等資源,但缺點是不好控制;
4)copy_to_user()、copy_from_user(),是在驅動程序中調用接口,實現(xiàn)用戶空間與內核空間的數(shù)據(jù)拷貝操作,應用于實時性要求不高的項目中。
以及:
- procfs(/proc)
- sysctl (/proc/sys)
- sysfs(/sys)
- netlink 套接口
4、系統(tǒng)調用與普通函數(shù)調用的區(qū)別
系統(tǒng)調用:
1.使用INT和IRET指令,內核和應用程序使用的是不同的堆棧,因此存在堆棧的切換,從用戶態(tài)切換到內核態(tài),從而可以使用特權指令操控設備
2.依賴于內核,不保證移植性
3.在用戶空間和內核上下文環(huán)境間切換,開銷較大
4.是操作系統(tǒng)的一個入口點
普通函數(shù)調用:
1.使用CALL和RET指令,調用時沒有堆棧切換
2.平臺移植性好
3.屬于過程調用,調用開銷較小
4.一個普通功能函數(shù)的調用
5、內核態(tài),用戶態(tài)的區(qū)別
內核態(tài),操作系統(tǒng)在內核態(tài)運行——運行操作系統(tǒng)程序
用戶態(tài),應用程序只能在用戶態(tài)運行——運行用戶程序
當一個進程在執(zhí)行用戶自己的代碼時處于用戶運行態(tài)(用戶態(tài)),此時特權級最低,為3級,是普通的用戶進程運行的特權級,大部分用戶直接面對的程序都是運行在用戶態(tài)。Ring3狀態(tài)不能訪問Ring0的地址空間,包括代碼和數(shù)據(jù);當一個進程因為系統(tǒng)調用陷入內核代碼中執(zhí)行時處于內核運行態(tài)(內核態(tài)),此時特權級最高,為0級。執(zhí)行的內核代碼會使用當前進程的內核棧,每個進程都有自己的內核棧。
6、 bootloader、內核 、根文件的關系
啟動順序:bootloader->linux kernel->rootfile->app
Bootloader全名為啟動引導程序,是第一段代碼,它主要用來初始化處理器及外設,然后調用Linux內核。Linux內核在完成系統(tǒng)的初始化之后需要掛載某個文件系統(tǒng)作為根文件系統(tǒng)(RootFilesystem),然后加載必要的內核模塊,啟動應用程序。(一個嵌入式Linux系統(tǒng)從軟件角度看可以分為四個部分:引導加載程序(Bootloader),Linux內核,文件系統(tǒng),應用程序。)
7 、Bootloader啟動的兩個階段:
Stage1:匯編語言
1)基本的硬件初始化(關閉看門狗和中斷,MMU(帶操作系統(tǒng)),CACHE。配置系統(tǒng)工作時鐘)
2)為加載stage2準備RAM空間
3)拷貝內核映像和文件系統(tǒng)映像到RAM中
4)設置堆棧指針sp
5)跳到stage2的入口點
Stage2:c語言
1)初始化本階段要使用到的硬件設備(led uart等)
2)檢測系統(tǒng)的內存映射
3)加載內核映像和文件系統(tǒng)映像
4)設置內核的啟動參數(shù)
嵌入式系統(tǒng)中廣泛采用的非易失性存儲器通常是Flash,而Bootloader就位于該存儲器的最前端,所以系統(tǒng)上電或復位后執(zhí)行的第一段程序便是Bootloader。
8、 linux下檢查內存狀態(tài)的命令
- 1)查看進程:top
- 2)查看內存:free
- 3)cat /proc/meminfo
- 4)vmstat
假如一個公司服務器有很多用戶,你使用top命令,可以看到哪個同事在使用什么命令,做什么事情,占用了多少CPU。
9 、一個程序從開始運行到結束的完整過程(四個過程)
預處理(Pre-Processing)、編譯(Compiling)、匯編(Assembling)、鏈接(Linking)
10、什么是堆,棧,內存泄漏和內存溢出?
棧由系統(tǒng)操作,程序員不可以操作。
所以內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完后必須顯式釋放的內存。應用程序一般使用malloc,new等函數(shù)從堆中分配到一塊內存,使用完后,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用。
內存溢出:你要求分配的內存超出了系統(tǒng)能給你的,系統(tǒng)不能滿足需求,于是產(chǎn)生溢出。
內存越界:向系統(tǒng)申請了一塊內存,而在使用內存時,超出了申請的范圍(常見的有使用特定大小數(shù)組時發(fā)生內存越界)
內存溢出問題是 C 語言或者 C++ 語言所固有的缺陷,它們既不檢查數(shù)組邊界,又不檢查類型可靠性(type-safety)。眾所周知,用 C/C++ 語言開發(fā)的程序由于目標代碼非常接近機器內核,因而能夠直接訪問內存和寄存器,這種特性大大提升了 C/C++ 語言代碼的性能。只要合理編碼,C/C++ 應用程序在執(zhí)行效率上必然優(yōu)于其它高級語言。然而,C/C++ 語言導致內存溢出問題的可能性也要大許多。
11、死鎖的原因、條件
產(chǎn)生死鎖的原因主要是:
(1) 因為系統(tǒng)資源不足。
(2) 進程運行推進的順序不合適。
(3) 資源分配不當?shù)取?/p>
如果系統(tǒng)資源充足,進程的資源請求都能夠得到滿足,死鎖出現(xiàn)的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產(chǎn)生死鎖
這四個條件是死鎖的必要條件,只要系統(tǒng)發(fā)生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發(fā)生死鎖。
(1) 互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 循環(huán)等待條件:若干進程之間形成一種頭尾相接的循環(huán)等待資源關系。
12、硬鏈接與軟鏈接
鏈接操作實際上是給系統(tǒng)中已有的某個文件指定另外一個可用于訪問它的名稱。對于這個新的文件名,我們可以為之指定不同的訪問權限,以控制對信息的共享和安全性的問題。如果鏈接指向目錄,用戶就可以利用該鏈接直接進入被鏈接的目錄而不用打一大堆的路徑名。而且,即使我們刪除這個鏈接,也不會破壞原來的目錄。
1>硬鏈接
硬鏈接只能引用同一文件系統(tǒng)中的文件。它引用的是文件在文件系統(tǒng)中的物理索引(也稱為inode)。當您移動或刪除原始文件時,硬鏈接不會被破壞,因為它所引用的是文件的物理數(shù)據(jù)而不是文件在文件結構中的位置。硬鏈接的文件不需要用戶有訪問原始文件的權限,也不會顯示原始文件的位置,這樣有助于文件的安全。如果您刪除的文件有相應的硬鏈接,那么這個文件依然會保留,直到所有對它的引用都被刪除。
2>軟鏈接(符號鏈接)
軟連接,其實就是新建立一個文件,這個文件就是專門用來指向別的文件的(那就和windows 下的快捷方式的那個文件有很接近的意味)。軟連接產(chǎn)生的是一個新的文件,但這個文件的作用就是專門指向某個文件的,刪了這個軟連接文件,那就等于不需要這個連接,和原來的存在的實體原文件沒有任何關系,但刪除原來的文件,則相應的軟連接不可用。
13、計算機中,32bit與64bit有什么區(qū)別
64bit計算主要有兩大優(yōu)點:可以進行更大范圍的整數(shù)運算;可以支持更大的內存。
64位操作系統(tǒng)下的虛擬內存空間大小:地址空間大小不是2^32,也不是2^64,而一般是2^48。因為并不需要2^64那么大的尋址空間,過大的空間只會造成資源的浪費。所以64位Linux一般使用48位表示虛擬空間地址,40位標識物理地址。
14、中斷和異常的區(qū)別
內中斷:同步中斷(異常)是由cpu內部的電信號產(chǎn)生的中斷,其特點為當前執(zhí)行的指令結束后才轉而產(chǎn)生中斷,由于有cpu主動產(chǎn)生,其執(zhí)行點必然是可控的。
外中斷:異步中斷是由cpu的外設產(chǎn)生的電信號引起的中斷,其發(fā)生的時間點不可預期。
15、中斷怎么發(fā)生,中斷處理流程
請求中斷→響應中斷→關閉中斷→保留斷點→中斷源識別→保護現(xiàn)場→中斷服務子程序→恢復現(xiàn)場→中斷返回。

16、 Linux 操作系統(tǒng)掛起、休眠、關機相關命令
關機命令有halt, init 0, poweroff ,shutdown -h 時間,其中shutdown是最安全的
重啟命令有reboot,init 6,,shutdow -r時間
在linux命令中reboot是重新啟動,shutdown -r now是立即停止然后重新啟動
具體可用參數(shù)可以百度。
17、說一個linux下編譯優(yōu)化選項:
加:-o
18、在有數(shù)據(jù)cache情況下,DMA數(shù)據(jù)鏈路為:
外設-DMA-DDR-cache-CPU
19、linux命令
1、改變文件屬性的命令:chmod (chmod 777 /etc/squid 運行命令后,squid文件夾(目錄)的權限就被修改為777(可讀可寫可執(zhí)行))
2、查找文件中匹配字符串的命令:grep
3、查找當前目錄:pwd
4、刪除目錄:rm -rf 目錄名
5、刪除文件:rm 文件名
6、創(chuàng)建目錄(文件夾):mkdir
7、創(chuàng)建文件:touch
8、vi和vim 文件名也可以創(chuàng)建
9、解壓:tar -xzvf 壓縮包
打包:tar -cvzf 目錄(文件夾)
10、查看進程對應的端口號
- 1、先查看進程pid
- ps -ef | grep 進程名
- 2、通過pid查看占用端口
- netstat -nap | grep 進程pid
20、硬實時系統(tǒng)和軟實時系統(tǒng)
軟實時系統(tǒng):
Windows、Linux系統(tǒng)通常為軟實時,當然有補丁可以將內核做成硬實時的系統(tǒng),不過商用沒有這么做的。
硬實時系統(tǒng):
對時間要求很高,限定時間內不管做沒做完必須返回。
VxWorks,uCOS,F(xiàn)reeRTOS,WinCE,RT-thread等實時系統(tǒng);
21、MMU基礎
現(xiàn)代操作系統(tǒng)普遍采用虛擬內存管理(Virtual Memory Management) 機制,這需要MMU( Memory Management Unit,內存管理單元) 的支持。有些嵌入式處理器沒有MMU,則不能運行依賴于虛擬內存管理的操作系統(tǒng)。
也就是說:操作系統(tǒng)可以分成兩類,用MMU的、不用MMU的。
用MMU的是:Windows、MacOS、Linux、Android;不用MMU的是:FreeRTOS、VxWorks、UCOS……
與此相對應的:CPU也可以分成兩類,帶MMU的、不帶MMU的。
帶MMU的是:Cortex-A系列、ARM9、ARM11系列;
不帶MMU的是:Cortex-M系列……(STM32是M系列,沒有MMU,不能運行Linux,只能運行一些UCOS、FreeRTOS等等)。
MMU就是負責虛擬地址(virtual address)轉化成物理地址(physical address),轉換過程比較復雜,可以自行百度。
第六章 單片機常見面試題
1、ROM與RAM
這一點我另一篇文章講解過,這里放鏈接:
ROM與RAM的區(qū)別
2、 IO口工作方式(學過STM32的人應該很熟悉)
上拉輸入、下拉輸入、推挽輸出、開漏輸出。
3、請說明總線接口USRT、I2C、USB的異同點
(串/并、速度、全/半雙工、總線拓撲等)

4、IIC協(xié)議時序圖
必須會畫出來,我面試被問到過,讓我畫,我畫了個大概。
IIC協(xié)議有兩根線,一根SCL時鐘線,一根SDA數(shù)據(jù)線,如圖可以看到開始信號和結束信號的電平狀態(tài)。開始后,因為IIC總線可以掛在很多設備(不超過8個),所以先發(fā)送一個設備地址,選中這個設備,設備地址最后一位代表了是寫還是讀。選中設備后,再發(fā)送寄存器地址,代表選中某個寄存器,再開始傳輸數(shù)據(jù)。
八位設備地址=7位從機地址+讀/寫地址,
再給地址添加一個方向位位用來表示接下來數(shù)據(jù)傳輸?shù)姆较颍?/p>
0表示主設備向從設備(write)寫數(shù)據(jù),
1表示主設備向從設備(read)讀數(shù)據(jù)

開始信號:SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送數(shù)據(jù)。
結束信號:SCL 為高電平時,SDA 由低電平向高電平跳變,結束傳送數(shù)據(jù)。
應答信號:接收數(shù)據(jù)的 IC 在接收到 8bit 數(shù)據(jù)后,向發(fā)送數(shù)據(jù)的 IC 發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù)。CPU 向受控單元發(fā)出一個信號后,等待受控單元發(fā)出一個應答信號,CPU 接收到應答信號后,根據(jù)實際情況作出是否繼續(xù)傳遞信號的判斷。若未收到應答信號,由判斷為受控單元出現(xiàn)故障。
IIC信號在數(shù)據(jù)傳輸過程中,當SCL=1高電平時,數(shù)據(jù)線SDA必須保持穩(wěn)定狀態(tài),不允許有電平跳變,只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。SCL=1時 數(shù)據(jù)線SDA的任何電平變換會看做是總線的起始信號或者停止信號。
IIC我也有一篇文章有講解,請看鏈接:
IIC總線最多可以掛多少個設備
5、單片機的SP指針始終指向
棧頂
6、IIC總線在傳送數(shù)據(jù)過程中共有三種類型信號:
它們分別是:開始信號、結束信號和應答信號。
7、FIQ中斷向量入口地址:
FIQ和IRQ是兩種不同類型的中斷,ARM為了支持這兩種不同的中斷,提供了對應的叫做FIQ和IRQ處理器模式(ARM有7種處理模式)。
FIQ的中斷向量地址在0x0000001C,而IRQ的在0x00000018。
8、SPI四種模式,簡述其中一種模式,畫出時序圖
在芯片資料上極性和相位一般表示為CPOL(Clock POLarity)和CPHA(Clock PHAse), 極性和相位組合成4種工作模式。

spi四種模式SPI的相位(CPHA)和極性(CPOL)分別可以為0或1,對應的4種組合構成了SPI的4種模式(mode)
Mode 0 CPOL=0, CPHA=0
Mode 1 CPOL=0, CPHA=1
Mode 2 CPOL=1, CPHA=0
Mode 3 CPOL=1, CPHA=1
時鐘極性CPOL: 即SPI空閑時,時鐘信號SCLK的電平(1:空閑時高電平; 0:空閑時低電平) 時鐘相位CPHA: 即SPI在SCLK第幾個邊沿開始采樣(0:第一個邊沿開始; 1:第二個邊沿開始)
sd卡的spi常用的是mode 0 和mode 3,這兩種模式的相同的地方是都在時鐘上升沿采樣傳輸數(shù)據(jù),區(qū)別這兩種方式的簡單方法就是看空閑時,時鐘的電平狀態(tài),低電平為mode 0 ,高電平為mode 3。
具體的通信過程請自行百度,2021年秋招大疆筆試題考了這道題。
第七章 雜項面試題
1、講一講馮諾依曼和哈佛體系的區(qū)別
哈佛結構是一種將程序指令存儲和數(shù)據(jù)存儲分開的存儲器結構。目前使用哈佛結構的中央處理器和微控制器有很多,ARM9、ARM10和ARM11,51單片機屬于哈佛結構。
馮·諾伊曼結構也稱普林斯頓結構,是一種將程序指令存儲器和數(shù)據(jù)存儲器合并在一起的存儲器結構。
2、面向對象編程的三大特性
以及重載的意思。重載,是指允許存在多個同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。
3、http默認端口號
80
4、linux中mysql數(shù)據(jù)庫默認的端口是
3306
5、編程習慣小知識點
C語言編程中,單片機平臺,一般有.c和.h文件,如果一個人在.h文件中定義了一個變量,會有什么后果。(討論編程習慣的問題,我一般是只在.h文件中聲明函數(shù),不會做變量定義;另外,編程中每一個模塊都會有對應的.c和.h文件,最終的總程序自己定義一個comm.c和comm.h去調用各個模塊,這樣的習慣我覺得還行)
if語句中如果是或運算( | ),第一個條件滿足時,第二個條件還會判斷嗎。或運算的話,當然不會,因為 0|1=1,中斷了