自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

嵌入式筆試面試題目系列(匯總)

系統(tǒng) Linux
本系列按類別對(duì)題目進(jìn)行分類整理,這樣有利于大家對(duì)嵌入式的筆試面試考察框架有一個(gè)完整的理解。

[[377628]]

 本系列按類別對(duì)題目進(jìn)行分類整理,這樣有利于大家對(duì)嵌入式的筆試面試考察框架有一個(gè)完整的理解。

一、進(jìn)程與線程

1、什么是進(jìn)程、線程,有什么區(qū)別?

進(jìn)程是資源(CPU、內(nèi)存等)分配的基本單位,線程是CPU調(diào)度和分配的基本單位(程序執(zhí)行的最小單位)。同一時(shí)間,如果CPU是單核,只有一個(gè)進(jìn)程在執(zhí)行,所謂的并發(fā)執(zhí)行,也是順序執(zhí)行,只不過(guò)由于切換速度太快,你以為這些進(jìn)程在同步執(zhí)行而已。多核CPU可以同一時(shí)間點(diǎn)有多個(gè)進(jìn)程在執(zhí)行。

2、多進(jìn)程、多線程的優(yōu)缺點(diǎn)

說(shuō)明:一個(gè)進(jìn)程由進(jìn)程控制塊、數(shù)據(jù)段、代碼段組成,進(jìn)程本身不可以運(yùn)行程序,而是像一個(gè)容器一樣,先創(chuàng)建出一個(gè)主線程,分配給主線程一定的系統(tǒng)資源,這時(shí)候就可以在主線程開(kāi)始實(shí)現(xiàn)各種功能。當(dāng)我們需要實(shí)現(xiàn)更復(fù)雜的功能時(shí),可以在主線程里創(chuàng)建多個(gè)子線程,多個(gè)線程在同一個(gè)進(jìn)程里,利用這個(gè)進(jìn)程所擁有的系統(tǒng)資源合作完成某些功能。

優(yōu)缺點(diǎn):1)一個(gè)進(jìn)程死了不影響其他進(jìn)程,一個(gè)線程崩潰很可能影響到它本身所處的整個(gè)進(jìn)程。2) 創(chuàng)建多進(jìn)程的系統(tǒng)花銷大于創(chuàng)建多線程。3)多進(jìn)程通訊因?yàn)樾枰缭竭M(jìn)程邊界,不適合大量數(shù)據(jù)的傳送,適合小數(shù)據(jù)或者密集數(shù)據(jù)的傳送。多線程無(wú)需跨越進(jìn)程邊界,適合各線程間大量數(shù)據(jù)的傳送。并且多線程可以共享同一進(jìn)程里的共享內(nèi)存和變量。

3、什么時(shí)候用進(jìn)程,什么時(shí)候用線程

1)創(chuàng)建和銷毀較頻繁使用線程,因?yàn)閯?chuàng)建進(jìn)程花銷大。2)需要大量數(shù)據(jù)傳送使用線程,因?yàn)槎嗑€程切換速度快,不需要跨越進(jìn)程邊界。3)安全穩(wěn)定選進(jìn)程;快速頻繁選線程;

4、多進(jìn)程、多線程同步(通訊)的方法

進(jìn)程間通訊:

(1)有名管道/無(wú)名管道(2)信號(hào)(3)共享內(nèi)存(4)消息隊(duì)列(5)信號(hào)量(6)socket

線程通訊(鎖):

(1)信號(hào)量(2)讀寫(xiě)鎖(3)條件變量(4)互斥鎖(5)自旋鎖

5、進(jìn)程線程的狀態(tài)轉(zhuǎn)換圖

(1)就緒狀態(tài):進(jìn)程已獲得除CPU外的所有必要資源,只等待CPU時(shí)的狀態(tài)。一個(gè)系統(tǒng)會(huì)將多個(gè)處于就緒狀態(tài)的進(jìn)程排成一個(gè)就緒隊(duì)列。

(2)執(zhí)行狀態(tài):進(jìn)程已獲CPU,正在執(zhí)行。單處理機(jī)系統(tǒng)中,處于執(zhí)行狀態(tài)的進(jìn)程只一個(gè);多處理機(jī)系統(tǒng)中,有多個(gè)處于執(zhí)行狀態(tài)的進(jìn)程。

(3)阻塞狀態(tài):正在執(zhí)行的進(jìn)程由于某種原因而暫時(shí)無(wú)法繼續(xù)執(zhí)行,便放棄處理機(jī)而處于暫停狀態(tài),即進(jìn)程執(zhí)行受阻。(這種狀態(tài)又稱等待狀態(tài)或封鎖狀態(tài))

通常導(dǎo)致進(jìn)程阻塞的典型事件有:請(qǐng)求I/O,申請(qǐng)緩沖空間等。

一般,將處于阻塞狀態(tài)的進(jìn)程排成一個(gè)隊(duì)列,有的系統(tǒng)還根據(jù)阻塞原因不同把這些阻塞集成排成多個(gè)隊(duì)列。


(1) 就緒→執(zhí)行

處于就緒狀態(tài)的進(jìn)程,當(dāng)進(jìn)程調(diào)度程序?yàn)橹峙淞颂幚頇C(jī)后,該進(jìn)程便由就緒狀態(tài)轉(zhuǎn)變成執(zhí)行狀態(tài)。

(2) 執(zhí)行→就緒

處于執(zhí)行狀態(tài)的進(jìn)程在其執(zhí)行過(guò)程中,因分配給它的一個(gè)時(shí)間片已用完而不得不讓出處理機(jī),于是進(jìn)程從執(zhí)行狀態(tài)轉(zhuǎn)變成就緒狀態(tài)。

(3) 執(zhí)行→阻塞

正在執(zhí)行的進(jìn)程因等待某種事件發(fā)生而無(wú)法繼續(xù)執(zhí)行時(shí),便從執(zhí)行狀態(tài)變成阻塞狀態(tài)。

(4) 阻塞→就緒

處于阻塞狀態(tài)的進(jìn)程,若其等待的事件已經(jīng)發(fā)生,于是進(jìn)程由阻塞狀態(tài)轉(zhuǎn)變?yōu)榫途w狀態(tài)。

6、父進(jìn)程、子進(jìn)程

父進(jìn)程調(diào)用fork()以后,克隆出一個(gè)子進(jìn)程,子進(jìn)程和父進(jìn)程擁有相同內(nèi)容的代碼段、數(shù)據(jù)段和用戶堆棧。父進(jìn)程和子進(jìn)程誰(shuí)先執(zhí)行不一定,看CPU。所以我們一般我們會(huì)設(shè)置父進(jìn)程等待子進(jìn)程執(zhí)行完畢。

7、說(shuō)明什么是上下文切換?

你可以有很多角度,有進(jìn)程上下文,有中斷上下文。

進(jìn)程上下文:一個(gè)進(jìn)程在執(zhí)行的時(shí)候,CPU的所有寄存器中的值、進(jìn)程的狀態(tài)以及堆棧中的內(nèi)容,當(dāng)內(nèi)核需要切換到另一個(gè)進(jìn)程時(shí),它需要保存當(dāng)前進(jìn)程的所有狀態(tài),即保存當(dāng)前進(jìn)程的進(jìn)程上下文,以便再次執(zhí)行該進(jìn)程時(shí),能夠恢復(fù)切換時(shí)的狀態(tài),繼續(xù)執(zhí)行。

中斷上下文:由于觸發(fā)信號(hào),導(dǎo)致CPU中斷當(dāng)前進(jìn)程,轉(zhuǎn)而去執(zhí)行另外的程序。那么當(dāng)前進(jìn)程的所有資源要保存,比如堆棧和指針。保存過(guò)后轉(zhuǎn)而去執(zhí)行中斷處理程序,快讀執(zhí)行完畢返回,返回后恢復(fù)上一個(gè)進(jìn)程的資源,繼續(xù)執(zhí)行。這就是中斷的上下文。

二、C/C++題目

1、new和malloc

做嵌入式,對(duì)于內(nèi)存是十分在意的,因?yàn)榭捎脙?nèi)存有限,所以嵌入式筆試面試題目,內(nèi)存的題目高頻。

1)malloc和free是c++/c語(yǔ)言的庫(kù)函數(shù),需要頭文件支持stdlib.h;new和delete是C++的關(guān)鍵字,不需要頭文件,需要編譯器支持;

2)使用new操作符申請(qǐng)內(nèi)存分配時(shí),無(wú)需指定內(nèi)存塊的大小,編譯器會(huì)根據(jù)類型信息自行計(jì)算。而malloc則需要顯式地支持所需內(nèi)存的大小。

