【C 語言】1、 C 和 C++有什么不同?
1)C語言面向過程編程,重程序的實現;C++面向對象編程,重程序的設計;
2)C是C++的一個子集;C++全面兼容C;
3)C++相對于C引入了重載、內聯函數、異常處理、類的封裝/繼承/多態、以及STL/容器類等…
2、進程和線程的異同、關系?
1)進程:是系統資源分配和調度的基本單位,有自己的pid;
線程:是運行的基本單位,有自己的tid。
2)進程:一個進程至少擁有1個線程,為主線程;
線程:同一個進程中的線程可以并發,且共享進程的資源,擁有自己獨立的??臻g和執行序列。
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:臨時局部變量存放區。棧幀數據歲函數結束而消失?!?strong>后進先出
堆heap:動態內存區。程序運行時malloc和new動態申請的區域?!?strong>手動申請/釋放
BSS:靜態內存分配區。存放未初始化的全局變量?!?strong>可讀可寫
數據段data:靜態內存分配區。存放已初始化的全局變量、靜態局部變量?!?strong>可讀可寫
代碼段text:存放程序執行代碼、只讀常量區域?!?strong>只讀
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被返回;
失?。涸诟高M程里返回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++容器的分類及各自的特性?
新聞熱點
疑難解答
圖片精選