[No0000166]CPU的組成結構及其原理

中央處理器(Central Processing Unit, CPU)

CPU
的基本架構和工作原理其實百科上講得已經相當清楚了,不過我覺得有些事情呢還是給個例子出來比較方便學習。
本文會先從內存地址,計算機的一般架構之類的基礎知識出發,然后逐步為讀者"拼裝"出一個超級簡單的8-bit CPU。。。就像下圖這樣(大圖點開)

這就是本文的目標:拼裝這樣一個結構的CPU

-----------------------------------------------------------------------------------------------------------------------

上面那個大圖里有幾個梯形的符號
它們叫做數據選擇器(Multiplexer),也叫多路選擇器或多路開關
已經知道這個東西是干啥的童鞋直接跳過此樓吧。。

這圖是一個21選擇器,A,B,S為輸入,Z為輸出,它們可取的值當然都只有01
怎么工作的呢?
以該圖為例:
S=1的時候,輸出值Z = 輸入值B
S=0的時候,輸出值Z = 輸入值A
比如說A=1,B=0,S=0的時候輸出是多少?S=0就是說:選擇A的值輸出,也就是說輸出值Z=A=1
就這么簡單

同樣地,我們也可以有41選擇器

只不過控制輸入S變成了兩位(00,01,10,11,分別對應一二三四),道理還是一樣的

如果你對這個東東怎么做成的感興趣的話。。。下面就是41選擇器的其中一種電路 = =

哦,還有。。本文使用的邏輯門符號均是ANSI/IEEE Std 91-1984中的Distinctive shape,不是用方框符號。。。= =

你只要知道數據選擇器是干啥的就好,不用惦記上邊那電路。。

------------------------------------------------------------------------------------------------------------

1. 計算機架構(Computer Architecture)

CPU
、內部存儲器(Internal Storage Device)和輸入/輸出設備(Input/Output Device, I/O)是電子計算機三大核心部件。內部儲存器可以是硬盤,內存,緩存等;輸入設備可以是鼠標,鍵盤;輸出設備可以有屏幕,音箱等等。。

當你打開電腦硬盤上安裝的某個程序時,你的操作系統會把硬盤上的相應內容放入內存中。至于怎么放,在內存的什么地方放那可是一門大學問,光這個就夠一般人喝一壺的。。相關知識可以在大學的操作系統課程里學到

比如說你放個音樂。要放音樂,先用鼠標點開一個mp3文件,于是你就使用了一個輸入設備。這個輸入設備會把一個中斷請求(Interrupt Request)送到CPU那邊,結合來自操作系統的信息后CPU就知道:哦,你用鼠標點開那個mp3文件了!于是:
1. CPU
執行操作系統里關于文件關聯的代碼,于是你的電腦就知道要用WMP打開文件了
2.
你的操作系統開始把WMP這個程序里含有的指令和mp3文件的內容從硬盤上拉進內存里(還是CPU的工作)
3.
然后你的CPU開始一條一條地(雙核的話那你就當成兩條兩條地好了)執行內存里的WMP程序指令(也就是如何解碼mp3),并且把解碼后的PCM比特流傳到聲卡上,再由聲卡把數字信號轉換成模擬信號送到音箱/耳機(輸出設備)里。So now you have music

又比如說你要編輯一個txt文件。還是先得用鼠標點開文件,又用了一次輸入設備。于是:
1. CPU
執行操作系統里關于文件關聯的代碼,于是你的電腦就知道要用notepad打開文件了
2.
你的操作系統把notepad的程序指令和文件內容拉進內存
3.
然后你的CPU又開始執行Notepad程序的指令了
4.
每當你敲一次鍵盤(還是輸入設備!!),都會向CPU發送一個中斷請求好讓CPU知道你敲了某個鍵。比如說你敲個Y,那么CPU就會把Y這個字符寫進內存里。然后你要保存的時候操作系統就會把內存里改過的東東倒進硬盤里!~