3)new操作符內(nèi)存分配成功時(shí),返回的是對(duì)象類型的指針,類型嚴(yán)格與對(duì)象匹配,無(wú)需進(jìn)行類型轉(zhuǎn)換,故new是符合類型安全性的操作符。而malloc內(nèi)存分配成功則是返回void*,需要通過(guò)強(qiáng)制類型轉(zhuǎn)換將void*指針轉(zhuǎn)換成我們需要的類型。

4)new內(nèi)存分配失敗時(shí),會(huì)拋出bad_alloc異常。malloc分配內(nèi)存失敗時(shí)返回NULL。

2、在1G內(nèi)存的計(jì)算機(jī)中能否malloc(1.2G)?為什么?(2021浙江大華二面問(wèn)題)

答:是有可能申請(qǐng)1.2G的內(nèi)存的。

解析:回答這個(gè)問(wèn)題前需要知道m(xù)alloc的作用和原理,應(yīng)用程序通過(guò)malloc函數(shù)可以向程序的虛擬空間申請(qǐng)一塊虛擬地址空間,與物理內(nèi)存沒(méi)有直接關(guān)系,得到的是在虛擬地址空間中的地址,之后程序運(yùn)行所提供的物理內(nèi)存是由操作系統(tǒng)完成的。

3 、extern”C” 的作用

我們可以在C++中使用C的已編譯好的函數(shù)模塊,這時(shí)候就需要用到extern”C”。也就是extern“C” 都是在c++文件里添加的。

extern在鏈接階段起作用(四大階段:預(yù)處理--編譯--匯編--鏈接)。

4、strcat、strncat、strcmp、strcpy哪些函數(shù)會(huì)導(dǎo)致內(nèi)存溢出?如何改進(jìn)?(2021浙江大華二面問(wèn)題)

strcpy函數(shù)會(huì)導(dǎo)致內(nèi)存溢出。

strcpy拷貝函數(shù)不安全,他不做任何的檢查措施,也不判斷拷貝大小,不判斷目的地址內(nèi)存是否夠用。

  1. char *strcpy(char *strDest,const char *strSrc) 

strncpy拷貝函數(shù),雖然計(jì)算了復(fù)制的大小,但是也不安全,沒(méi)有檢查目標(biāo)的邊界。

  1. strncpy(dest, src, sizeof(dest));  

strncpy_s是安全的

strcmp(str1,str2),是比較函數(shù),若str1=str2,則返回零;若str1

strncat()主要功能是在字符串的結(jié)尾追加n個(gè)字符。

  1. char * strncat(char *dest, const char *src, size_t n); 

strcat()函數(shù)主要用來(lái)將兩個(gè)char類型連接。例如:

  1. char d[20]="Golden"
  2. char s[20]="View"
  3. strcat(d,s); 
  4. //打印d 
  5. printf("%s",d); 

輸出 d 為 GoldenView (中間無(wú)空格)

延伸:

memcpy拷貝函數(shù),它與strcpy的區(qū)別就是memcpy可以拷貝任意類型的數(shù)據(jù),strcpy只能拷貝字符串類型。

memcpy 函數(shù)用于把資源內(nèi)存(src所指向的內(nèi)存區(qū)域)拷貝到目標(biāo)內(nèi)存(dest所指向的內(nèi)存區(qū)域);有一個(gè)size變量控制拷貝的字節(jié)數(shù);

函數(shù)原型:

  1. void *memcpy(void *dest, void *src, unsigned int count); 

5 、static的用法(定義和用途)(必考)

1)用static修飾局部變量:使其變?yōu)殪o態(tài)存儲(chǔ)方式(靜態(tài)數(shù)據(jù)區(qū)),那么這個(gè)局部變量在函數(shù)執(zhí)行完成之后不會(huì)被釋放,而是繼續(xù)保留在內(nèi)存中。

2)用static修飾全局變量:使其只在本文件內(nèi)部有效,而其他文件不可連接或引用該變量。

3)用static修飾函數(shù):對(duì)函數(shù)的連接方式產(chǎn)生影響,使得函數(shù)只在本文件內(nèi)部有效,對(duì)其他文件是不可見(jiàn)的(這一點(diǎn)在大工程中很重要很重要,避免很多麻煩,很常見(jiàn))。這樣的函數(shù)又叫作靜態(tài)函數(shù)。使用靜態(tài)函數(shù)的好處是,不用擔(dān)心與其他文件的同名函數(shù)產(chǎn)生干擾,另外也是對(duì)函數(shù)本身的一種保護(hù)機(jī)制。

6、const的用法(定義和用途)(必考)

const主要用來(lái)修飾變量、函數(shù)形參和類成員函數(shù):

1)用const修飾常量:定義時(shí)就初始化,以后不能更改。

2)用const修飾形參:func(const int a){};該形參在函數(shù)里不能改變

3)用const修飾類成員函數(shù):該函數(shù)對(duì)成員變量只能進(jìn)行只讀操作,就是const類成員函數(shù)是不能修改成員變量的數(shù)值的。

被const修飾的東西都受到強(qiáng)制保護(hù),可以預(yù)防意外的變動(dòng),能提高程序的健壯性。

參考一個(gè)大佬的回答:

我只要一聽(tīng)到被面試者說(shuō):"const意味著常數(shù)",我就知道我正在和一個(gè)業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應(yīng)該非常熟悉const能做什么和不能做什么.如果你從沒(méi)有讀到那篇文章,只要能說(shuō)出const意味著"只讀"就可以了。盡管這個(gè)答案不是完全的答案,但我接受它作為一個(gè)正確的答案。如果應(yīng)試者能正確回答這個(gè)問(wèn)題,我將問(wèn)他一個(gè)附加的問(wèn)題:下面的聲明都是什么意思?

  1. const int a; 
  2. int const a; 
  3. const int *a; 
  4. int * const a; 
  5. int const * a const; 

前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。

第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。

第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。

最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)。

7、volatile作用和用法

一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量在內(nèi)存中的值,而不是使用保存在寄存器里的備份(雖然讀寫(xiě)寄存器比讀寫(xiě)內(nèi)存快)。

回答不出這個(gè)問(wèn)題的人是不會(huì)被雇傭的。這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量。不懂得volatile的內(nèi)容將會(huì)帶來(lái)災(zāi)難。

以下幾種情況都會(huì)用到volatile:

1、并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)2、一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量3、多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量

8、const常量和#define的區(qū)別(編譯階段、安全性、內(nèi)存占用等)

用#define max 100 ; 定義的常量是沒(méi)有類型的(不進(jìn)行類型安全檢查,可能會(huì)產(chǎn)生意想不到的錯(cuò)誤),所給出的是一個(gè)立即數(shù),編譯器只是把所定義的常量值與所定義的常量的名字聯(lián)系起來(lái),define所定義的宏變量在預(yù)處理階段的時(shí)候進(jìn)行替換,在程序中使用到該常量的地方都要進(jìn)行拷貝替換;

用const int max = 255 ; 定義的常量有類型(編譯時(shí)會(huì)進(jìn)行類型檢查)名字,存放在內(nèi)存的靜態(tài)區(qū)域中,在編譯時(shí)確定其值。在程序運(yùn)行過(guò)程中const變量只有一個(gè)拷貝,而#define所定義的宏變量卻有多個(gè)拷貝,所以宏定義在程序運(yùn)行過(guò)程中所消耗的內(nèi)存要比const變量的大得多

9、變量的作用域(全局變量和局部變量)

全局變量:在所有函數(shù)體的外部定義的,程序的所在部分(甚至其它文件中的代碼)都可以使用。全局變量不受作用域的影響(也就是說(shuō),全局變量的生命期一直到程序的結(jié)束)。

局部變量:出現(xiàn)在一個(gè)作用域內(nèi),它們是局限于一個(gè)函數(shù)的。局部變量經(jīng)常被稱為自動(dòng)變量,因?yàn)樗鼈冊(cè)谶M(jìn)入作用域時(shí)自動(dòng)生成,離開(kāi)作用域時(shí)自動(dòng)消失。關(guān)鍵字auto可以顯式地說(shuō)明這個(gè)問(wèn)題,但是局部變量默認(rèn)為auto,所以沒(méi)有必要聲明為auto。

局部變量可以和全局變量重名,在局部變量作用域范圍內(nèi),全局變量失效,采用的是局部變量的值。

10、sizeof 與strlen (字符串,數(shù)組)

