程式語言 誠邁試題二

2021-06-27 23:27:58 字數 4779 閱讀 3337

1. linux核心記憶體分配方式

linux核心

位址空間劃分0~3g為使用者空間,3~4g為核心空間

2. new/delete和

malloc/free

的區別

(1)操作物件有所不同。 

malloc與free是c++/c語言的標準庫函式,new/delete是c++的運算子。對於非內部資料類的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件消亡之前要自動執行析構函式。由於malloc/free是庫函式而不是運算子,不在編譯器控制許可權之內,不能夠把執行建構函式和析構函式的任務強加malloc/free。

(2)在用法上也有所不同。函式malloc的原型如下:void * malloc(size_t size); 

用malloc申請一塊長度為length的整數型別的記憶體,程式如下:int *p = (int *) malloc(sizeof(int) * length); 

malloc返回值的型別是void *,所以在呼叫malloc 時要顯式地進行型別轉換,將void * 轉換成所需要的指標型別。 

malloc 函式本身並不識別要申請的記憶體是什麼型別,它只關心記憶體的總位元組數。 

函式free 的原型如下: 

void free( void * memblock ); 

為什麼free 函式不象malloc 函式那樣複雜呢?這是因為指標p 的型別以及它所指的記憶體的容量事先都是知道的,語句free(p)能正確地釋放記憶體。如果p 是null 指標,那麼free  

對p 無論操作多少次都不會出問題。如果p 不是null 指標,那麼free 對p連續操作兩次就會導致程式執行錯誤。 

new/delete 的使用要點 

運算子new 使用起來要比函式malloc 簡單得多

3. 驅動中斷

在linux裝置驅動程式設計中的中斷服務程式執行並不存在程序的上下文,因此在請求中斷服務程式的時間盡可能的短,因此,linux在中斷處理中引入了頂半部和底半部分離的機制。

所謂的中斷就是指cpu在執行程式的過程中,出現了某些突發事件待急處理,cpu必須暫停當前執行的程式,轉去處理突發事件,處理完畢後cpu又會返回原程式被中斷打斷的位置並繼續執行。根據中斷源,中斷可以分為內部中斷和外部中斷,內部中斷的中斷源來自cpu內部(軟中斷指令,溢位,除法錯誤等),外部中斷來自cpu處理器的外部,由於在arm處理器中可以有硬體可控制中斷,所以提供了外部中斷請求。

在linux核心中為了處理中斷的時間竟可能短和中斷處理完成大量工作之間找到乙個平衡點,linux將中斷處理分為頂半部和底半部,在頂半部完成盡可能少的緊急功能,它往往只是簡單的讀取暫存器中中斷狀態並清除中斷標誌後就進行登記中斷的工作,登記中斷的意味將底半部處理程式掛到裝置的底半部執行佇列中去,這樣頂半部可以盡可能快的服務更多的中斷請求,而底半部則要處理完中斷的所有事情。

在linux核心中對於中斷的請求和釋放都要使用到核心的request_irq()和free_irq()函式,而在底半部機制中主要有tasklet,工作佇列和軟中斷

4. 緊湊模式和非緊湊性模式

struct a;

struct b;

緊湊模式:sizeof(a) =1+1+2+4+8=16

非緊湊模式:sizeof(b) =4+4+4+8=20

5. 堆和棧的區別

1)程式的記憶體分配:

棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等

堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由os**

2)申請方式:

stack:

由系統自動配

heap:

需要程式設計師自己申請,並指明大小

3)申請效率的比較:

棧由系統自動分配,速度較快。但程式設計師是無法控制的。

堆是由new分配的記憶體,一般速度比較慢,而且容易產生記憶體碎片,不過用起來最方便.

4)申請後的系統響應及大小限制:

棧:只要棧的剩餘空間大於所申請空間,系統將為程式提供記憶體,否則將報異常提示棧溢

出。會遍歷該鍊錶,尋找第乙個空間大於所申請空間的堆結點,然後將該結點從空閒結點鍊錶

中刪除,並將該結點的空間分配給程式,另外,對於大多數系統,會在這塊記憶體空間中的

首位址處記錄本次分配的大小,這樣,**中的delete語句才能正確的釋放本記憶體空間。

另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部

分重新放入空閒鍊錶中。

5)堆疊的儲存內容 :

執行語句)的位址,然後是函式的各個引數

,引數是由右往左入棧

的,然後是函式中的區域性變數。注意靜態變數是不入棧的。

當本次函式呼叫結束後,區域性變數先出棧,然後是引數,最後棧頂指標指向最開始存的地

址,也就是主函式中的下一條指令,程式由該點繼續執行。

堆:一般是在堆的頭部用乙個位元組存放堆的大小。堆中的具體內容由程式設計師安排。

6. 呼叫函式時的壓棧順序

在函式呼叫時,第乙個進棧的是主函式中後的下一條指令(函式呼叫語句的下一條可

執行語句)的位址,然後是函式的各個引數

,引數是由右往左入棧

的,然後是函式中的區域性變數。注意靜態變數是不入棧的。

7. 區域性變數和全域性變數

1)全域性變數具有全域性作用域。全域性變數只需在乙個原始檔中定義,就可以作用於所有的原始檔。當然,其他不包括全域性變數定義的原始檔需要用extern關鍵字再次宣告這個全域性變數 2)

區域性變數只有區域性作用域,