。。。好吧我承認實際過程跟這兒說的不大一樣并且復雜得多,有些細節會在后面詳細講,but that's the basic idea.

這大約就是CPU,輸入/輸出設備和內存之間的互動方式了。

---------------------------------------------------------------------------------------------------

2.內存(Memory)

內存就是暫時存儲程序以及數據的地方,比如當我們在使用WPS處理文稿時,當你在鍵盤上敲入字符時,它就被存入內存中,當你選擇存盤時,內存中的數據才會被存入硬盤。一斷電內存上的東東就沒了

內存里的數據是根據內存地址(Memory Address)來組織的。每個地址都是獨特的,每個地址一般來說對應著一個字節(byte)=8 bit,我們管這叫Byte addressable memory.

32 bit的系統上,內存地址的長度就是32 bit。那么一個32 bit長度的二進制數最大可以表示的數是多少呢?很簡單,2^32 = 4294967296。也就是說,32 bit的內存地址最大可以對應4294967296字節的內存!

這個數字換算一下就可以得出它相當于4GB。現在你知道為什么32位系統不支持4GB以上的內存了嗎?

------------------------------------------------------------------------------------------------------

3. 指令編碼(Instruction Encoding)

終于要說點正經的了。。前面說過CPU會執行內存/緩存中的程序指令,可是這些指令是以什么樣的形式儲存在內存里的呢?要知道所謂的指令其實就是一長串的01而已。那CPU如何從這些01里知道指令是什么呢?這就是指令編碼的內容了。

先說說CPU。您說,CPU能干啥?其實很簡單,無非就是加減乘除,讀寫內存,邏輯運算什么的。若是復雜些的CPU可能指令集要大些,不過基本的指令大概就這些。CPU內部也有自己的儲存單元,叫做寄存器(Register),也是暫時用來放數據的地方,速度特別快,容量特別小。
就拿我經常用的NIOS II來說,它內部有32個寄存器,它可以執行的指令包括(不好意思我要用匯編語言了=_=):

add rA,rB,rC #
把寄存器rB,rC里的數加起來,結果放入寄存器rC
addi rB, rA, IMM16 #
rA里的數跟一個16位的數相加,結果放入rB
beq rB,rA,LABEL #
rA=rB,則跳到LABEL指定的內存地址開始執行指令,否則繼續按照內存地址順序執行指令
stwio rB, b_o(rA) #
從內存地址rA+b_o處讀取一個字節,數據放入rB
ldwio rB, b_o(rA) #
從內存地址rA+b_o處開始寫入一個字節,寫入的數據在rB


等等

總結起來,CPU可以有以下幾個功能:
1.
進行寄存器之間的運算和比較
2.
由寄存器內指定的地址讀寫內存
3.
分支指令,類似于C語言里的if語句。比如跳到某個寄存器里指定的內存地址開始讀取并執行指令

當然,更復雜的指令集是有可能的,不過這里就不說了

---------------------------------------------------------------------------------------------

我知道讀者可能好幾樓沒見著個圖有點煩躁了,不過請有些耐心,等開始拼裝CPU的時候圖片絕對多。。。

Anyway
,繼續說指令編碼
大致來說,上面的指令可以分為三大類:I-type,R-type,J-type
P.S.
這種分類適用于MIPS架構的處理器,其他我就不知道了

1. I-type
32 bit為例。一條I-type指令包括四個元素:
兩個寄存器編號,一個16位數字和一個操作碼

31-27
位代表指令里寄存器rA的編號
26-22
位代表寄存器rB的編號
21-6
位是一個16位的二進制數
5-0
位是操作碼