1.如果是數(shù)組

  1. #include<stdio.h> 
  2. int main() 
  3.     int a[5]={1,2,3,4,5}; 
  4.     printf(“sizeof  數(shù)組名=%d\n”,sizeof(a)); 
  5.     printf(“sizeof *數(shù)組名=%d\n”,sizeof(*a)); 

運(yùn)行結(jié)果

  1. sizeof  數(shù)組名=20 
  2. sizeof *數(shù)組名=4 

2.如果是指針,sizeof只會(huì)檢測(cè)到是指針的類型,指針都是占用4個(gè)字節(jié)的空間(32位機(jī))。

sizeof是什么?是一個(gè)操作符,也是關(guān)鍵字,就不是一個(gè)函數(shù),這和strlen()不同,strlen()是一個(gè)函數(shù)。

那么sizeof的作用是什么?返回一個(gè)對(duì)象或者類型所占的內(nèi)存字節(jié)數(shù)。我們會(huì)對(duì)sizeof()中的數(shù)據(jù)或者指針做運(yùn)算嗎?基本不會(huì)。例如sizeof(1+2.0),直接檢測(cè)到其中類型是double,即是sizeof(double) = 8。如果是指針,sizeof只會(huì)檢測(cè)到是指針的類型,指針都是占用4個(gè)字節(jié)的空間(32位機(jī))。

  1. char *p = "sadasdasd"
  2. sizeof(p):4 
  3. sizeof(*p):1//指向一個(gè)char類型的 

除非使用strlen(),僅對(duì)字符串有效,直到'\0'為止了,計(jì)數(shù)結(jié)果不包括\0。

要是非要使用sizeof來(lái)得到指向內(nèi)容的大小,就得使用數(shù)組名才行, 如

  1. char a[10]; 
  2. sizeof(a):10  //檢測(cè)到a是一個(gè)數(shù)組的類型。 

 

關(guān)于strlen(),它是一個(gè)函數(shù),考察的比較簡(jiǎn)單:

  1. strlen “\n\t\tag\AAtang” 

答案:11

11、經(jīng)典的sizeof(struct)和sizeof(union)內(nèi)存對(duì)齊

內(nèi)存對(duì)齊作用:

1.平臺(tái)原因(移植原因):不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。

2.性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對(duì)齊。原因在于,為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪問(wèn)。

結(jié)構(gòu)體struct內(nèi)存對(duì)齊的3大規(guī)則:

1.對(duì)于結(jié)構(gòu)體的各個(gè)成員,第一個(gè)成員的偏移量是0,排列在后面的成員其當(dāng)前偏移量必須是當(dāng)前成員類型的整數(shù)倍;

2.結(jié)構(gòu)體內(nèi)所有數(shù)據(jù)成員各自內(nèi)存對(duì)齊后,結(jié)構(gòu)體本身還要進(jìn)行一次內(nèi)存對(duì)齊,保證整個(gè)結(jié)構(gòu)體占用內(nèi)存大小是結(jié)構(gòu)體內(nèi)最大數(shù)據(jù)成員的最小整數(shù)倍;

3.如程序中有#pragma pack(n)預(yù)編譯指令,則所有成員對(duì)齊以n字節(jié)為準(zhǔn)(即偏移量是n的整數(shù)倍),不再考慮當(dāng)前類型以及最大結(jié)構(gòu)體內(nèi)類型。

  1. #pragma pack(1) 
  2.   
  3. struct fun{ 
  4.   int i; 
  5.   double d; 
  6.   char c; 
  7. }; 

sizeof(fun) = 13

  1. struct CAT_s 
  2.     int ld; 
  3.     char Color; 
  4.     unsigned short Age; 
  5.     char *Name
  6.     void(*Jump)(void); 
  7. }Garfield; 

1.使用32位編譯,int占4, char 占1, unsigned short 占2,char* 占4,函數(shù)指針占4個(gè),由于是32位編譯是4字節(jié)對(duì)齊,所以該結(jié)構(gòu)體占16個(gè)字節(jié)。(說(shuō)明:按幾字節(jié)對(duì)齊,是根據(jù)結(jié)構(gòu)體的最長(zhǎng)類型決定的,這里是int是最長(zhǎng)的字節(jié),所以按4字節(jié)對(duì)齊);

2.使用64位編譯 ,int占4, char 占1, unsigned short 占2,char* 占8,函數(shù)指針占8個(gè),由于是64位編譯是8字節(jié)對(duì)齊(說(shuō)明:按幾字節(jié)對(duì)齊,是根據(jù)結(jié)構(gòu)體的最長(zhǎng)類型決定的,這里是函數(shù)指針是最長(zhǎng)的字節(jié),所以按8字節(jié)對(duì)齊)所以該結(jié)構(gòu)體占24個(gè)字節(jié)。

  1. //64位 
  2. struct C  
  3. {  
  4.  double t;   //8   1111 1111 
  5.  char b;  //1      1 
  6.  int a;   //4      0001111   
  7.  short c;  //2     11000000 
  8. };   
  9.  sizeof(C) = 24;  //注意:1 4 2 不能拼在一起 

char是1,然后在int之前,地址偏移量得是4的倍數(shù),所以char后面補(bǔ)三個(gè)字節(jié),也就是char占了4個(gè)字節(jié),然后int四個(gè)字節(jié),最后是short,只占兩個(gè)字節(jié),但是總的偏移量得是double的倍數(shù),也就是8的倍數(shù),所以short后面補(bǔ)六個(gè)字節(jié)

聯(lián)合體union內(nèi)存對(duì)齊的2大規(guī)則:

1.找到占用字節(jié)最多的成員;

2.union的字節(jié)數(shù)必須是占用字節(jié)最多的成員的字節(jié)的倍數(shù),而且需要能夠容納其他的成員

  1. //x64 
  2. typedef union { 
  3.     long i; 
  4.     int k[5]; 
  5.     char c; 
  6. }D 

要計(jì)算union的大小,首先要找到占用字節(jié)最多的成員,本例中是long,占用8個(gè)字節(jié),int k[5]中都是int類型,仍然是占用4個(gè)字節(jié)的,然后union的字節(jié)數(shù)必須是占用字節(jié)最多的成員的字節(jié)的倍數(shù),而且需要能夠容納其他的成員,為了要容納k(20個(gè)字節(jié)),就必須要保證是8的倍數(shù)的同時(shí)還要大于20個(gè)字節(jié),所以是24個(gè)字節(jié)。

引申:位域(大疆筆試題)

C語(yǔ)言允許在一個(gè)結(jié)構(gòu)體中以位為單位來(lái)指定其成員所占內(nèi)存長(zhǎng)度,這種以位為單位的成員稱為“位段”或稱“位域”( bit field) 。利用位段能夠用較少的位數(shù)存儲(chǔ)數(shù)據(jù)。一個(gè)位段必須存儲(chǔ)在同一存儲(chǔ)單元中,不能跨兩個(gè)單元。如果第一個(gè)單元空間不能容納下一個(gè)位段,則該空間不用,而從下一個(gè)單元起存放該位段。

1.位段聲明和結(jié)構(gòu)體類似

2.位段的成員必須是int、unsigned int、signed int

3.位段的成員名后邊有一個(gè)冒號(hào)和一個(gè)數(shù)字

  1. typedef struct_data{ 
  2.    char m:3; 
  3.    char n:5; 
  4.    short s; 
  5.      
  6.    union
  7.    int a; 
  8.    char b; 
  9.    }; 
  10.      
  11.    int h; 
  12. }_attribute_((packed)) data_t; 

答案12

m和n一起,剛好占用一個(gè)字節(jié)內(nèi)存,因?yàn)楹竺媸莝hort類型變量,所以在short s之前,應(yīng)該補(bǔ)一個(gè)字節(jié)。所以m和n其實(shí)是占了兩個(gè)字節(jié)的,然后是short兩個(gè)個(gè)字節(jié),加起來(lái)就4個(gè)字節(jié),然后聯(lián)合體占了四個(gè)字節(jié),總共8個(gè)字節(jié)了,最后int h占了四個(gè)字節(jié),就是12個(gè)字節(jié)了

attribute((packed)) 取消對(duì)齊

GNU C的一大特色就是__attribute__機(jī)制。__attribute__可以設(shè)置函數(shù)屬性(Function Attribute)、變量屬性(Variable Attribute)和類型屬性(Type Attribute)。

__attribute__書(shū)寫(xiě)特征是:__attribute__前后都有兩個(gè)下劃線,并且后面會(huì)緊跟一對(duì)括弧,括弧里面是相應(yīng)的__attribute__參數(shù)。