它是自動物件,他在程式執行期間不是一直存在,而是只在函式執行期間存在,函式的一次呼叫結束後,變數就被撤銷,其所占用的記憶體也被收回。

8. bootloader啟動過程

第一步:當系統在上電或者復位的後,

cpu的pc指標會指向實體地址的0x00000000處,這裡的實體地址表示片內的irom儲存器,它固化了系統啟動的bl0引導**,這段**會選擇以什麼方式啟動,就會找到bootloader的bl1存放的位址,由於bl1不支援片上執行,所以會把irom這段**拷貝到iram中去,

但是在拷貝之前,

irom

會先把iram

的起始4個位址分別寫上一定的內容(不過通常只寫0x00位址為bl1所佔空間的大小(一般是8k),而其他三個位址全寫為0),把bl1這段**拷貝到

iram

後,irom

的使命就快要完成了,

irom

的最後乙個任務就是把

pc指標指向放bl1的那塊位址的起始位置,然後就按照這個位址的指令開始執行。

第二步:這個時候開始執行bl1的**。這段**的功能是初始化硬體,比如串列埠,記憶體,顯示器,按鍵等

,還有電源、時鐘初始化,堆疊空間,以及各種必要的初始化,並且會提供乙個命令列,可以進行互動。在這之後會有乙個設定核心引數的過程,這些引數在記憶體中的存在方式也是以結構體儲存,以鍊錶進行關聯的,而這個 鍊錶有乙個固定的起始位址0x30000100;每乙個結構體代表乙個資訊,並首尾相連,核心在需要這些引數時,就可以再對應的位址上取資料。

第三部:第二步

執行完畢後,就要把kernel的**拷貝到

sdram

中的乙個指定位址,

在linux中一般拷貝到實體地址的0x20008000處,

並且會把這個位址強制轉換成乙個函式指標,並且向這個函式中傳遞一些引數,最終會到核心中執行核心**。這個時候,核心就會被引導到執行狀態。

9. 巨集定義、內聯函式、和普通函式的區別

1)內聯函式的執行過程與帶引數巨集定義很相似,但引數的處理不同。帶引數的巨集定義並不對引數進行運算,而是直接替換;內聯函式首先是函式,這就意味著函式的很多性質都適用於內聯函式,即內聯函式先把引數表示式進行運算求值,然後把表示式的值傳遞給形式引數。 2)

內聯函式與帶引數巨集定義的另乙個區別是,內聯函式的引數型別和返回值型別在宣告中都有明確的指定;而帶引數巨集定義的引數沒有型別的概念,只有在巨集展開以後,才由編譯器檢查語法,這就存在很多的安全隱患 3)

巨集做的是簡單的字串替換(

只是字串的替換,不是其他型別引數的替換),而函式的引數的傳遞,引數是有資料型別的,可以是各種各樣的型別.

巨集的引數替換是不經計算而直接處理的,而函式呼叫是將實參的值傳遞給形參,既然說是值,自然是計算得來的.

巨集在編譯之前進行,即先用巨集體替換巨集名,然後再編譯的,而函式顯然是編譯之後,在執行時,才呼叫的.因此,巨集占用的是編譯的時間,而函式占用的是執行時的時間.

巨集的引數是不佔記憶體空間的,因為只是做字串的替換,而函式呼叫時的引數傳遞則是具體變數之間的資訊傳遞,形參作為函式的區域性變數,顯然是占用記憶體的.

10. 程序間通訊方式

傳統的程序間通訊方式:無名管道,有名管道和訊號

sys v ipc物件:共享記憶體,訊息佇列和訊號燈

bsd通訊方式:套接字

11. input子系統

輸入子系統由驅動層(drivers),輸入子系統核心層( input core )和事件處理層(event handler)三部份組成。乙個輸入事件,如滑鼠移動,鍵盤按鍵按下等都是通過 driver -> inputcore -> eventhandler -> userspace 的順序到達使用者空間傳給應用程式。下面介紹各部分的功能:

(1)驅動層功能:負責和底層的硬體裝置打交道,將底層硬體裝置對使用者輸入的響應轉換為標準的輸入事件以後再向上傳送給輸入子系統核心層(input core)。

(2)input系統核心層:input core即input layer,由driver/input/input.c及相關標頭檔案實現,它對下提供了裝置驅動層的介面,對上提供了事件處理層(event handler)的程式設計介面。

(3)事件處理層將硬體裝置上報的事件分發到使用者空間和核心。

C語言程式設計二

include include 統計給定的n個數中,負數 零和正數的個數。int main1 else if x 0 else printf d d d n fu,zero,zheng return 0 數列的定義如下 數列的第一項為n,以後各項為前一項的平方根,求數列的前m項的和。int main...

C語言 初學程式設計小試題

1.有個陣列,找出第二大的數,並且列印出來 int a 方法一 陣列 int main int max a 0 int max2 10000 int len sizeof a sizeof int for int i 0 i len i for int i 0 i len i printf 第二大的...

C語言經典筆試題(二)

21 關鍵字volatile有什麼含意?並給出三個不同的例 子。參 乙個定義為volatile的變數是說這變數可 能會被意想不到地改變,這樣,編譯器就不會去假設 這個變數的值了。精確地說就是,優化器在用到這個 變數時必須每次都小心地重新讀取這個變數的值,而 不是使用儲存在暫存器裡的備份。下面是vol...