例子:
NIOS II
匯編指令 addi r6,r7,310表示把寄存器r7里的數加上310,結果放入寄存器r6。如果我們規定addi運算對應的六位操作碼是000011,那么請問整條指令的編碼是?
解答:
寄存器r6的編號是6,即00110
寄存器r7的編號是7,即00111
數字310對應的二進制數是0000000100110110
addi
的操作碼是000011
所以整條指令的編碼就是00110 00111 0000000100110110 000011
-----------------------r6-----r7--------310---------addi------
32位!
這就是I-type指令在內存里存在的形式!!~

----------------------------------------------------------------------------

2. R-type

還是以32 bit為例。一條R-type指令通常包括四個元素:
三個寄存器編號,一個操作碼

31-27
位是寄存器rA的編號
26-22
位是寄存器rB的編號
21-17
位是寄存器rC(一般來說這個是目標寄存器)的編號
16-6
位是OPX,是操作碼
5-0
位。。你當它沒用吧,寫上000000就好 = =

例子:
匯編指令 add r10,r9,r8是典型的R-type指令。它表示把寄存器r9,r8里的數加起來,然后把結果寫入寄存器r10(目標寄存器)。若規定add運算的操作碼為00000011111,請問整條指令的編碼是?
解答:
寄存器r10的編號是10,即01010
寄存器r9的編號是9,即01001
寄存器r8的編號是8,即01000
add
運算操作碼是00000011111
OP = 000000
所以整條指令的二進制編碼是01001 01000 01010 00000011111 000000
---------------------------r9-----r8---r10------add-------OP
32位!

-----------------------------------------------------------------------------------------

3. J-Type

一條32bitJ-Type指令包含兩個元素:
一個26位的數字(通常是內存地址)和一個6位的操作碼

31-6
位是數字
5-0
位是操作碼

例子:
匯編指令 call ROUTINE_3是典型的J-Type指令,它表示該指令執行完畢后CPU將從ROUTINE_3開始的內存地址讀取并執行其他指令。若ROUTINE_3開頭指令的內存地址是0x00002b3ccall的操作碼是000000,請問整條指令的二進制編碼是?
解答:
16
進制數0x00002b3c = 0000 0000 0000 0000 0010 1011 0011 1101
call
操作碼是000000
所以整個指令的編碼是00000000000000000010101100111101 000000
------------------------------ROUTINE_3--------------call--
還是32位!

4.再說些CPU的事情

讓我試著用圖片總結一下前面的基礎知識。。

上圖概括了CPU和計算機其他部分的互動方式。該圖與實際的計算機有很大差距,but you get the idea...現在讓我們把注意力集中在CPU身上!

CPU
只知道執行指令,而指令是在內存里的(實際上不一定,但是為了讓事情簡單些,我們假設指令都是在內存里的)。所以CPU需要從內存里取出指令,這一步叫做提取(Fetch)

CPU
還需要知道這條指令是干什么的,所以被編碼過的指令會被傳到CPU的控制電路那邊解碼以正確設置控制信號,這樣CPU才能正確執行指令,這一步叫解碼(Decode)

上面兩步完成后CPU就可以執行該條指令了,也就是執行(Execute)
運算后的結果經常需要保存,用來進行下一個指令的運算。那保存在哪里呢?無非就是寄存器組和內存。這一步叫做寫回(Writeback)

CPU
的結構簡圖(省略了到輸入/輸出設備的連接)

時鐘信號(Clock Signal)說白了其實就是一個頻率很高的方波,就像這樣:

它控制著CPU內核的工作節奏,每當時鐘信號由01(rising edge)的時候,CPU里面的元件就會做點什么。

數據通路(Datapath)是一個能夠執行任何指令集內的指令的電路,但是它需要控制電路告訴它應該在什么時候執行什么指令。數據通路包括了寄存器組,算術邏輯單元(Arithmetic logic unit, ALU)以及很多其他的元件。

控制電路負責解碼指令并且正確設置控制信號,于是數據通路就能根據這些控制信號知道應當執行哪一條指令。

----------------------------------------------------------------------------------------------------------

5. 好了,開始搭CPU = =