跨平臺(tái)通信時(shí)用到。不同平臺(tái)內(nèi)存對(duì)齊方式不同。如果使用結(jié)構(gòu)體進(jìn)行平臺(tái)間的通信,會(huì)有問(wèn)題。例如,發(fā)送消息的平臺(tái)上,結(jié)構(gòu)體為24字節(jié),接受消息的平臺(tái)上,此結(jié)構(gòu)體為32字節(jié)(只是隨便舉個(gè)例子),那么每個(gè)變量對(duì)應(yīng)的值就不對(duì)了。

不同框架的處理器對(duì)齊方式會(huì)有不同,這個(gè)時(shí)候不指定對(duì)齊的話,會(huì)產(chǎn)生錯(cuò)誤結(jié)果

12、inline函數(shù)

在C語(yǔ)言中,如果一些函數(shù)被頻繁調(diào)用,不斷地有函數(shù)入棧,即函數(shù)棧,會(huì)造成??臻g或棧內(nèi)存的大量消耗。為了解決這個(gè)問(wèn)題,特別的引入了inline修飾符,表示為內(nèi)聯(lián)函數(shù)。

大多數(shù)的機(jī)器上,調(diào)用函數(shù)都要做很多工作:調(diào)用前要先保存寄存器,并在返回時(shí)恢復(fù),復(fù)制實(shí)參,程序還必須轉(zhuǎn)向一個(gè)新位置執(zhí)行C++中支持內(nèi)聯(lián)函數(shù),其目的是為了提高函數(shù)的執(zhí)行效率,用關(guān)鍵字 inline 放在函數(shù)定義(注意是定義而非聲明)的前面即可將函數(shù)指定為內(nèi)聯(lián)函數(shù),內(nèi)聯(lián)函數(shù)通常就是將它在程序中的每個(gè)調(diào)用點(diǎn)上“內(nèi)聯(lián)地”展開(kāi)。

內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價(jià),僅僅省去了函數(shù)調(diào)用的開(kāi)銷,從而提高函數(shù)的執(zhí)行效率。

13、內(nèi)存四區(qū),什么變量分別存儲(chǔ)在什么區(qū)域,堆上還是棧上。

 


 

文字常量區(qū),叫.rodata,不可以改變,改變會(huì)導(dǎo)致段錯(cuò)誤

  1. int a0=1; 
  2. static int a1; 
  3. const static a2=0; 
  4. extern int a3; 
  5.  
  6. void fun(void) 
  7.  int a4; 
  8.  volatile int a5; 
  9.  return

a0 :全局初始化變量;生命周期為整個(gè)程序運(yùn)行期間;作用域?yàn)樗形募?存儲(chǔ)位置為data段。

a1 :全局靜態(tài)未初始化變量;生命周期為整個(gè)程序運(yùn)行期間;作用域?yàn)楫?dāng)前文件;儲(chǔ)存位置為BSS段。

a2 :全局靜態(tài)變量

a3 :全局初始化變量;其他同a0。

a4 :局部變量;生命周期為fun函數(shù)運(yùn)行期間;作用域?yàn)閒un函數(shù)內(nèi)部;儲(chǔ)存位置為棧。

a5 :局部易變變量;

14、使用32位編譯情況下,給出判斷所使用機(jī)器大小端的方法。


聯(lián)合體方法判斷方法:利用union結(jié)構(gòu)體的從低地址開(kāi)始存,且同一時(shí)間內(nèi)只有一個(gè)成員占有內(nèi)存的特性。大端儲(chǔ)存符合閱讀習(xí)慣。聯(lián)合體占用內(nèi)存是最大的那個(gè),和結(jié)構(gòu)體不一樣。

a和c公用同一片內(nèi)存區(qū)域,所以更改c,必然會(huì)影響a的數(shù)據(jù)

  1. #include<stdio.h> 
  2.  
  3. int main(){ 
  4.   union w 
  5.   { 
  6.       int a; 
  7.       char b; 
  8.   }c; 
  9.   c.a = 1; 
  10.   if(c.b == 1) 
  11.    printf("小端存儲(chǔ)\n"); 
  12.   else 
  13.    printf("大端存儲(chǔ)\n"); 
  14.  return 0; 

指針?lè)椒?/p>

通過(guò)將int強(qiáng)制類型轉(zhuǎn)換成char單字節(jié),p指向a的起始字節(jié)(低字節(jié))

  1. #include <stdio.h> 
  2. int main () 
  3.     int a = 1; 
  4.     char *p = (char *)&a; 
  5.     if(*p == 1) 
  6.     { 
  7.         printf("小端存儲(chǔ)\n"); 
  8.     } 
  9.     else 
  10.     { 
  11.         printf("大端存儲(chǔ)\n"); 
  12.     } 
  13.     return 0; 

15、用變量a給出下面的定義

  1. a) 一個(gè)整型數(shù); 
  2. b)一個(gè)指向整型數(shù)的指針; 
  3. c)一個(gè)指向指針的指針,它指向的指針是指向一個(gè)整型數(shù); 
  4. d)一個(gè)有10個(gè)整型的數(shù)組; 
  5. e)一個(gè)有10個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù); 
  6. f)一個(gè)指向有10個(gè)整型數(shù)數(shù)組的指針; 
  7. g)一個(gè)指向函數(shù)的指針,該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù); 
  8. h)一個(gè)有10個(gè)指針的數(shù)組,該指針指向一個(gè)函數(shù),該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù) 
  9. 答案: 
  10. a)int a 
  11. b)int *a; 
  12. c)int **a; 
  13. d)int a[10]; 
  14. e)int *a [10]; 
  15. f) int a[10], *p=a; 
  16. g)int (*a)(int
  17. h) int( *a[10])(int

16、與或非,異或。運(yùn)算符優(yōu)先級(jí)

sum=a&b<

其中a=3,b=5,c=4(先加再移位再&再異或)答案4


第三章網(wǎng)絡(luò)編程

1 、TCP、UDP的區(qū)別

TCP---傳輸控制協(xié)議,提供的是面向連接、可靠的字節(jié)流服務(wù)。當(dāng)客戶和服務(wù)器彼此交換數(shù)據(jù)前,必須先在雙方之間建立一個(gè)TCP連接,之后才能傳輸數(shù)據(jù)。

UDP---用戶數(shù)據(jù)報(bào)協(xié)議,是一個(gè)簡(jiǎn)單的面向數(shù)據(jù)報(bào)的運(yùn)輸層協(xié)議。UDP不提供可靠性,它只是把應(yīng)用程序傳給IP層的數(shù)據(jù)報(bào)發(fā)送出去,但是并不能保證它們能到達(dá)目的地。

1)TCP是面向連接的,UDP是面向無(wú)連接的

2)UDP程序結(jié)構(gòu)較簡(jiǎn)單

3)TCP是面向字節(jié)流的,UDP是基于數(shù)據(jù)報(bào)的

4)TCP保證數(shù)據(jù)正確性,UDP可能丟包

5)TCP保證數(shù)據(jù)順序到達(dá),UDP不保證

2 、TCP、UDP的優(yōu)缺點(diǎn)

TCP優(yōu)點(diǎn):可靠穩(wěn)定

TCP的可靠體現(xiàn)在TCP在傳輸數(shù)據(jù)之前,會(huì)有三次握手來(lái)建立連接,而且在數(shù)據(jù)傳遞時(shí),有確認(rèn)、窗口、重傳、擁塞控制機(jī)制,在數(shù)據(jù)傳完之后,還會(huì)斷開(kāi)來(lái)連接用來(lái)節(jié)約系統(tǒng)資源。

TCP缺點(diǎn):慢,效率低,占用系統(tǒng)資源高,易被攻擊

在傳遞數(shù)據(jù)之前要先建立連接,這會(huì)消耗時(shí)間,而且在數(shù)據(jù)傳遞時(shí),確認(rèn)機(jī)制、重傳機(jī)制、擁塞機(jī)制等都會(huì)消耗大量時(shí)間,而且要在每臺(tái)設(shè)備上維護(hù)所有的傳輸連接。然而,每個(gè)連接都會(huì)占用系統(tǒng)的CPU,內(nèi)存等硬件資源。因?yàn)門CP有確認(rèn)機(jī)制、三次握手機(jī)制,這些也導(dǎo)致TCP容易被利用,實(shí)現(xiàn)DOS、DDOS、CC等攻擊。

UDP優(yōu)點(diǎn):快,比TCP稍安全

UDP沒(méi)有TCP擁有的各種機(jī)制,是一種無(wú)狀態(tài)的傳輸協(xié)議,所以傳輸數(shù)據(jù)非常快,沒(méi)有TCP的這些機(jī)制,被攻擊利用的機(jī)會(huì)就少一些,但是也無(wú)法避免被攻擊。

UDP缺點(diǎn):不可靠,不穩(wěn)定

因?yàn)闆](méi)有TCP的這些機(jī)制,UDP在傳輸數(shù)據(jù)時(shí),如果網(wǎng)絡(luò)質(zhì)量不好,就會(huì)很容易丟包,造成數(shù)據(jù)的缺失。

3 、TCP UDP適用場(chǎng)景

TCP:傳輸一些對(duì)信號(hào)完整性,信號(hào)質(zhì)量有要求的信息。

UDP:對(duì)網(wǎng)絡(luò)通訊質(zhì)量要求不高時(shí),要求網(wǎng)絡(luò)通訊速度要快的場(chǎng)景。

4、 TCP為什么是可靠連接?

因?yàn)閠cp傳輸?shù)臄?shù)據(jù)滿足3大條件,不丟失,不重復(fù),按順序到達(dá)。

5、OSI典型網(wǎng)絡(luò)模型,簡(jiǎn)單說(shuō)說(shuō)有哪些


6、三次握手、四次揮手

三次握手


1、TCP服務(wù)器進(jìn)程先創(chuàng)建傳輸控制塊TCB,時(shí)刻準(zhǔn)備接受客戶進(jìn)程的連接請(qǐng)求,此時(shí)服務(wù)器就進(jìn)入了LISTEN(監(jiān)聽(tīng))狀態(tài);

2、TCP客戶進(jìn)程也是先創(chuàng)建傳輸控制塊TCB,然后向服務(wù)器發(fā)出連接請(qǐng)求報(bào)文,這是報(bào)文首部中的同部位SYN=1,同時(shí)選擇一個(gè)初始序列號(hào) seq=x ,此時(shí),TCP客戶端進(jìn)程進(jìn)入了 SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)。TCP規(guī)定,SYN報(bào)文段(SYN=1的報(bào)文段)不能攜帶數(shù)據(jù),但需要消耗掉一個(gè)序號(hào)。

3、TCP服務(wù)器收到請(qǐng)求報(bào)文后,如果同意連接,則發(fā)出確認(rèn)報(bào)文。確認(rèn)報(bào)文中應(yīng)該 ACK=1,SYN=1,確認(rèn)號(hào)是ack=x+1,同時(shí)也要為自己初始化一個(gè)序列號(hào) seq=y,此時(shí),TCP服務(wù)器進(jìn)程進(jìn)入了SYN-RCVD(同步收到)狀態(tài)。這個(gè)報(bào)文也不能攜帶數(shù)據(jù),但是同樣要消耗一個(gè)序號(hào)。

4、TCP客戶進(jìn)程收到確認(rèn)后,還要向服務(wù)器給出確認(rèn)。確認(rèn)報(bào)文的ACK=1,ack=y+1,自己的序列號(hào)seq=x+1,此時(shí),TCP連接建立,客戶端進(jìn)入ESTABLISHED(已建立連接)狀態(tài)。TCP規(guī)定,ACK報(bào)文段可以攜帶數(shù)據(jù),但是如果不攜帶數(shù)據(jù)則不消耗序號(hào)。

5、當(dāng)服務(wù)器收到客戶端的確認(rèn)后也進(jìn)入ESTABLISHED狀態(tài),此后雙方就可以開(kāi)始通信了。

四次揮手


1、客戶端進(jìn)程發(fā)出連接釋放報(bào)文,并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報(bào)文首部,F(xiàn)IN=1,其序列號(hào)為seq=u(等于前面已經(jīng)傳送過(guò)來(lái)的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)加1),此時(shí),客戶端進(jìn)入FIN-WAIT-1(終止等待1)狀態(tài)。TCP規(guī)定,F(xiàn)IN報(bào)文段即使不攜帶數(shù)據(jù),也要消耗一個(gè)序號(hào)。

2、服務(wù)器收到連接釋放報(bào)文,發(fā)出確認(rèn)報(bào)文,ACK=1,ack=u+1,并且?guī)献约旱男蛄刑?hào)seq=v,此時(shí),服務(wù)端就進(jìn)入了CLOSE-WAIT(關(guān)閉等待)狀態(tài)。TCP服務(wù)器通知高層的應(yīng)用進(jìn)程,客戶端向服務(wù)器的方向就釋放了,這時(shí)候處于半關(guān)閉狀態(tài),即客戶端已經(jīng)沒(méi)有數(shù)據(jù)要發(fā)送了,但是服務(wù)器若發(fā)送數(shù)據(jù),客戶端依然要接受。這個(gè)狀態(tài)還要持續(xù)一段時(shí)間,也就是整個(gè)CLOSE-WAIT狀態(tài)持續(xù)的時(shí)間。

3、客戶端收到服務(wù)器的確認(rèn)請(qǐng)求后,此時(shí),客戶端就進(jìn)入FIN-WAIT-2(終止等待2)狀態(tài),等待服務(wù)器發(fā)送連接釋放報(bào)文(在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù))。

4、服務(wù)器將最后的數(shù)據(jù)發(fā)送完畢后,就向客戶端發(fā)送連接釋放報(bào)文,F(xiàn)IN=1,ack=u+1,由于在半關(guān)閉狀態(tài),服務(wù)器很可能又發(fā)送了一些數(shù)據(jù),假定此時(shí)的序列號(hào)為seq=w,此時(shí),服務(wù)器就進(jìn)入了LAST-ACK(最后確認(rèn))狀態(tài),等待客戶端的確認(rèn)。

5、客戶端收到服務(wù)器的連接釋放報(bào)文后,必須發(fā)出確認(rèn),ACK=1,ack=w+1,而自己的序列號(hào)是seq=u+1,此時(shí),客戶端就進(jìn)入了TIME-WAIT(時(shí)間等待)狀態(tài)。注意此時(shí)TCP連接還沒(méi)有釋放,必須經(jīng)過(guò)2∗ *∗MSL(最長(zhǎng)報(bào)文段壽命)的時(shí)間后,當(dāng)客戶端撤銷相應(yīng)的TCB后,才進(jìn)入CLOSED狀態(tài)。

6、服務(wù)器只要收到了客戶端發(fā)出的確認(rèn),立即進(jìn)入CLOSED狀態(tài)。同樣,撤銷TCB后,就結(jié)束了這次的TCP連接??梢钥吹剑?wù)器結(jié)束TCP連接的時(shí)間要比客戶端早一些。

第四章常見(jiàn)算法

十種常見(jiàn)排序算法可以分為兩大類:

非線性時(shí)間比較類排序:通過(guò)比較來(lái)決定元素間的相對(duì)次序,由于其時(shí)間復(fù)雜度不能突破O(nlogn),因此稱為非線性時(shí)間比較類排序。

線性時(shí)間非比較類排序:不通過(guò)比較來(lái)決定元素間的相對(duì)次序,它可以突破基于比較排序的時(shí)間下界,以線性時(shí)間運(yùn)行,因此稱為線性時(shí)間非比較類排序。


算法優(yōu)劣評(píng)價(jià)術(shù)語(yǔ)

穩(wěn)定性:

穩(wěn)定:如果 a 原本在 b 前面,而 a = b,排序之后 a 仍然在 b 的前面;

不穩(wěn)定:如果 a 原本在 b 的前面,而 a = b,排序之后 a 可能會(huì)出現(xiàn)在 b 的后面;

排序方式:

內(nèi)排序:所有排序操作都在內(nèi)存中完成,占用常數(shù)內(nèi)存,不占用額外內(nèi)存。

外排序:由于數(shù)據(jù)太大,因此把數(shù)據(jù)放在磁盤(pán)中,而排序通過(guò)磁盤(pán)和內(nèi)存的數(shù)據(jù)傳輸才能進(jìn)行,占用額外內(nèi)存。

復(fù)雜度:

時(shí)間復(fù)雜度: 一個(gè)算法執(zhí)行所耗費(fèi)的時(shí)間。

空間復(fù)雜度: 運(yùn)行完一個(gè)程序所需內(nèi)存的大小。



至于各種算法的原理以及代碼實(shí)現(xiàn),由于太多并且比較復(fù)雜,不在本文列出。但推薦兩本入門的書(shū):《啊哈!算法》、《大話數(shù)據(jù)結(jié)構(gòu)》。電子版我會(huì)發(fā)在交流群里。