如果讀者到目前為止都還能懂的話,那么恭喜!你終于有了足夠的基礎知識來搭建一個簡單的CPU了。
當然了,CPU這玩意不是說搭就搭的。我們的CPU能干些什么?能執行些什么指令?指令是怎么編碼的?它由哪些小模塊組成?都有哪些控制信號?這些問題都必須有明確的回答。

從現在開始,我強烈建議讀者拿幾張空白的紙出來記下這些問題的回答,因為我們即將面對的是眾多的指令,模塊以及控制信號。這可比拼裝家具復雜多了,如果不記下來的話到時大概會頭暈目眩。

當初LZ對這個CPU做一丁點兒小改動的時候,可得對著一張電路圖,大大的控制信號表格以及超長的Verilog HDL代碼,花了不少時間和草稿紙呢

I will be back tomorrow or after 3 hours...~

--------------------------------------------------------------------------------------------------------------

我們的CPU能做什么?

從現在開始將進入本文最復雜,最能繞暈人的部分,請做好準備。。
下面要開始說明這個CPU的規格,信息量略大,推薦寫在紙上記著。

現在我們對下面的行**幾個簡化約定(要是不簡化的話,讀者就會看到一大堆密密麻麻的描述文字),請務必記好。

TMP = MEM[R2]
這個語句表示從寄存器R2指定的內存地址讀取數據,然后把讀到的數據賦值給TMP
舉個例子:如果寄存器R2里的數字是0001 0011
而內存地址0001 0011處所存的數據是1111 1111
那么這個語句就表示TMP被賦值1111 1111TMP = 1111 1111

MEM[R2] = TMP
這個語句表示TMP的值被寫入內存,寫入的位置是內存地址R2
舉個例子:如果TMP = 1111 1110R2 = 0000 0001
那么這個語句就表示內存地址0000 0001處的數據變成了1111 1110

R1 = TMP
這個語句表示寄存器R1寫入TMP的值
舉個例子:如果TMP = 0000 1111
那么這個語句表示寄存器R1里的數字變成了0000 1111

PC = PC + 1
幾乎每個指令都會帶有這個語句,意思是PC寄存器里的數字加1
PC
寄存器中有指令所在的內存地址。每執行完一條指令后,這個內存地址一般都會加1,好讓CPU調出下一條指令

-------------------------------------------------------------------------------------------------

前面說過,我們的CPU8-bit的,也就是說它最多只能支持2^8=256個內存地址。我們的CPU內部將會有四個通用寄存器(General Purpose Register)R0~R3,一個PC寄存器(Program Counter Register),每個寄存器容量為8 bit。這個CPU不支持中斷,意味著它不接受鍵盤和鼠標的輸入,只會從內存里讀取并執行指令。另外,CPU內部還有兩個特殊的比特位,NZ。如果某個運算的結果是負數,那么N就會被設定為1;如果某個運算結果為零,那么Z就被設定為1。我們將會在跳轉指令里用到這兩個比特位。

CPU可以執行10種指令:

1. LOAD R1 (R2)
實現方法:
TMP = MEM[R2]
R1 = TMP
PC = PC + 1
這條指令是把內存地址R2處的數據讀出來,然后放進寄存器R1里。接著PC寄存器加一為下一條指令做準備。看出來了嗎?下面將不再有這種文字描述,全部使用簡寫。

2. STORE R1 (R2)
實現方法:
MEM[R2] = R1
PC = PC + 1

3. ADD R1 R2 [
加法運算]
實現方法:?
TMP = R1 + R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

4. SUB R1 R2 [
減法運算]
實現方法:
TMP = R1 - R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

5. NAND R1 R2 [NAND
邏輯運算]
實現方法:
TMP = R1 NAND R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

6. ORI IMM5 [OR
邏輯運算]
實現方法:
TMP = R1 OR IMM5, IMM5
是一個5-bit的二進制數
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