排序算法很多,嵌入式要求的不會(huì)太多,你會(huì)冒泡排序、快速排序、插入排序就可以解決很多問(wèn)題。難的比如動(dòng)態(tài)規(guī)劃問(wèn)題,圖的路徑問(wèn)題,嵌入式考的比較少,純軟才會(huì)考這些。(大公司和獨(dú)角獸公司考的會(huì)相對(duì)難一些)

第五章Linux操作系統(tǒng)題目

1、 Linux內(nèi)核的組成部分

Linux內(nèi)核主要由五個(gè)子系統(tǒng)組成:進(jìn)程調(diào)度,內(nèi)存管理,虛擬文件系統(tǒng),網(wǎng)絡(luò)接口,進(jìn)程間通信。


2、Linux系統(tǒng)的組成部分

Linux系統(tǒng)一般有4個(gè)主要部分:

內(nèi)核、shell、文件系統(tǒng)和應(yīng)用程序。


3、用戶空間與內(nèi)核通信方式有哪些?

1)系統(tǒng)調(diào)用。用戶空間進(jìn)程通過(guò)系統(tǒng)調(diào)用進(jìn)入內(nèi)核空間,訪問(wèn)指定的內(nèi)核空間數(shù)據(jù);

2)驅(qū)動(dòng)程序。用戶空間進(jìn)程可以使用封裝后的系統(tǒng)調(diào)用接口訪問(wèn)驅(qū)動(dòng)設(shè)備節(jié)點(diǎn),以和運(yùn)行在內(nèi)核空間的驅(qū)動(dòng)程序通信;

3)共享內(nèi)存mmap。在代碼中調(diào)用接口,實(shí)現(xiàn)內(nèi)核空間與用戶空間的地址映射,在實(shí)時(shí)性要求很高的項(xiàng)目中為首選,省去拷貝數(shù)據(jù)的時(shí)間等資源,但缺點(diǎn)是不好控制;

4)copy_to_user()、copy_from_user(),是在驅(qū)動(dòng)程序中調(diào)用接口,實(shí)現(xiàn)用戶空間與內(nèi)核空間的數(shù)據(jù)拷貝操作,應(yīng)用于實(shí)時(shí)性要求不高的項(xiàng)目中。

以及:

  1. procfs(/proc) 
  2. sysctl (/proc/sys) 
  3. sysfs(/sys) 
  4. netlink 套接口 

4、系統(tǒng)調(diào)用與普通函數(shù)調(diào)用的區(qū)別

系統(tǒng)調(diào)用:

1.使用INT和IRET指令,內(nèi)核和應(yīng)用程序使用的是不同的堆棧,因此存在堆棧的切換,從用戶態(tài)切換到內(nèi)核態(tài),從而可以使用特權(quán)指令操控設(shè)備

2.依賴于內(nèi)核,不保證移植性

3.在用戶空間和內(nèi)核上下文環(huán)境間切換,開(kāi)銷較大

4.是操作系統(tǒng)的一個(gè)入口點(diǎn)

普通函數(shù)調(diào)用:

1.使用CALL和RET指令,調(diào)用時(shí)沒(méi)有堆棧切換

2.平臺(tái)移植性好

3.屬于過(guò)程調(diào)用,調(diào)用開(kāi)銷較小

4.一個(gè)普通功能函數(shù)的調(diào)用

5、內(nèi)核態(tài),用戶態(tài)的區(qū)別

內(nèi)核態(tài),操作系統(tǒng)在內(nèi)核態(tài)運(yùn)行——運(yùn)行操作系統(tǒng)程序

用戶態(tài),應(yīng)用程序只能在用戶態(tài)運(yùn)行——運(yùn)行用戶程序

當(dāng)一個(gè)進(jìn)程在執(zhí)行用戶自己的代碼時(shí)處于用戶運(yùn)行態(tài)(用戶態(tài)),此時(shí)特權(quán)級(jí)最低,為3級(jí),是普通的用戶進(jìn)程運(yùn)行的特權(quán)級(jí),大部分用戶直接面對(duì)的程序都是運(yùn)行在用戶態(tài)。Ring3狀態(tài)不能訪問(wèn)Ring0的地址空間,包括代碼和數(shù)據(jù);當(dāng)一個(gè)進(jìn)程因?yàn)橄到y(tǒng)調(diào)用陷入內(nèi)核代碼中執(zhí)行時(shí)處于內(nèi)核運(yùn)行態(tài)(內(nèi)核態(tài)),此時(shí)特權(quán)級(jí)最高,為0級(jí)。執(zhí)行的內(nèi)核代碼會(huì)使用當(dāng)前進(jìn)程的內(nèi)核棧,每個(gè)進(jìn)程都有自己的內(nèi)核棧。

6、 bootloader、內(nèi)核 、根文件的關(guān)系

啟動(dòng)順序:bootloader->linux kernel->rootfile->app

Bootloader全名為啟動(dòng)引導(dǎo)程序,是第一段代碼,它主要用來(lái)初始化處理器及外設(shè),然后調(diào)用Linux內(nèi)核。Linux內(nèi)核在完成系統(tǒng)的初始化之后需要掛載某個(gè)文件系統(tǒng)作為根文件系統(tǒng)(RootFilesystem),然后加載必要的內(nèi)核模塊,啟動(dòng)應(yīng)用程序。(一個(gè)嵌入式Linux系統(tǒng)從軟件角度看可以分為四個(gè)部分:引導(dǎo)加載程序(Bootloader),Linux內(nèi)核,文件系統(tǒng),應(yīng)用程序。)

7 、Bootloader啟動(dòng)的兩個(gè)階段:

Stage1:匯編語(yǔ)言

1)基本的硬件初始化(關(guān)閉看門狗和中斷,MMU(帶操作系統(tǒng)),CACHE。配置系統(tǒng)工作時(shí)鐘)

2)為加載stage2準(zhǔn)備RAM空間

3)拷貝內(nèi)核映像和文件系統(tǒng)映像到RAM中

4)設(shè)置堆棧指針sp

5)跳到stage2的入口點(diǎn)

Stage2:c語(yǔ)言

1)初始化本階段要使用到的硬件設(shè)備(led uart等)

2)檢測(cè)系統(tǒng)的內(nèi)存映射

3)加載內(nèi)核映像和文件系統(tǒng)映像

4)設(shè)置內(nèi)核的啟動(dòng)參數(shù)

嵌入式系統(tǒng)中廣泛采用的非易失性存儲(chǔ)器通常是Flash,而B(niǎo)ootloader就位于該存儲(chǔ)器的最前端,所以系統(tǒng)上電或復(fù)位后執(zhí)行的第一段程序便是Bootloader。

8、 linux下檢查內(nèi)存狀態(tài)的命令

  1. 1)查看進(jìn)程:top 
  2. 2)查看內(nèi)存:free 
  3. 3)cat /proc/meminfo 
  4. 4)vmstat 

假如一個(gè)公司服務(wù)器有很多用戶,你使用top命令,可以看到哪個(gè)同事在使用什么命令,做什么事情,占用了多少CPU。

9 、一個(gè)程序從開(kāi)始運(yùn)行到結(jié)束的完整過(guò)程(四個(gè)過(guò)程)

預(yù)處理(Pre-Processing)、編譯(Compiling)、匯編(Assembling)、鏈接(Linking)

10、什么是堆,棧,內(nèi)存泄漏和內(nèi)存溢出?

棧由系統(tǒng)操作,程序員不可以操作。

所以內(nèi)存泄漏是指堆內(nèi)存的泄漏。堆內(nèi)存是指程序從堆中分配的,大小任意的(內(nèi)存塊的大小可以在程序運(yùn)行期決定),使用完后必須顯式釋放的內(nèi)存。應(yīng)用程序一般使用malloc,new等函數(shù)從堆中分配到一塊內(nèi)存,使用完后,程序必須負(fù)責(zé)相應(yīng)的調(diào)用free或delete釋放該內(nèi)存塊,否則,這塊內(nèi)存就不能被再次使用。

內(nèi)存溢出:你要求分配的內(nèi)存超出了系統(tǒng)能給你的,系統(tǒng)不能滿足需求,于是產(chǎn)生溢出。

內(nèi)存越界:向系統(tǒng)申請(qǐng)了一塊內(nèi)存,而在使用內(nèi)存時(shí),超出了申請(qǐng)的范圍(常見(jiàn)的有使用特定大小數(shù)組時(shí)發(fā)生內(nèi)存越界)