7. SHIFT L/R R1 IMM2 [
移位運算]
實現方法:
IF (L) THEN TMP = R1 << IMM2
ELSE TMP = R1 >> IMM2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

8. BZ IMM4 [
如果Z=1,就跳過IMM4個指令]
實現方法:
IF (Z == 1) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1

9. BNZ IMM4 [
跟上一條指令相反]
實現方法:
IF (Z == 0) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1

10. BPZ IMM4 [
N = 0,就跳過IMM4個指令]
實現方法:
IF (N == 0) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1

這些描述都比較抽象,做拼裝的時候這些東西應該會表現得更具體些。

---------------------------------------------------------------------------------------------------

CPU的指令編碼

5個指令的編碼方式都是:
7-6
位是寄存器R1的編號
5-4
位是寄存器R2的編號
3-0
位是操作碼


ORI
指令的編碼


SHIFT
指令的編碼


三個跳轉指令的編碼

--------------------------------------------------------------------------------------------------------------------------

數據通路的設計

這個CPU的數據通路將由以下部件組成:
寄存器

data in ----------
寫入寄存器數據,8條線,因為是8-bit
data out ----------
輸出寄存器的數據,8條線,因為是8-bit
控制信號write ---------- 是否允許寫入數據。是的話write = 1, 否則 write = 0
clock ----------
時鐘信號
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

數據選擇器

相信諸位都應該知道這玩意怎么工作的吧?當然輸入輸出都是8條線
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

通用寄存器組

通用寄存器R0-R3都在這里面。
reg1,reg2 ----------
說明指令里涉及哪兩個寄存器
regw ----------
指明要往哪個寄存器里寫數據(應該是2條線,沒畫出來)
data0 ----------
reg1指定的寄存器中輸出數據
data1 ----------
reg2指定的寄存器中輸出數據
dataw ----------
實際寫入寄存器的數據從這里進去(應該是8條線,沒畫出來)
控制信號write ---------- 是否允許寫入數據?是的話write = 1,否則write = 0
clock ----------
時鐘信號
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

算術邏輯單元(ALU)

這個模塊就是CPU做運算的地方了。它能實現加減法,NANDOR運算,以及移位運算。
In0,In1 ----------
輸入
控制信號ALUop ---------- 告訴ALU應該做哪個運算
Z,N ----------
前面提過的特殊比特位,ALU要負責根據運算結果設置ZN
OUT ----------
運算結果輸出

-----------------------------------------------------------------------------------------------------------------

繼續說CPU組件。。。

指令內存

addr ----------
指定從哪個內存地址讀取指令
Out ----------
從內存里輸出的指令在這里去往CPU
控制信號Read ---------- 是否允許讀取指令?是的話Read = 1, 否則 Read = 0
我們假設指令內存是只讀(Read Only)
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

數據內存

addr ----------
指定從哪個內存地址讀取數據
Din ----------
往內存里寫的數據從這里進去
Dout ----------
從內存里讀取的數據從這里出去
Clock ----------
時鐘信號
控制信號MemWrite ---------- 是否允許數據寫入內存?是的話MemWrite = 1, 否則為0
控制信號MemRead ---------- 是否允許讀取?是的話MemRead = 1,否則為0
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

現在我們要用上面的模塊去組裝CPU的數據通路。

首先,無論執行的是哪一條指令,CPU都必須先從內存里把指令調出來,前面說過這一步叫做提取。此步驟由下圖的電路執行。

這個電路由一個PC寄存器(Program Counter Register)和指令內存組成。PC寄存器里儲存的是該條指令所在的內存地址,然后指令內存會根據PC寄存器指定的地址向CPU輸出相應的指令。控制信號PCWrite決定是否允許更改PC寄存器里的數字,如果允許那么PCWrite = 1, 否則為0

-------------------------------------------------------------------------------------------------

能執行加法指令的電路

前面說過加法指令ADD R1 R2的編碼形式如下