內(nèi)存溢出問(wèn)題是 C 語(yǔ)言或者 C++ 語(yǔ)言所固有的缺陷,它們既不檢查數(shù)組邊界,又不檢查類型可靠性(type-safety)。眾所周知,用 C/C++ 語(yǔ)言開(kāi)發(fā)的程序由于目標(biāo)代碼非常接近機(jī)器內(nèi)核,因而能夠直接訪問(wèn)內(nèi)存和寄存器,這種特性大大提升了 C/C++ 語(yǔ)言代碼的性能。只要合理編碼,C/C++ 應(yīng)用程序在執(zhí)行效率上必然優(yōu)于其它高級(jí)語(yǔ)言。然而,C/C++ 語(yǔ)言導(dǎo)致內(nèi)存溢出問(wèn)題的可能性也要大許多。

11、死鎖的原因、條件

產(chǎn)生死鎖的原因主要是:

(1) 因?yàn)橄到y(tǒng)資源不足。

(2) 進(jìn)程運(yùn)行推進(jìn)的順序不合適。

(3) 資源分配不當(dāng)?shù)取?/p>

如果系統(tǒng)資源充足,進(jìn)程的資源請(qǐng)求都能夠得到滿足,死鎖出現(xiàn)的可能性就很低,否則就會(huì)因爭(zhēng)奪有限的資源而陷入死鎖。其次,進(jìn)程運(yùn)行推進(jìn)順序與速度不同,也可能產(chǎn)生死鎖

這四個(gè)條件是死鎖的必要條件,只要系統(tǒng)發(fā)生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會(huì)發(fā)生死鎖。

(1) 互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。

(2) 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。

(3) 不剝奪條件:進(jìn)程已獲得的資源,在末使用完之前,不能強(qiáng)行剝奪。

(4) 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

12、硬鏈接與軟鏈接

鏈接操作實(shí)際上是給系統(tǒng)中已有的某個(gè)文件指定另外一個(gè)可用于訪問(wèn)它的名稱。對(duì)于這個(gè)新的文件名,我們可以為之指定不同的訪問(wèn)權(quán)限,以控制對(duì)信息的共享和安全性的問(wèn)題。如果鏈接指向目錄,用戶就可以利用該鏈接直接進(jìn)入被鏈接的目錄而不用打一大堆的路徑名。而且,即使我們刪除這個(gè)鏈接,也不會(huì)破壞原來(lái)的目錄。

1>硬鏈接

硬鏈接只能引用同一文件系統(tǒng)中的文件。它引用的是文件在文件系統(tǒng)中的物理索引(也稱為inode)。當(dāng)您移動(dòng)或刪除原始文件時(shí),硬鏈接不會(huì)被破壞,因?yàn)樗玫氖俏募奈锢頂?shù)據(jù)而不是文件在文件結(jié)構(gòu)中的位置。硬鏈接的文件不需要用戶有訪問(wèn)原始文件的權(quán)限,也不會(huì)顯示原始文件的位置,這樣有助于文件的安全。如果您刪除的文件有相應(yīng)的硬鏈接,那么這個(gè)文件依然會(huì)保留,直到所有對(duì)它的引用都被刪除。

2>軟鏈接(符號(hào)鏈接)

軟連接,其實(shí)就是新建立一個(gè)文件,這個(gè)文件就是專門用來(lái)指向別的文件的(那就和windows 下的快捷方式的那個(gè)文件有很接近的意味)。軟連接產(chǎn)生的是一個(gè)新的文件,但這個(gè)文件的作用就是專門指向某個(gè)文件的,刪了這個(gè)軟連接文件,那就等于不需要這個(gè)連接,和原來(lái)的存在的實(shí)體原文件沒(méi)有任何關(guān)系,但刪除原來(lái)的文件,則相應(yīng)的軟連接不可用。

13、計(jì)算機(jī)中,32bit與64bit有什么區(qū)別

64bit計(jì)算主要有兩大優(yōu)點(diǎn):可以進(jìn)行更大范圍的整數(shù)運(yùn)算;可以支持更大的內(nèi)存。

64位操作系統(tǒng)下的虛擬內(nèi)存空間大?。旱刂房臻g大小不是2^32,也不是2^64,而一般是2^48。因?yàn)椴⒉恍枰?^64那么大的尋址空間,過(guò)大的空間只會(huì)造成資源的浪費(fèi)。所以64位Linux一般使用48位表示虛擬空間地址,40位標(biāo)識(shí)物理地址。

14、中斷和異常的區(qū)別

內(nèi)中斷:同步中斷(異常)是由cpu內(nèi)部的電信號(hào)產(chǎn)生的中斷,其特點(diǎn)為當(dāng)前執(zhí)行的指令結(jié)束后才轉(zhuǎn)而產(chǎn)生中斷,由于有cpu主動(dòng)產(chǎn)生,其執(zhí)行點(diǎn)必然是可控的。

外中斷:異步中斷是由cpu的外設(shè)產(chǎn)生的電信號(hào)引起的中斷,其發(fā)生的時(shí)間點(diǎn)不可預(yù)期。

15、中斷怎么發(fā)生,中斷處理流程

請(qǐng)求中斷→響應(yīng)中斷→關(guān)閉中斷→保留斷點(diǎn)→中斷源識(shí)別→保護(hù)現(xiàn)場(chǎng)→中斷服務(wù)子程序→恢復(fù)現(xiàn)場(chǎng)→中斷返回。


16、 Linux 操作系統(tǒng)掛起、休眠、關(guān)機(jī)相關(guān)命令

關(guān)機(jī)命令有halt, init 0, poweroff ,shutdown -h 時(shí)間,其中shutdown是最安全的

重啟命令有reboot,init 6,,shutdow -r時(shí)間

在linux命令中reboot是重新啟動(dòng),shutdown -r now是立即停止然后重新啟動(dòng)

具體可用參數(shù)可以百度。

17、說(shuō)一個(gè)linux下編譯優(yōu)化選項(xiàng):

加:-o

18、在有數(shù)據(jù)cache情況下,DMA數(shù)據(jù)鏈路為:

外設(shè)-DMA-DDR-cache-CPU

19、linux命令

1、改變文件屬性的命令:chmod (chmod 777 /etc/squid 運(yùn)行命令后,squid文件夾(目錄)的權(quán)限就被修改為777(可讀可寫(xiě)可執(zhí)行))

2、查找文件中匹配字符串的命令:grep

3、查找當(dāng)前目錄: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、查看進(jìn)程對(duì)應(yīng)的端口號(hào)

  1. 1、先查看進(jìn)程pid 
  2. ps -ef | grep 進(jìn)程名 
  3.  
  4. 2、通過(guò)pid查看占用端口 
  5. netstat -nap | grep 進(jìn)程pid 

20、硬實(shí)時(shí)系統(tǒng)和軟實(shí)時(shí)系統(tǒng)

軟實(shí)時(shí)系統(tǒng):

Windows、Linux系統(tǒng)通常為軟實(shí)時(shí),當(dāng)然有補(bǔ)丁可以將內(nèi)核做成硬實(shí)時(shí)的系統(tǒng),不過(guò)商用沒(méi)有這么做的。

硬實(shí)時(shí)系統(tǒng):

對(duì)時(shí)間要求很高,限定時(shí)間內(nèi)不管做沒(méi)做完必須返回。

VxWorks,uCOS,F(xiàn)reeRTOS,WinCE,RT-thread等實(shí)時(shí)系統(tǒng);

21、MMU基礎(chǔ)

現(xiàn)代操作系統(tǒng)普遍采用虛擬內(nèi)存管理(Virtual Memory Management) 機(jī)制,這需要MMU( Memory Management Unit,內(nèi)存管理單元) 的支持。有些嵌入式處理器沒(méi)有MMU,則不能運(yùn)行依賴于虛擬內(nèi)存管理的操作系統(tǒng)。

也就是說(shuō):操作系統(tǒng)可以分成兩類,用MMU的、不用MMU的。

用MMU的是:Windows、MacOS、Linux、Android;不用MMU的是:FreeRTOS、VxWorks、UCOS……

與此相對(duì)應(yīng)的:CPU也可以分成兩類,帶MMU的、不帶MMU的。

帶MMU的是:Cortex-A系列、ARM9、ARM11系列;

不帶MMU的是:Cortex-M系列……(STM32是M系列,沒(méi)有MMU,不能運(yùn)行Linux,只能運(yùn)行一些UCOS、FreeRTOS等等)。

MMU就是負(fù)責(zé)虛擬地址(virtual address)轉(zhuǎn)化成物理地址(physical address),轉(zhuǎn)換過(guò)程比較復(fù)雜,可以自行百度。