該指令會把寄存器R1R2里的數字加起來,然后把結果寫回R1
INST
線的3-0位是操作碼,會被送到控制電路那邊解碼。解碼后控制電路會設置好各個控制信號使得CPU的數據通路執行加法運算。我們以后再詳細說說控制電路的事情,現在讓我們來看看在數據通路里,INST7-4位是如何使用的。


上圖是一個可以執行加法指令的電路(圖里的數字有點小錯誤,不要在意)
INST 7-6
位代表R1的編號,作為通用寄存器組的reg1regw輸入
INST 5-4
位代表R2的編號,作為reg2的輸入
然后R1R2里的數據從data0,data1輸出,送到ALU做加法運算(ALUop會告訴ALU做加法運算)
TMP = R1 + R2
完成
然后加法運算的結果被送到寄存器組的dataw輸入。這時RFWrite = 1。由于此時regw指定的寄存器編號是R1,所以加法運算的結果就被寫回了寄存器R1
R1 = TMP
完成
此外,ALU還會把NZ這兩個特殊的比特位根據運算結果設置好
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
完成

這條指令還沒完,我們需要把PC寄存器里的數字加一,這樣CPU才能取得下一條指令。因此還得加點東西。

有了上面那個電路之后
PC = PC + 1
就可以完成了

同樣的電路也可以用作執行SUBNAND指令。唯一不同的是控制信號ALUop會讓ALU做減法或者NAND運算。

-----------------------------------------------------------------------------------------

執行ORI指令的電路

ORI IMM5
的編碼

這個指令會把寄存器R1里的數字與一個5-bit的二進制數做OR運算,然后把結果寫回R1
要實現這個指令只需把上面的電路稍作更改即可


可以看到這個電路增加了兩個數據選擇器(圖中的reg0,reg1應分別為reg1,reg2)
首先,因為ORI指令總是在寄存器R1上進行操作,不像ADD,SUB,NAND等其他指令需要指定在哪些寄存器上進行操作,所以我們加入一個控制信號為R1Sel的選擇器。
當執行ORI指令時,R1Sel = 1,這樣reg1的輸入在執行ORI指令時總會是01
所以data0輸出也總是會輸出R1的數據到ALU
這時,ALU的另外一個輸入應當是指令里的IMM5,而不是從寄存器組那邊過來的輸入
于是我們加入另一個控制信號為ALU2的選擇器,這樣我們就可以選擇是從寄存器組還是從INST線那邊輸入ALU數據。
當執行ORI指令時,ALU2 = 1,這樣ALU就會把INST 7-3位的5-bit二進制數作為輸入
然后控制信號ALUop告訴ALU進行OR運算
TMP = R1 OR IMM5
完成
結果寫回R1
R1 = TMP
完成
ALU
根據運算結果設置NZ
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
完成
PC
寄存器加一,CPU為下一條指令做好準備
PC = PC + 1
完成

-----------------------------------------------------------------------------------------------------------------


-----------------------------------------------------------------------------------------------------

能執行內存讀取以及SHIFT指令的電路

LOAD R1 (R2)
STORE R1 (R2)
由于這兩條指令里的R2部分總是作為地址使用,所以寄存器R2的輸出要連到數據內存的addr輸入;而R1STORE指令中是作為數據源的寄存器使用的,所以連接到Datain輸入。R1LOAD指令中是作為放內存讀出數據的寄存器使用的,所以連回到寄存器組的dataw輸入。中間加了一個RFin選擇器,這樣寄存器組就可以選擇是從ALU還是從數據內存那邊寫入數據。

現在我們要把數據內存加入我們的電路里,如下圖:

最后我們還把ALU2選擇器擴展了一下,使得執行SHIFT指令時ALU能夠選擇從INST線讀到運算需要的數據(圖中的INST 5-2應當為INST 4-3,因為SHIFT指令的IMM2在指令編碼的4-3)

然后這個CPU的數據通路就基本完成了!!

轉載于:https://www.cnblogs.com/Chary/p/No0000166.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451402.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451402.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451402.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java 時間總結

轉載請標明出處&#xff1a;http://blog.csdn.net/zhaoyanjun6/article/details/80613024 本文出自【趙彥軍的博客】 時區 整個地球分為二十四時區&#xff0c;每個時區都有自己的本地時間。為了統一起見&#xff0c;使用一個統一的時間&#xff0c;稱為通用協調時(UTC, Univer…

js中的var是什么意思

聲明&#xff08;創建&#xff09; JavaScript 變量 在 JavaScript 中創建變量經常被稱為“聲明”變量。您可以通過 var 語句來聲明 JavaScript 變量&#xff1a;var x; var carname; 在以上聲明之后&#xff0c;變量并沒有值&#xff0c;不過您可以在聲明它們時向變量賦值&…

HTTP/2 協議入門

一、2015年&#xff0c; HTTP/2發布。 二、二進制協議 HTTP/2是一個二進制協議&#xff0c;頭信息和數據體都是二進制&#xff0c;并且統稱為“幀”&#xff08;frame&#xff09;,頭信息幀和數據幀。 二進制協議的一個好處是&#xff0c;可以定義額外的幀。HTTP/2定義了近1…

態度決定高度

“一個將什么都不放在眼里的人&#xff0c;他的未來一定是一片黑暗&#xff0c;因為他什么都看不到”。知識的獲得和能力的鍛煉是個一點一滴慢慢積累的過程&#xff0c;這個過程需要我們端正態度&#xff0c;俯身求教。好高騖遠一直都是很多人容易犯的錯誤&#xff0c;這樣導致…

中間件技術是什么?

&#xff08;一&#xff09;舉例說明&#xff1a; 我開了一家炸雞店&#xff08;業務端&#xff09;&#xff0c;然而周邊有太多屠雞場&#xff08;底層&#xff09;&#xff0c;為了成本我肯定想一個個比價&#xff0c;再綜合質量挑選一家屠雞場合作&#xff08;適配不同底層邏…

4.10/4.11/4.12 lvm講解 4.13 磁盤故障小案例

2019獨角獸企業重金招聘Python工程師標準>>> 準備磁盤分區 fdisk /dev/sdb n 創建三個新分區&#xff0c;分別1G t 改變分區類型為8e 準備物理卷 pvcreate /dev/sdb1 pvcreate /dev/sdb2 pvcreate /dev/sdb3 pvdisplay/pvs 列出當前的物理卷 pvremove /dev/sdb3 刪除…

《Effective Java》 第一講:創建和銷毀對象

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一、用靜態工廠方法代替構造器 用靜態工廠的優點 &#xff1a; 1. 方法有名字&#xff0c;更好理解。 2.不必每次調用的時候都創建一…

外圍功能電路控制 LET′S TRY“嵌入式編程”: 4 of 6

外圍功能電路控制 LET′S TRY“嵌入式編程”: 4 of 6本連載講解作為嵌入式系統開發技術人員所必需具備的單片機的基礎知識。 在《單片機入門&#xff08;1&#xff09;&#xff5e;&#xff08;3&#xff09;》中&#xff0c;我們一起學習了單片機的硬件和編程語言以及開發環境…

如何防止代碼腐爛

很多團隊都有這個問題&#xff0c;一個項目的代碼本來開始設計得好好的&#xff0c;一段時間以后&#xff0c;代碼就會變得難以理解&#xff0c;難以維護&#xff0c;難以修改。為什么&#xff1f;我一直在思考這個問題。 讓我們先看一個人的情況。 1. 程序員的成長 新手的代碼…

什么是商業智能(BI),以及其與數據分析的區別?