第六章 單片機(jī)常見(jiàn)面試題

1、ROM與RAM

這一點(diǎn)我另一篇文章講解過(guò),這里放鏈接:

ROM與RAM的區(qū)別

2、 IO口工作方式(學(xué)過(guò)STM32的人應(yīng)該很熟悉)

上拉輸入、下拉輸入、推挽輸出、開(kāi)漏輸出。

3、請(qǐng)說(shuō)明總線接口USRT、I2C、USB的異同點(diǎn)

(串/并、速度、全/半雙工、總線拓?fù)涞?


4、IIC協(xié)議時(shí)序圖

必須會(huì)畫(huà)出來(lái),我面試被問(wèn)到過(guò),讓我畫(huà),我畫(huà)了個(gè)大概。

IIC協(xié)議有兩根線,一根SCL時(shí)鐘線,一根SDA數(shù)據(jù)線,如圖可以看到開(kāi)始信號(hào)和結(jié)束信號(hào)的電平狀態(tài)。開(kāi)始后,因?yàn)镮IC總線可以掛在很多設(shè)備(不超過(guò)8個(gè)),所以先發(fā)送一個(gè)設(shè)備地址,選中這個(gè)設(shè)備,設(shè)備地址最后一位代表了是寫(xiě)還是讀。選中設(shè)備后,再發(fā)送寄存器地址,代表選中某個(gè)寄存器,再開(kāi)始傳輸數(shù)據(jù)。

八位設(shè)備地址=7位從機(jī)地址+讀/寫(xiě)地址,

再給地址添加一個(gè)方向位位用來(lái)表示接下來(lái)數(shù)據(jù)傳輸?shù)姆较颍?/p>

0表示主設(shè)備向從設(shè)備(write)寫(xiě)數(shù)據(jù),

1表示主設(shè)備向從設(shè)備(read)讀數(shù)據(jù)


開(kāi)始信號(hào):SCL 為高電平時(shí),SDA 由高電平向低電平跳變,開(kāi)始傳送數(shù)據(jù)。

結(jié)束信號(hào):SCL 為高電平時(shí),SDA 由低電平向高電平跳變,結(jié)束傳送數(shù)據(jù)。

應(yīng)答信號(hào):接收數(shù)據(jù)的 IC 在接收到 8bit 數(shù)據(jù)后,向發(fā)送數(shù)據(jù)的 IC 發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù)。CPU 向受控單元發(fā)出一個(gè)信號(hào)后,等待受控單元發(fā)出一個(gè)應(yīng)答信號(hào),CPU 接收到應(yīng)答信號(hào)后,根據(jù)實(shí)際情況作出是否繼續(xù)傳遞信號(hào)的判斷。若未收到應(yīng)答信號(hào),由判斷為受控單元出現(xiàn)故障。

IIC信號(hào)在數(shù)據(jù)傳輸過(guò)程中,當(dāng)SCL=1高電平時(shí),數(shù)據(jù)線SDA必須保持穩(wěn)定狀態(tài),不允許有電平跳變,只有在時(shí)鐘線上的信號(hào)為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。SCL=1時(shí) 數(shù)據(jù)線SDA的任何電平變換會(huì)看做是總線的起始信號(hào)或者停止信號(hào)。

IIC我也有一篇文章有講解,請(qǐng)看鏈接:

IIC總線最多可以掛多少個(gè)設(shè)備

5、單片機(jī)的SP指針始終指向

棧頂

6、IIC總線在傳送數(shù)據(jù)過(guò)程中共有三種類型信號(hào):

它們分別是:開(kāi)始信號(hào)、結(jié)束信號(hào)和應(yīng)答信號(hào)。

7、FIQ中斷向量入口地址:

FIQ和IRQ是兩種不同類型的中斷,ARM為了支持這兩種不同的中斷,提供了對(duì)應(yīng)的叫做FIQ和IRQ處理器模式(ARM有7種處理模式)。

FIQ的中斷向量地址在0x0000001C,而IRQ的在0x00000018。

8、SPI四種模式,簡(jiǎn)述其中一種模式,畫(huà)出時(shí)序圖

在芯片資料上極性和相位一般表示為CPOL(Clock POLarity)和CPHA(Clock PHAse), 極性和相位組合成4種工作模式。


spi四種模式SPI的相位(CPHA)和極性(CPOL)分別可以為0或1,對(duì)應(yīng)的4種組合構(gòu)成了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

時(shí)鐘極性CPOL: 即SPI空閑時(shí),時(shí)鐘信號(hào)SCLK的電平(1:空閑時(shí)高電平; 0:空閑時(shí)低電平) 時(shí)鐘相位CPHA: 即SPI在SCLK第幾個(gè)邊沿開(kāi)始采樣(0:第一個(gè)邊沿開(kāi)始; 1:第二個(gè)邊沿開(kāi)始)

sd卡的spi常用的是mode 0 和mode 3,這兩種模式的相同的地方是都在時(shí)鐘上升沿采樣傳輸數(shù)據(jù),區(qū)別這兩種方式的簡(jiǎn)單方法就是看空閑時(shí),時(shí)鐘的電平狀態(tài),低電平為mode 0 ,高電平為mode 3。

具體的通信過(guò)程請(qǐng)自行百度,2021年秋招大疆筆試題考了這道題。

第七章 雜項(xiàng)面試題

1、講一講馮諾依曼和哈佛體系的區(qū)別

哈佛結(jié)構(gòu)是一種將程序指令存儲(chǔ)和數(shù)據(jù)存儲(chǔ)分開(kāi)的存儲(chǔ)器結(jié)構(gòu)。目前使用哈佛結(jié)構(gòu)的中央處理器和微控制器有很多,ARM9、ARM10和ARM11,51單片機(jī)屬于哈佛結(jié)構(gòu)。

馮·諾伊曼結(jié)構(gòu)也稱普林斯頓結(jié)構(gòu),是一種將程序指令存儲(chǔ)器和數(shù)據(jù)存儲(chǔ)器合并在一起的存儲(chǔ)器結(jié)構(gòu)。

2、面向?qū)ο缶幊痰娜筇匦?/strong>

以及重載的意思。重載,是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。

3、http默認(rèn)端口號(hào)

80

4、linux中mysql數(shù)據(jù)庫(kù)默認(rèn)的端口是

3306

5、編程習(xí)慣小知識(shí)點(diǎn)

C語(yǔ)言編程中,單片機(jī)平臺(tái),一般有.c和.h文件,如果一個(gè)人在.h文件中定義了一個(gè)變量,會(huì)有什么后果。(討論編程習(xí)慣的問(wèn)題,我一般是只在.h文件中聲明函數(shù),不會(huì)做變量定義;另外,編程中每一個(gè)模塊都會(huì)有對(duì)應(yīng)的.c和.h文件,最終的總程序自己定義一個(gè)comm.c和comm.h去調(diào)用各個(gè)模塊,這樣的習(xí)慣我覺(jué)得還行)

if語(yǔ)句中如果是或運(yùn)算( | ),第一個(gè)條件滿足時(shí),第二個(gè)條件還會(huì)判斷嗎?;蜻\(yùn)算的話,當(dāng)然不會(huì),因?yàn)?0|1=1,中斷了

 

 

責(zé)任編輯:姜華 來(lái)源: 嵌入式Linux系統(tǒng)開(kāi)發(fā)
相關(guān)推薦

2021-01-20 07:28:34

嵌入式筆試面試

2021-01-15 07:49:01

嵌入式筆試面試

2021-01-14 10:24:33

嵌入式筆試面試

2021-01-19 07:16:25

嵌入式筆試面試

2021-01-21 08:00:50

嵌入式筆試面試

2021-02-25 16:26:35

嵌入式筆試面試

2009-06-16 14:03:16

Hibernate面試Hibernate面試

2009-06-02 15:11:11

Hibernate面試題查詢

2018-03-08 18:40:47

Java百度面試題

2011-05-19 16:30:38

軟件測(cè)試

2017-08-29 14:12:16

Java面試題

2021-10-27 11:00:30

C++語(yǔ)言面試

2009-05-14 09:28:16

嵌入式面試求職

2021-03-31 10:36:33

Python面試題開(kāi)發(fā)

2009-06-18 15:45:55

J2ee筆試

2009-08-01 23:17:19

ASP.NET面試題目ASP.NET

2015-07-31 09:34:44

Java面試題

2009-08-18 10:30:32

2019-02-21 14:12:26

前端面試題Vue

2019-02-18 11:20:59

shell面試題命令
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)