BI&#xff08;Business Intelligence&#xff09;即商務智能&#xff0c;它是一套完整的解決方案&#xff0c;用來將企業中現有的數據進行有效的整合&#xff0c;快速準確地提供報表并提出決策依據&#xff0c;幫助企業做出明智的業務經營決策。它是一種產品/服務&#xff0c;…

php課程 4-15 數組遍歷、超全局數組、表單提交數據(多看學習視頻)

php課程 4-15 數組遍歷、超全局數組、表單提交數據&#xff08;多看學習視頻&#xff09; 一、總結 一句話總結&#xff1a;超全局數組特別有用&#xff0c;比如$_SERVER可以獲取所有的客戶端訪問服務器的情況。 1、數組遍歷三種方式&#xff08;最不熟悉的那一種&#xff09;…

git branch 分支

Git自學之路&#xff08;四&#xff09;- git branch 分支 幾乎所有的版本控制系統都以某種形式支持分支。 使用分支意味著你可以把你的工作從開發主線上分離開來&#xff0c;以免影響開發主線。 在很多版本控制系統中&#xff0c;這是一個略微低效的過程——常常需要完全創建一…

軟件工程師的十個“不職業”行為

職業化是軟件工程師的必然選擇。本文根據我在教學和軟件開發管理方面的實踐&#xff0c;列舉幾個軟件工程師“不職業”的行為或習慣&#xff0c;從另外一個側面進一步探討什么是真正的軟件工程師職業化。職業化之于軟件工程師非常重要。因為&#xff1a;軟件是看不見也摸不著的…

fn:substring()函數

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 fn:substring()函數返回字符串中指定開始和結束索引的子串。 語法 fn:substring()函數的語法如下&#xff1a; ${fn:substring(<s…

大數據分析如何創建最佳的移動應用用戶體驗

2019獨角獸企業重金招聘Python工程師標準>>> 如今&#xff0c;越來越多的人使用移動應用程序。而移動應用將在未來成為一個價值數十億美元的產業。大數據可以幫助企業構建最佳的用戶體驗。 多年來&#xff0c;開發移動應用程序的技術一直在不斷發展&#xff0c;這實…

C語言自學的方法

一、C語言入門的基本學習方法 《C語言》的內容很豐富&#xff0c;有的部分涉及到的細節很多&#xff0c;如硬件知識和數據結構知識等&#xff0c;自學時不可能面面俱到&#xff0c;否則必然會顧此失彼&#xff0c;反而抓不住主要矛盾。筆者認為對初學C語言的考生&#xff0c;開…

CAP原理簡單理解

C&#xff1a;集群中所有機器狀態是一致的。 A&#xff1a;客戶端訪問集群中任意一個節點&#xff0c;總能得到"處理成功"的結果。 假設有五個節點&#xff1a;n1~n5 &#xff0c;出現網絡分區被分成兩組&#xff1a;[n1~n2]和[n3~n5]&#xff0c;那么當n1出來客戶端…

Jstorm+Spring+mybatis整合

在現有的jstorm框架下&#xff0c;有一個需求&#xff1a;jstorm要對接mysql數據庫的實時讀取數據&#xff0c; 通過bolt處理&#xff0c;可能要調用service層的框架&#xff0c;最后保存到數據庫。 在網上尋找了一下&#xff0c;發現storm集成spring的資料非常少&#xff0c;有…

無限享受百度文庫,財富值無視

相信大家在百度上找東西時&#xff0c;遇到有的文庫需要財富值&#xff0c;可是自己又沒有&#xff0c;是不是很頭疼啊。請看&#xff1a; 找到自己要的文庫&#xff0c;如我找的文庫鏈接為&#xff1a;http://wenku.baidu.com/view/7db6 ... html?l5.1.5.1&&#xff08;…

JavaScript onerror 事件( window.onerror = )

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 使用 onerror 事件是一種老式的標準的在網頁中捕獲 Javascript 錯誤的方法。 實例 onerror 事件 如何使用 onerror 事件捕獲網頁中的錯誤…