① githubmarkdown以源碼方式顯示了
注意:Windows環境下載時,分為User版和System版(推薦),User版只能安裝在C盤的用戶文件夾下,System版可以自定義安裝位置,用戶可以安裝需求選擇下載哪個版本。
設置中文
安裝好VS Code後,軟體默認為英文,以下步驟可以將其設置為中文。
選擇View - Command Palette,或使用快捷鍵Ctrl+Shift+P,搜索configure language,然後選擇Configure Display Language,然後選擇zh-cn,如下圖。
在這里插入圖片描述
注意: 若選擇Configure Display Language後,未出現上圖所示選項,而是出現如下圖的json文件編輯頁面,則可能為舊版的VS Code,將json文件中的locale後面的en改為zh-cn,然後按照步驟3中安裝Chinese (Simplified)Language Pack擴展。
在這里插入圖片描述
若沒有zh-cn,可以選擇Install additional languages,然後安裝擴展包Chinese (Simplified) Language Pack,然後重復步驟1。
也可以先在View - Extensions中安裝Chinese (Simplified)Language Pack中文簡體語言包擴展,如下圖第1個擴展,然後進行步驟1。
在這里插入圖片描述
安裝擴展
在查看 - 擴展中可以查看、設置、啟用、禁用、卸載已安裝擴展,即對已安裝擴展進行管理,同時可以搜索並安裝各種擴展,如下圖。
在這里插入圖片描述
編輯Markdown文檔
在VS Code中打開或新建.md格式的文件即可進行編輯(在VS Code中新建文件時可能需要先保存為.md格式文件),點擊右上角的預覽按鈕可以進行實時預覽。下圖第一個按鈕即為預覽按鈕。
在這里插入圖片描述
配合Markdown使用的擴展
推薦的擴展套裝:
基於Markdown Preview Enhanced擴展預覽窗口(推薦):Markdown Preview Enhanced 和 Prince軟體 + markdownlint + Mermaid Markdown Syntax Highlighting + Maridown pdf(可選) + vscode-pdf(可選)
優點:支持各種CSDN博客特殊語法,如:mermaid繪圖,注腳,注釋,等等。而且預覽窗口不受VS Code軟體深色主題的影響,更加形象的展示所編寫文件的pdf文檔樣式。
基於原生預覽窗口:markdownlint + Markdown+Math + Mermaid Markdown Syntax Highlighting + Markdown Preview Mermaid Support + Maridown PDF + vscode-pdf(可選)
優點:預覽窗口反應快速,無需安裝額外的預覽擴展,主題可以跟隨VS Code軟體的深色主題。
缺點:部分特殊語法無法得到支持。
以下為各個擴展的詳情介紹:
markdownlint:一個好用的 Markdown 格式檢查擴展,它規定了許多規則並實時對文檔進行檢查,防止一些語法錯誤,同時維持文檔風格的統一,使用此工具有助於形成一個良好的寫作習慣和規范。
Markdown Preview Enhanced:一個很好用的完善預覽功能的插件,可以更加形象的展示所編寫文件的pdf文檔樣式。優點是支持LaTeX數學公式和Mermaid圖表等內容的顯示。
安裝後,你會發現工作區的右上角多了一個預覽按鈕,這個按鈕就是Markdown Preview Enhanced插件產生的,如下圖。直接右鍵.md文件的頁面也可以開啟Markdown Preview Enhanced。
在這里插入圖片描述
注意:右鍵Markdown Preview Enhanced預覽頁面也有一些選項,如下圖。Open in Browser是在瀏覽器中打開預覽,HTML是列印成HTML文件,PDF是列印成PDF文件(此選項需額外安裝Prince軟體,VS Code擴展庫中沒有,安裝方法見後文)。
在這里插入圖片描述
安裝Prince軟體:進入Prince官網,點擊下載,選擇對應的版本進行下載並安裝。然後添加環境變數,右鍵我的電腦->屬性->高級系統設置->環境變數->系統變數->Path->編輯,新建一條Prince安裝路徑\engine\bin即可。然後重啟VS Code。
Markdown All in One:集成了各種功能,同時也支持LaTeX數學公式(在擴展設置中啟用基本的數學支持選項可以開啟與關閉該功能),但貌似沒有顯示Mermaid圖表和列印PDF的功能。個人建議,若啟用Markdown+Math擴展,則不必啟用此擴展。
Markdown+Math:使VS Code原生的Markdown預覽窗口支持顯示LaTeX數學公式。可以與Markdown All in One擴展同時使用,同時使用時,LaTeX公式顯示風格以Markdown+Math為標准。
Mermaid Markdown Syntax Highlighting:支持Mermaid圖表代碼高亮,但無法在原生預覽窗口顯示。
Markdown Preview Mermaid Support:支持原生預覽窗口顯示Mermaid圖表。
Maridown PDF:可以簡單的將編寫的.md文件轉換成其他格式的文件,右鍵.md文件的頁面可以進行轉換,如下圖。生成的文件將會直接保存在.md文件的文件夾下。但不支持LaTeX數學公式和Mermaid圖表等內容的顯示。
在這里插入圖片描述
vscode-pdf:若希望在VS Code中直接打開並瀏覽pdf格式文件,可以通過安裝該插件來達到該目的。
Markdown Pad 2
介紹
Markdown是一種可以使用普通文本編輯器編寫的標記語言,通過簡單的標記語法,它可以使普通文本內容具有一定的格式。而Markdown Pad 2 便是編輯Markdown語言的一款編輯器,其功能強大,便捷,速度快,無廣告,而且還可以進行個性化設置。下面介紹一下Windows系統下,該工具的安裝與配置方法。
安裝
進入官網:官網鏈接,然後點擊Download MarkdownPad;或者直接點擊該鏈接,下載鏈接,會立刻開始下載。
運行上一步驟下載到的exe文件,開始安裝,並完成安裝。
注意:Win10若提示HTML渲染組件出錯,錯誤的表現形式為,不能實時預覽Markdown生成的HTML頁面。則需要安裝awesomium_sdk,下載地址:Download awesomium_v1.6.6_sdk_win.exe。
設置中文
Tool —> Options —> Editor —> Language,選擇中文。
Key
在初次打開軟體時單擊Enter Key按鈕,或點擊幫助—>升級到MarkdownPad專業版。輸入如下Email和Key。
Email
[email protected]
1
1
Key
/sQytXJUQl/D8Vb/ikJdhGMMQr0R4B+L3nWU97eaVPTRKfWGDE8/eAgKzpGwrQQoDh+nzX1xoVQ8NAuH+s4UcSeQ==
1
1
個性化設置
菜單欄 —> 工具 —> 選項
Markdown —> GitHub 風格 Markdown (離線)
樣式表 —> Markdownpad-github.css
文件 —> 在導出的PDF文件中包含CSS背景
Markdown與HTML的聯系
Markdown支持HTML的大部分標簽,但反之HTML不支持Markdown語法;即Markdown兼容HTML。例如換行標簽<br>,鍵盤文本<kbd>,預格式文本<pre>,上標<sup>,下標<sub>,等等。更多標簽和用法請參照HTML標簽 。
例子:
鍵盤文本-復制的快捷鍵:<kbd>Ctrl/Command</kbd> + <kbd>C</kbd>
顯示:
Ctrl/Command + C
Markdown中支持HTML的大部分字元實體,如大於號:> ,顯示為>。更多HTML字元實體請參照HTML字元實體 。
編輯技巧
快捷鍵
在編輯頁面可以適當的使用快捷鍵提升效率。以下為CSDN的快捷鍵,其中有些是可以通用於各個編輯器的。
CSDN快捷鍵:
撤銷:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜體:Ctrl/Command + I
標題:Ctrl/Command + Shift + H
無序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
待辦列表:Ctrl/Command + Shift + C
插入代碼:Ctrl/Command + Shift + K
插入鏈接:Ctrl/Command + Shift + L
插入圖片:Ctrl/Command + Shift + G
列表
當使用順序列表時,按回車會自動生成序號,想中斷排序,再按一次回車即可。
在順序列表的編號後面按回車,不會打亂編號的順序。
當使用列表後,縮進中斷時,可以使用Tab進行縮進。
標記失效
在使用Markdown標記語言時,一些標記後需要加空格才會生效,如標題標記:# 。
一些標記的前面需要有回車才會生效,如分隔符:--- 。
一些字體標記,當結束標記前的字元為標點符號時可能會失效。
例如:**標點符號。**是句號。
顯示:**標點符號。**是句號。
解決方案:在結束標記**後加空格即可,其他字體標記同理。
例如:**標點符號。** 是句號。
顯示:標點符號。 是句號。
頁面內跳轉
由於Markdown目前沒有實現頁面內跳轉的方法,故可以使用HTML的方法進行頁面內跳轉,因為Markdown支持HTML。值得一提的是,跳轉到錨點時,可以使用Markdown的鏈接語法進行跳轉。
注意: 示例中錨點的<h1>標簽可以換成任何其他標簽,如<text>標簽等。
純HTML示例:
<!-- 跳轉到錨點 -->
<a href="#1">錨點目標</a>
<!-- 創建錨點 -->
<h1 id="1">錨點</h1>
1
2
3
4
1
2
3
4
HTML創建錨點+Markdown跳轉示例:
跳轉到錨點:[錨點目標](錨點id '標題')
創建錨點(同上):<h1 id="1">錨點</h1>
展示:
HTML語法跳轉:錨點目標
Markdown語法跳轉:錨點目標
錨點
CSDN博客技巧
CSDN目錄
輸入#,並按下Space後,將生成1級標題。
輸入##,並按下space後,將生成2級標題。
以此類推,我們支持6級標題。有助於使用@[TOC](自定義目錄標題)或@[toc](自定義目錄標題)語法後生成一個有縮進的目錄,可實現頁內跳轉。
CSDN快捷鍵
同編輯技巧章節的快捷鍵。此處省略。
自定義列表
CSDN編輯器支持,某些本地編輯器不支持。
例子(最前面要有空行):
Authors
: John
: Luke
1
2
3
1
2
3
顯示:
Authors
John
Luke
注腳
CSDN編輯器支持,某些本地編輯器不支持。
注腳會按照文章的順序自動排序。
例子:
一個具有注腳的文本。[^1]
[^1]: 注腳的解釋
1
2
1
2
顯示:
一個具有注腳的文本。1
注釋
CSDN編輯器支持,某些本地編輯器不支持。
例子(注釋詞前後要有空格):
Markdown兼容 HTML 語言。
*[HTML]: 超文本標記語言
1
2
1
2
顯示:
Markdown兼容 HTML 語言。
LaTeX公式
CSDN編輯器中支持LaTeX數學公式,詳情請見後文的LaTeX公式章節。Typroa軟體支持,設置方法詳見上文的 Markdown工具 - Typroa - 設置 章節。
Mermaid制圖
CSDN編輯器中支持mermaid繪圖,如甘特圖,UML圖等。詳情及具體用法請見參考文檔。
參考文檔:鏈接 。
需要注意的是:有些本地編輯器不支持mermaid繪圖,但如果使用VS Code,則可以通過安裝Markdown Preview Enhanced或Markdown Preview Mermaid Support擴展的方式支持,詳情請見上文的 Markdown工具 - VS Code - 配合Markdown使用的擴展 章節。
下方是一些圖的簡單繪制方法。
甘特圖
```mermaid
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section 現有任務
已完成 :done, des1, 2014-01-06,2014-01-08
進行中 :active, des2, 2014-01-09, 3d
計劃一 : des3, after des2, 5d
計劃二 : des4, after des3, 5d
```
顯示:
Mon 06
Mon 13
Mon 20
已完成
進行中
計劃一
計劃二
現有任務
Adding GANTT diagram functionality to mermaid
UML圖
```mermaid
sequenceDiagram
張三 ->> 李四: 你好!李四, 最近怎麼樣?
李四–>>王五: 你最近怎麼樣,王五?
李四–x 張三: 我很好,謝謝!
李四-x 王五: 我很好,謝謝!
Note right of 王五: 李四想了很長時間, 文字太長了
不適合放在一行.
李四–>>張三: 打量著王五…
張三->>王五: 很好… 王五, 你怎麼樣?
```
顯示:
張三
李四
王五
你好!李四, 最近怎麼樣?
你最近怎麼樣,王五?
我很好,謝謝!
我很好,謝謝!
李四想了很長時間, 文字太長了
不適合放在一行.
打量著王五...
很好... 王五, 你怎麼樣?
張三
李四
王五
FLowchart流程圖
```mermaid
flowchat
st=>start: 開始
e=>end: 結束
op=>operation: 我的操作
cond=>condition: 確認?
st->op->cond
cond(yes)->e
cond(no)->op
```
顯示:
開始
我的操作
確認?
結束
yes
no
導出與導入
導出
用戶可以在CSDN文章中任意編輯。完成了一篇文章的寫作後, 可以在上方工具欄找到 導出按鈕 ,生成一個.md文件或者.html文件進行本地保存。
導入
如果用戶想載入一篇自己寫過的.md文件或者.html文件,在上方工具欄可以選擇導入按鈕進行對應擴展名的文件導入,並繼續創作。
字元實體
前言
與HTML字元實體相同,詳情可參照HTML字元實體 。
空格
不換行空格,全稱是 No-Break Space,它是最常見和我們使用最多的空格,大多數的人可能只接觸了 ,它是按下space鍵產生的空格。在HTML中,如果你用空格鍵產生此空格,空格是不會累加的(只算1個)。要使用html實體表示才可累加,該空格占據寬度受字體影響明顯而強烈。
半形空格,全稱是 En Space,en是字體排印學的計量單位,為em寬度的一半。根據定義,它等同於字體度的一半(如16px字體中就是8px)。名義上是小寫字母n的寬度。此空格傳承空格家族一貫的特性:透明的,此空格有個相當穩健的特性,就是其占據的寬度正好是1/2個中文寬度,而且基本上不受字體影響。
全形空格,全稱是 Em Space,em是字體排印學的計量單位,相當於當前指定的點數。例如,1 em在16px的字體中就是16px。此空格也傳承空格家族一貫的特性:透明的,此空格也有個相當穩健的特性,就是其占據的寬度正好是1個中文寬度,而且基本上不受字體影響。
其他
顯示結果 描述 實體名稱 實體編號
空格
< 小於號 < <
|大於號 |> |>
≦ |小於等於 |≤
≧ |大於等於 |≥
& |和號 |& |&
" |引號 |" |"
』 |撇號 |' (IE不支持) |'
¢ |分 |¢ |¢
£ |鎊 |£ |£
¥ |日圓 |¥ |¥
€ |歐元 |&euro |€
§ |小節 |§ |§
© |版權 |© |©
® |注冊商標 |® |®
™ |商標 |™ |™
× |乘號 |× |×
÷ |除號 |÷ |÷
轉義字元
寫法:\+字元
用途:當某些特殊字元與Markdown語法沖突時,使用轉義字元可以使字元強制顯示,字元實體也可用轉義字元顯示。
示例:
\>
顯示:>
\=\=
顯示:==
\>
顯示:>
等等
注意:使用字元實體也可以達到一樣的效果,但不常用的或記不住的字元實體建議使用轉義字元。
首行縮進
縮進2個漢字大小:
使用2個 (推薦)
使用4個
使用8個
空行
連續輸入2個回車,即可打出一個空行。
輸入HTML表簽<br>,即可打出一個換行。
字體
普通文本:
*強調文本* _強調文本_
**加粗文本** __加粗文本__
==標記文本==
~~刪除文本~~
> 引用文本
1
2
3
4
5
1
2
3
4
5
顯示:
強調文本 強調文本
加粗文本 加粗文本
標記文本
刪除文本
引用文本
注意:強調文本即斜體文本。
組合文本:
加粗加斜:使用***或___
例子:***加粗加斜***
顯示:加粗加斜
上下標
CSDN編輯器
此方法可能不適用某些本地編輯器,本地編輯器可以使用HTML方法或LaTeX公式方法。
上標:^文本^
下標:~文本~
例子:
H~2~O
2^10^
顯示:
H2O
210
HTML方法
此方法比較同用,適用於各種Markdown編輯器,因為Markdown支持HTML。顯示效果與CSDN編輯器相同。
上標:<sup>文本</sup>
下標:<sub>文本</sub>
例子:
H<sub>2</sub>O
2<sup>10</sup>
顯示:
H2O
210
LaTeX公式方法
詳情請見下文的 附錄 LaTeX公式細節 - 上下標 章節。以下為簡單的例子。
例子:
$x^z_{y+1}$
顯示:
x y + 1 z x^z_{y+1}x
y+1
z
引用可嵌套
例子:
>這是引用的內容
>>這是引用的內容
>>>>>>>>>>這是引用的內容
1
2
3
1
2
3
顯示:
這是引用的內容
這是引用的內容
這是引用的內容
目錄
Markdown基本語法並沒有生成目錄的功能,但很多平台或軟體都支持生成目錄,比如:CSDN博客平台、Typroa軟體、等等。使用方法如下,輸入下方命令即可在相應位置插入目錄,該目錄為Markdown文檔內的標題組成的目錄:
CSDN博客
@[TOC](目錄名稱) 或 @[toc](目錄名稱) 。
Typroa
[TOC] 或 [toc] 。
其他
同Typroa。
導出分頁
在Markdown導出為PDF時,若想要設置分頁,在Markdown文件想分頁的位置輸入如下HTML代碼即可,再次導出即可顯示分頁效果。該語句已在Typroa軟體中實驗成功。
<div style="page-break-after: always;"></div>
或
<div STYLE="page-break-after: always;"></div>
1
2
3
1
2
3
鏈接
格式:[鏈接文本](鏈接地址 '鏈接標題')
說明:鏈接文本為顯示的文字,鏈接地址為鏈接的網址,鏈接標題可以不寫,是滑鼠懸停在鏈接處顯示的標題。
例子:
[Link](https://mp.csdn.net)
顯示:
Link
列表
有序列表
示例:
1. 項目1
2. 項目2
3. 項目3
1
2
3
1
2
3
顯示:
項目1
項目2
項目3
無序列表
示例:
- 項目
- 項目
- 項目
1
2
3
1
2
3
顯示:
項目
項目
項目
待辦列表
示例:
- [ ] 計劃任務
- [x] 完成任務
1
2
1
2
顯示:
計劃任務
完成任務
多級列表
每寫下一級有序列表或無須列表時,多縮進1個Tab(推薦)或 4 個空格。
有序多級列表示例:
1. 標題1
1. 標題1.1
1. 標題1.1.1
2. 標題1.1.2
2. 標題1.2
3. 標題1.3
2. 標題2
1
2
3
4
5
6
7
1
2
3
4
5
6
7
顯示:
標題1
標題1.1
標題1.1.1
標題1.1.2
標題1.2
標題1.3
標題2
無序多級列表示例:
- 項目
- 項目
- 項目
1
2
3
1
2
3
顯示:
項目
項目
項目
自定義列表
注意:CSDN編輯器支持,某些本地編輯器不支持。
例子(最前面要有空行):
Authors
: John
: Luke
1
2
3
1
2
3
顯示:
Authors
John
Luke
圖片
Markdown圖片
插入圖片格式:
在這里插入圖片描述
注意: 圖片替換文本是圖片未顯示時替換的文本,圖片標題是滑鼠懸停在圖片上顯示的文本,圖片標題可不寫,圖片標題的引號用單引號和雙引號都可以。圖片地址可以是網路網址(https://xxx),也可以是本地相對路徑(推薦,如./images/pic1.jpg)或絕對路徑。
例子:
![Alt](https://img-blog.csdnimg.cn/20210531154235861.png 'title')
顯示:
Alt
CSDN圖片
CSDN平台針對Markdown的圖片語法做了特殊處理,支持調整圖片的大小和對齊方式,使用方法如下:
帶尺寸的圖片:
![Alt](https://img-blog.csdnimg.cn/20210531154235861.png# =30x30)
顯示:
Alt
居中的圖片:
![Alt](https://img-blog.csdnimg.cn/20210531154235861.png#pic_center)
補充:圖片居左為#pic_left,圖片居右為#pic_right 。
顯示:
Alt
居中並且帶尺寸的圖片:
![Alt](https://img-blog.csdnimg.cn/20210531154235861.png#pic_center =30x30)
顯示:
Alt
為了讓用戶更加便捷,CSDN博客增加了圖片拖拽功能。
HTML圖片
即使不在CSDN平台,Markdown編輯器也可以實現調整圖片大小和對齊方式的功能,因為Markdown支持HTML,使用HTML語言即可,使用方法如下:
居中圖片
代碼:
<div align=[對齊方式]> <!--對齊方式可以為center,left,right-->
<img src="圖片地址" alt="替換文字" width="寬度" height="高度">
</div>
1
2
3
1
2
3
示例1:居中的圖片
<div align=center>
<img src="https://img-blog.csdnimg.cn/2021053115541388.png">
</div>
1
2
3
1
2
3
顯示:
示例2:居中且帶尺寸的圖片
<div align=center>
<img src="https://img-blog.csdnimg.cn/2021053115541388.png" width="50%">
</div>
1
2
3
1
2
3
顯示:
圖片居中標題
無論以何種方式插入圖片,都有在圖片下方輸入圖片標題的需求,使用HTML語法即可為圖片添加居中標題,使用方法如下:
在圖片下方添加如下HTML代碼即可:
<center>圖片標題</center>
1
1
顯示:
圖片標題
表格
如果表格貼近行首,則可以使用簡便方式製作表格
例子:
列1 | 列2
--- | ---
值1 |值2
值3 |值4
1
2
3
4
1
2
3
4
顯示:
列1 列2
值1 值2
值3 值4
若表格前有Tab縮進,則左側的 | 需補全,否則會出現第一列不顯示的狀況。
例子:
| 列1 | 列2
| --- | ---
| 值1 |值2
| 值3 |值4
1
2
3
4
1
2
3
4
顯示:
列1 列2
值1 值2
值3 值4
完整的表格格式。
例子:
| 列1 | 列2 | 列3 |
| :--- | :---: | ---: |
| 文本居左 | 文本居中 | 文本居右 |
1
2
3
1
2
3
顯示:
列1 列2 列3
文本居左 文本居中 文本居右
注意:最左側(第一個) | 右端最好有1或2個空格,否則可能會出現未知錯誤(如缺失字元,對齊失效等)。
分割線
三個或者三個以上的 - 或者 * 都可以,效果是一樣的。
注意分割線前要有空行。
例子:
(空行)
---
----
***
*****
1
2
3
4
5
1
2
3
4
5
顯示:
代碼塊
單行代碼塊
代碼只有一行或在文本中插入時可以使用,也可以叫行中代碼塊,格式為:`代碼` 。
例子:
`print('Hello World!)`
顯示:
print('Hello World!)
多行代碼塊
多行代碼塊可以插入多行代碼,且可以標記編程語言的類型,如python,可以簡寫成py,JavaScript可以簡寫成js。
格式:
```編程語言類型
代碼片段
代碼片段
```
例子:
```py
for i in(1,11,1):
print(『Hello World!』,end=『\n』)
```
顯示:
for i in(1,11,1):
print('Hello World!',end='\n')
1
2
1
2
技巧
代碼塊前面可以使用Tab縮進,顯示的代碼塊前端也會有縮進。
例子:
print('前面有縮進。')
1
1
在CSDN博客設置頁面,可以選擇一款自己喜歡的代碼片高亮樣式。
LaTeX數學公式
介紹
CSDN支持LaTeX公式,但有些本地編輯器可能不支持LaTeX公式,Typroa可以更改設置支持,VS Code可以通過安裝擴展的方式支持,詳情請見上文的 Markdown工具 章節。
LaTeX數學公式的各種細節請參見我的另一篇博客:LaTeX數學公式-詳細教程 。
官方文檔:
傳送門:官方文檔
網址:https://math.meta.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference
中文教程:
傳送門:中文教程
網址:https://www.jianshu.com/p/25f0139637b7
技巧:使用在線LaTeX公式編輯器,來生成LaTeX公式代碼,然後復制到Markdown編輯器中,並在兩邊加上$或$$即可。
在線LaTeX公式編輯器網址:https://private.codecogs.com/latex/eqneditor.php
插入公式
左對齊公式(行中公式):$數學公式$
居中公式(獨立公式):$$數學公式$$
注意:使用$行中公式時,數學公式與$連接處不要有空格,否則公式不會顯示;使用$$居中公式時,數學公式與$$連接處可以有空格。即$ 數學公式 $ 不顯示公式。
注釋:%為單行注釋。
細節:細節請參見我的另一篇博客:LaTeX數學公式-詳細教程 。
注意事項
使用$,即行中公式時,數學公式與$連接處不要有空格,否則公式不會顯示。
使用$$,即居中公式時,數學公式與$$連接處可以有空格。即$ 數學公式 $ 不顯示公式。
使用$$時,上方要空一行。
=不要單獨打一行,否則可能會出錯。
+ - * / = ( ) | , . '等符號直接在$或$$之間輸入即可識別。
② 關於中斷嵌套的問題
關於中斷嵌套:在linux內核里,如果驅動在申請注冊中斷的時候沒有特別的指定,do_irq在做中斷響應的時候,是開啟中斷的,如果在驅動的中斷處理函數正在執行的過程中,出現同一設備的中斷或者不同設備的中斷,這時候新的中斷會被立即處理,還是被pending,等當前中斷處理完成後,再做處理。在2.4和2.6內核里,關於這一塊是否有什麼不同。 一般申請中斷的時候都允許開中斷,即不使用SA_INTERRUPT標志。如果允許共享則加上 SA_SHIRQ,如果可以為內核熵池提供熵值(譬如你寫的驅動是ide之類的驅動),則再加上 SA_SAMPLE_RANDOM標志。這是普通的中斷請求過程。對於這種一般情況,只要發生中斷,就可以搶占內核,即使內核正在執行其他中斷函數。這里有兩點說明:一是因為linux不支持 中斷優先順序,因此任何中斷都可以搶占其他中斷,但是同種類型的中斷(即定義使用同一個 中斷線的中斷)不會發生搶占,他們會在執行本類型中斷的時候依次被調用執行。二是所謂 只要發生中斷,就可以搶占內核這句是有一定限制的,因為當中斷發生的時候系統由中斷門 進入時自動關中斷(對於x86平台就是將eflags寄存器的if位置為0),只有當中斷函數被執行 (handle_IRQ_event)的過程中開中斷之後才能有搶占。 對於同種類型的中斷,由於其使亂豎用同樣的idt表項,通過其狀態標志(IRQ_PENDING和 IRQ_INPROGRESS)可以空毀防止同種類型的中斷函數執行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函數被重入),對於不同的中斷,則可以自由的嵌套。因此,所謂中斷嵌套, 對於不同的中斷是可以自由嵌套的,而對於同種類型的中斷,是不可以嵌套執行的。以下簡單解釋一下如何利斗陪備用狀態標志來防止同種類型中斷的重入:當某種類型的中斷第一次發生時,首先其idt表項的狀態位上被賦予IRQ_PENDING標志,表示有待處理。 然後將中斷處理函數action置為null,然後由於其狀態沒有IRQ_INPROGRESS標志(第一次),故將其狀態置上IRQ_INPROGRESS並去處IRQ_PENDING標志,同時將action賦予相應的中斷處理函數指針(這里是一個重點,linux很巧妙的用法,隨後說明)。這樣,後面就可以順利執行handle_IRQ_event進行中斷處理,當在handle_IRQ_event中開中斷後,如果有同種類型的中斷發生,則再次進入do_IRQ函數,然後其狀態位上加上IRQ_PENDING標志,但是由於前一次中斷處理中加上的IRQ_INPROGRESS沒有被清除,因此這里無法清除IRQ_PENDING標志,因此action還是為null,這樣就無法再次執行handle_IRQ_event函數。從而退出本次中斷處理,返回上一次的中斷處理函數中,即繼續執行handle_IRQ_event函數。當handle_IRQ_event返回時檢查IRQ_PENDING標志,發現存在這個標志,說明handle_IRQ_event執行過程中被中斷過,存在未處理的同類中斷,因此再次循環執行handle_IRQ_event函數。直到不存在IRQ_PENDING標志為止。2.4和2.6的差別,就我來看,主要是在2.6中一進入do_IRQ,多了一個關閉內核搶占的動作,同時在處理中多了一種對IRQ_PER_CPU類型的中斷的處理,其他沒有什麼太大的改變。這類IRQ_PER_CPU的中斷主要用在smp環境下將中斷綁定在某一個指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中斷的時候。 其實簡單的說,中斷可以嵌套,但是同種類型的中斷是不可以嵌套的,因為在IRQ上發生中斷,在中斷響應的過程中,這個IRQ是屏蔽的,也就是這個IRQ的中斷是不能被發現的。 同時在內核的臨界區內,中斷是被禁止的 關於do_IRQ可能會丟失中斷請求:do_IRQ函數是通過在執行完handle_IRQ_event函數之後判斷status是否被設置了IRQ_PENDING標志來判斷是否還有沒有被處理的同一通道的中斷請求。 但是這種方法只能判斷是否有,而不能知道有多少個未處理的統一通道中斷請求。也就是說,假如在第一個中斷請求執行handle_IRQ_event函數的過程中來了同一通道的兩個或更多中斷請求,而這些中斷不會再來,那麼僅僅通過判斷status是否設置了IRQ_PENDING標志不知道到底有多少個未處理的中斷,handle_IRQ_event只會被再執行一次。這算不算是個bug呢? 不算,只要知道有中斷沒有處理就OK了,知道1個和知道N個,本質上都是一樣的。作為外設,應當能夠處理自己中斷未被處理的情況。不可能丟失的,在每一個中斷描述符的結構體內,都有一個鏈表,鏈表中存放著服務常式序關於中斷中使用的幾個重要概念和關系: 一、基本概念 1. 產生的位置 發生的時刻 時序 中斷 CPU外部 隨機 非同步 異常 CPU正在執行的程序 一條指令終止執行後 同步 2.由中斷或異常執行的代碼不是一個進程,而是一個內核控制路徑,代表中斷發生時正在運行的進程的執行 中斷處理程序與正在運行的程序無關 引起異常處理程序的進程正是異常處理程序運行時的當前進程 二、特點 (2)能以嵌套的方式執行,但是同種類型的中斷不可以嵌套 (3)盡可能地限制臨界區,因為在臨界區中,中斷被禁止 2.大部分異常發生在用戶態,缺頁異常是唯一發生於內核態能觸發的異常 缺頁異常意味著進程切換,因此中斷處理程序從不執行可以導致缺頁的操作 3.中斷處理程序運行於內核態 中斷發生於用戶態時,要把進程的用戶空間堆棧切換到進程的系統空間堆棧,剛切換時,內核堆棧是空的 中斷發生於內核態時, 不需要堆棧空間的切換 三、分類 1.中斷的分類:可屏蔽中斷、不可屏蔽中斷 2.異常的分類: 分類 解決異常的方法 舉例 故障 那條指令會被重新執行 缺頁異常處理程序 陷阱 會從下一條指令開始執行 調試程序
③ 內核不停切換
內核態與用戶態是操作系統的兩種運行級別,intel cpu提供Ring0-Ring3三種級別的運行模式。Ring0級別最高,Ring3最低。其中特權級0(Ring0)是留給操作系統代碼,設備驅動程序代碼使用的,它們工作於系統核心態;而特權極3(Ring3)則給普通的用戶程序使用,它們工作在用戶態。運行於處理器核心態的代碼不受任何的限制,可以自由地訪問任何有效地址,進行直接埠訪問。而運行於用戶態的代碼則要受到處理器的諸多檢查,它們只能訪問映射其地址空間的頁表項中規定的在用戶態下可訪問頁面的虛擬地址,且只能對任務狀態段(TSS)中I/O許可點陣圖(I/O Permission Bitmap)中規定的可訪問埠進行直接訪問(此時處理器狀態和控制標志寄存器EFLAGS中的IOPL通常為0,指明當前可以進行直接I/O的最低特權級別是Ring0)。以上的討論只限於保護模式操作系統,象DOS這種模式操作系統則沒有這些概念,其中的所有代碼都可被看作運行在核心態。
當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(或簡稱為內核態)。此時處理器處於特權級最高的(0級) 內核代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。當進程在執沖旁行用戶自己的代碼時,則稱其處於用戶運行態(用戶態)。即此時處理器在特權級最低的(3級)用戶代碼中運行。
在內核態下CPU可執行任何指令,在用戶態下CPU只能執行非特權指令。當CPU處於內核態,可以隨意進入用戶態;而當CPU處於用戶態時,用戶從用戶態切換到內核態只有在系統調用和中斷兩種情況下發生,一般程序一開始都是運行於用戶態,當程序需要使用系統資源時,就必須通過調用軟中斷進入內核態。
Linux使用了Ring3級別運行用戶態,Ring0作為內核態,沒有使用Ring1和Ring2。Ring3狀態不能訪問Ring0的地址空間,包括代碼和數據。Linux進程的4GB地址空間,3G-4G部分大家是共享的,是內核態的地址空間,這里存放在整個內核的代碼和所有的內核模塊,以及內核所維護的數據。用戶運行一個程序,該程序所創建的進程開始是運行在用戶態的,如果要執行文件操作,網路數據發送等操作,必須通過 write,send等系統調用,這些系統調用會調用內核中的代碼來完成操作,這時,必須切換到Ring0,然後進入3GB-4GB中的內核地址空間去執行這些代碼完成操作,完成後,切換回Ring3,回到用戶態。這樣,用戶態的程序就不能隨意操作內核地址空間,具有一定的安全保護作用。
處理器模式從Ring3向Ring0的切換發生在控制權轉移時,有以下兩種情況:訪問調用門的長轉移指令CALL,訪問中斷門或陷阱門的INT指令。具體的轉移細節由於涉及復雜的保護檢查和堆棧切換,不再贅述,請參閱相關資料。現代的操作系統通常使用中斷門來提供系統服務,通過執行一條陷入指令來完成模式切換,在INTEL X86上這條指令是INT,如在森塵WIN9X下是INT30(保護模式回調),在LINUX下是INT80,在WINNT/2000下是INT2E。用戶模式的服務程序(如系統DLL)通過執行一個INTXX來請求系統服務,然後處理器模式將切換到核心態,工作於核心態的相應的系統代碼將服務於此次請求並將結果傳給用戶程序。
一,中斷處理過程
硬體中斷:來自時鍾,外設
可編程中斷:programmed interrupt,執行引起軟體中斷的指散春橡令。
例外中斷:如頁面錯。
都由系統負責處理。當發生一個中斷時,如果CPU正在比該中斷級低的處理機運行級上運行,它就在解碼下條指令之前,接受該中斷,並提高處理機運行級。內核處理中斷的操作順序如下:
1,對於正在進行的進程,保存其當前寄存器上下文,並創建壓入一個新的上下文層。
2,確定中斷源,識別中斷類型。如是時鍾或磁碟的。
3,查找中斷向量。當系統接受一個中斷時,它從機器中得到一個數,系統把這個作為查表的偏移量。這個表通常成為中斷向量(interrupt vector)。中斷向量的內容包括各種中斷源的中斷處理程序的地址,以及中斷處理程序取得參數的方式。
4,內核調用中斷處理程序。
5,中斷處理程序執行那個返回,恢復(彈出)前一上下文層。
二,軟中斷
軟中斷通知進程發生了非同步事件。
系統有個進程表,每個進程在進程表中有有個進程表項,每個進程表項有個軟中斷信號欄位,紀錄發向一個進程的所有未處理的軟中斷信號。
當一個進程即將從核心態返回到用戶態時,或它要進入或離開一個適當的低調度優先順序時,內核要檢查它是否收到了一個軟中斷信號。
內核僅當一個進程從核心態返回到用戶態時才處理軟中斷信號。
三,系統調用
我們在C程序中調用系統調用好像是個一般的函數調用,當實際上調用系統調用會引起用戶態到核心態的狀態變化,這是怎麼做到的呢?
原來,C編譯程序採用一個預定義的函數庫(C之程序庫),其中的函數具有系統調用的名字,從而解決了在用戶程序中請求系統調用的問題。這些庫函數一般都執行一條指令,該指令將進程的運行方式變為核心態,然後,使內核開始為系統調用執行代碼。我們稱這個指令為操作系統陷入(operating system trap)。
系統調用的介面是一個中斷處理程序的特例。
在處理操作系統陷入時,
1,內核根據系統調用號查系統調用入口表,找到相應的內核子程序的地址。
2,內核還要確定該系統調用所要求的參數個數。
3,從用戶地址空間拷貝參數到U區(Unix V)。
4,保存當前上下文,執行系統調用代碼。
核心態:當CPU正在運行內核代碼時(內核代碼是共享的)。
用戶態:當CPU正在運行用戶代碼時。
用戶模式:不可以訪問內核空間(>=0x80000000)
內核模式:可以訪問任何有效虛擬地址,包括內核空間。一個線程可以訪問其他任何線程地址空間。
④ 麻將中斷門什麼意思是條,餅,萬,一樣都不能少,還是必須有其中兩種才能胡牌。缺一種才能贏求詳解
斷門應該是條,餅,萬中至少要缺一門,才能胡,至於糊牌之前是不是必須報聽不同的地方應該不同,河北尺信牌的話不需要必須報聽,類似的玩法如打八張,活八張是條,餅,萬,風(字牌)有一門至少有八張才能胡,死八張是其中必須有一門有八張,不能多也不能少,才能胡,麻將不同的地方的習俗有很大不同,不知道你打的是哪扒缺里的牌,,,具體的情況要根據地方習陵此輪俗才能確定,,
⑤ 進程間切換和線程間切換分別做些什麼工作啊
進程:
在中斷描述符表(IDT)中,除中斷門、陷阱門和調用門外,還有一種「任務們」。任務門中包含有TSS段的選擇符。當CPU因中斷而穿過一個任務門時,就會將任務門中的段選擇符裂游自動裝入TR寄存器,使指向新的TSS,並完成任務切換。CPU可以通過JMP或CALL指令實現任務切換肆早銷,當跳轉或調用的目標段(代碼段)實際上指向GDT表中的一個TSS描述符項時,就會引起一次任務切換.
線程:
1.時間片:時鍾中斷處理常式從PCR中取得當前線程對象睜銀指針並更新線程時間,如果超出了時間片,則將當前線程從放入ready列表中,然後從standby列表中取出最高優先順序的線程,然後保存當前線程上下文數據,並轉到新的線程上下文.
2.主動等待:線程調用等待函數,則將當前線程放到wait列表中,然後從standby列表中取一個線程,切換上下文,當主動等待的事件完成時,線程被調度到ready列表中等待再次被調度運行.
3.搶先:時鍾中斷發現standby列表中有比當前線程更高的線程,則掛起當前線程,切換線程上下文,運行最需要運行的線程.
所以,線程間切換就是"線程掛起自己,讓出CPU"
⑥ C++代碼 有辦法封A變速齒輪么
正常 我機器以前也遇到這方面問題
在系統時間上與WINDOS進行同步連接
變速齒輪的原理是把一個程序在處理上先進行這個軟體上的過濾
下面是其中一段源代碼
// File name : SetClock.cpp
// Function1 : SetClock9x(int)
// Function2 : SetClockNT(int)
// Chu Rui 2001.3.1
#include "stdafx.h"
#include "ntport.h"
#define FREE_INT_NO 5
void Ring0()
{ //在Windows9x下進入ring0後進行的操作
__asm
{
cli
mov al,34h
out 43h,al //寫入8253控制寄存器,設置寫0號定時轎鍵仿器
mov ax,bx
out 40h,al //寫定時值低位
mov al,ah
out 40h,al //寫定時值高位
sti
iretd;
}
}
void SetClockNT(int freq)
{ //NT下的操作
//這里使用了NT Port庫
Outport(0x43,0x34); //寫入8253控制寄存器,設置寫0號定時器
Outport(0x40,freq&0xff); //寫定時值低亮並位
Outport(0x40,(freq>>8)&0xff); //寫定時值高位
}
void SetClock9x(int freq)
{
union Function_Pointer
{
void (*pointer)();
char bytes[sizeof(void *)];
}OldIntAddress,NewIntAddress;
int IDTAddress; //IDT表基地址
int IDTItemAddress; //要修改的中斷門所在地址
char *Pointer; //要修改的中斷門所在地址,指針形式
__asm
{
push eax
sidt [esp-2]
pop eax
mov IDTAddress,eax //得到IDT表基地閉纖址
}
IDTItemAddress=FREE_INT_NO*8+IDTAddress;
Pointer=(char *)IDTItemAddress;
NewIntAddress.pointer=Ring0;
OldIntAddress.bytes[0]=Pointer[0];
OldIntAddress.bytes[1]=Pointer[1];
OldIntAddress.bytes[2]=Pointer[6];
OldIntAddress.bytes[3]=Pointer[7]; //保存舊的中斷門
Pointer[0]=NewIntAddress.bytes[0];
Pointer[1]=NewIntAddress.bytes[1];
Pointer[6]=NewIntAddress.bytes[2];
Pointer[7]=NewIntAddress.bytes[3]; //設置新的中斷門
__asm
{
mov ebx,freq
int FREE_INT_NO //產生中斷,進入ring0
}
Pointer[0]=OldIntAddress.bytes[0];
Pointer[1]=OldIntAddress.bytes[1];
Pointer[6]=OldIntAddress.bytes[2];
Pointer[7]=OldIntAddress.bytes[3]; //恢復舊的中斷門
}
⑦ 系統中斷的中斷處理
中斷處理一般分為中斷響應和中斷處理兩個步驟。中斷響應由硬體實施,中斷處理弊或主要由軟體實施。
(1)中斷響應
對中斷請求的整個處理過程是由硬體和軟體結合起來而形成的一套中斷機構實施的。發生中斷時,CPU暫停執行當前的程序,而轉去處理中斷。這個由硬體對中斷請求作出反應的過程,稱為中斷響應。一般說來,中斷響應順序執行下述三步動作:
◆中止當前程序的執行;
◆保存原程序的斷點信息(主要是程序計數器PC和程序狀態寄存器PS的內容);
◆從中斷控制器取出中斷向量,轉到相應的處理程序。
通常CPU在執行完一條指令後,立即檢查有無中斷請求,如果有,則立即做出響應。
當發生中斷時,系統作出響應,不管它們是來自硬體(如來自時鍾或者外部設備)、程序性中斷(執行指令導致「軟體中斷」—Software Interrupts),或者來自意外事件(如訪問頁面不在內存)。
如果當前CPU的執行優先順序低於中斷的優先順序,那麼它就中止對當前程序下條指令的執行,接受該中斷,並提升處理機的執行級別(一般與中斷優先順序相同),以便在CPU處理當前中斷時,能屏蔽其它同級的或低級的中斷,然後保存斷點現場信息,通過取得的中斷向量轉到相應的中斷處理程序的入口。
(2)中斷處理
CPU從中斷控制器取得中斷向量,然後根據具體的中斷向量從中斷向量表IDT中找到相應的表項,該表項應是一個中斷門。於是,CPU就根據中斷門的設置而到達了該通道的總服務程序的入口。
核心對中斷處理的順序主要由以下動作完成:
◆保存正在運行進程的各寄存器的內容,把它們放入核心棧的新幀面中。
◆確定「中斷源」或核查中斷發生,識別中斷的類型(如時鍾中斷或盤中斷)和中斷的設備號(如哪個磁碟引起的中斷)。系統接到中斷後,就從機器那裡得拍笑到一個中斷號,它是檢索中斷向量表的位移。中斷向量因機器而異,但通常都包括相應中斷處理程序入口地址和中斷處理時處理機的狀態字。
◆核心調用中斷處理程序,對中斷進行處理。
◆中斷處理完成並返回。中斷處理程序執行完以後,核心便執行與機器相關的特定指令序列,恢復中斷時寄存器內容租賀伍和執行核心棧退棧,進程回到用戶態。如果設置了重調度標志,則在本進程返回到用戶態時做進程調度。
⑧ VC++ MFC如何獲取CPU ID及硬碟的序列號
// 「獲得Intel CPU ID」按鈕消息處理函數
void CIntelCPUIDDlg::OnBtnCPUID()
{
unsigned long s1,s2;
unsigned char vendor_id[]="------------";//CPU提供商ID
CString str1,str2,str3;
// 以下為獲得CPU ID的匯編語言指令
_asm // 得到CPU提供梁團缺商信息
{
xor eax,eax // 將eax清0
cpuid /橡辯/ 獲取CPUID的指令
mov dword ptr vendor_id,ebx
mov dword ptr vendor_id[+4],edx
mov dword ptr vendor_id[+8],ecx
}
str1.Format("%s",vendor_id);
_asm // 得到CPU ID的高32位
{
mov eax,01h
xor edx,edx
cpuid
mov s2,eax
}
str2.Format("%08X-",s2);
_asm // 得到CPU ID的低64位
{
mov eax,03h
xor ecx,ecx
xor edx,edx
cpuid
mov s1,edx
mov s2,ecx
}
str3.Format("%08X-%08X\n",s1,s2);
str2=str2+str3;
m_editVendor.SetWindowText(str1);
m_editCPUID.SetWindowText(str2);
}
// GetHDSerial.cpp: implementation of the CGetHDSerial class.
//
//////////////////////////////////////////////////////或睜////////////////
#include "stdafx.h"
#include "GetHDSerial.h"
char m_buffer[256];
WORD m_serial[256];
DWORD m_OldInterruptAddress;
DWORDLONG m_IDTR;
// 等待硬碟空閑
static unsigned int WaitHardDiskIdle()
{
BYTE byTemp;
Waiting:
_asm
{
mov dx, 0x1f7
in al, dx
cmp al, 0x80
jb Endwaiting
jmp Waiting
}
Endwaiting:
_asm
{
mov byTemp, al
}
return byTemp;
}
//中斷服務程序
void _declspec( naked )InterruptProcess(void)
{
int byTemp;
int i;
WORD temp;
//保存寄存器值
_asm
{
push eax
push ebx
push ecx
push edx
push esi
}
WaitHardDiskIdle();//等待硬碟空閑狀態
_asm
{
mov dx, 0x1f6
mov al, 0xa0
out dx, al
}
byTemp = WaitHardDiskIdle(); //若直接在Ring3級執行等待命令,會進入死循環
if ((byTemp&0x50)!=0x50)
{
_asm // 恢復中斷現場並退出中斷服務程序
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
_asm
{
mov dx, 0x1f6 //命令埠1f6,選擇驅動器0
mov al, 0xa0
out dx, al
inc dx
mov al, 0xec
out dx, al //發送讀驅動器參數命令
}
byTemp = WaitHardDiskIdle();
if ((byTemp&0x58)!=0x58)
{
_asm // 恢復中斷現場並退出中斷服務程序
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
//讀取硬碟控制器的全部信息
for (i=0;i<256;i++)
{
_asm
{
mov dx, 0x1f0
in ax, dx
mov temp, ax
}
m_serial[i] = temp;
}
_asm
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGetHDSerial::CGetHDSerial()
{
}
CGetHDSerial::~CGetHDSerial()
{
}
// 讀取硬碟序列號函數
char* CGetHDSerial::GetHDSerial()
{
m_buffer[0]='\n';
// 得到當前操作系統版本
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx( &OSVersionInfo);
if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
{
// Windows 9x/ME下讀取硬碟序列號
WORD m_wWin9xHDSerial[256];
Win9xReadHDSerial(m_wWin9xHDSerial);
strcpy (m_buffer, WORDToChar (m_wWin9xHDSerial, 10, 19));
}
else
{
// Windows NT/2000/XP下讀取硬碟序列號
DWORD m_wWinNTHDSerial[256];
// 判斷是否有SCSI硬碟
if ( ! WinNTReadIDEHDSerial(m_wWinNTHDSerial))
WinNTReadSCSIHDSerial(m_wWinNTHDSerial);
strcpy (m_buffer, DWORDToChar (m_wWinNTHDSerial, 10, 19));
}
return m_buffer;
}
// Windows9X/ME系統下讀取硬碟序列號
void _stdcall CGetHDSerial::Win9xReadHDSerial(WORD * buffer)
{
int i;
for(i=0;i<256;i++)
buffer[i]=0;
_asm
{
push eax
//獲取修改的中斷的中斷描述符(中斷門)地址
sidt m_IDTR
mov eax,dword ptr [m_IDTR+02h]
add eax,3*08h+04h
cli
//保存原先的中斷入口地址
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-04h]
mov dword ptr m_OldInterruptAddress,ecx
pop ecx
//設置修改的中斷入口地址為新的中斷處理程序入口地址
push ebx
lea ebx,InterruptProcess
mov word ptr [eax-04h],bx
shr ebx,10h
mov word ptr [eax+02h],bx
pop ebx
//執行中斷,轉到Ring 0(類似CIH病毒原理)
int 3h
//恢復原先的中斷入口地址
push ecx
mov ecx,dword ptr m_OldInterruptAddress
mov word ptr [eax-04h],cx
shr ecx,10h
mov word ptr [eax+02h],cx
pop ecx
sti
pop eax
}
for(i=0;i<256;i++)
buffer[i]=m_serial[i];
}
// Windows 9x/ME系統下,將字類型(WORD)的硬碟信息轉換為字元類型(char)
char * CGetHDSerial::WORDToChar (WORD diskdata [256], int firstIndex, int lastIndex)
{
static char string [1024];
int index = 0;
int position = 0;
// 按照高位元組在前,低位元組在後的順序將字數組diskdata 中內容存入到字元串string中
for (index = firstIndex; index <= lastIndex; index++)
{
// 存入字中的高位元組
string [position] = (char) (diskdata [index] / 256);
position++;
// 存入字中的低位元組
string [position] = (char) (diskdata [index] % 256);
position++;
}
// 添加字元串結束標志
string [position] = '\0';
// 刪除字元串中空格
for (index = position - 1; index > 0 && ' ' == string [index]; index--)
string [index] = '\0';
return string;
}
// Windows NT/2000/XP系統下,將雙字類型(DWORD)的硬碟信息轉換為字元類型(char)
char* CGetHDSerial::DWORDToChar (DWORD diskdata [256], int firstIndex, int lastIndex)
{
static char string [1024];
int index = 0;
int position = 0;
// 按照高位元組在前,低位元組在後的順序將雙字中的低字存入到字元串string中
for (index = firstIndex; index <= lastIndex; index++)
{
// 存入低字中的高位元組
string [position] = (char) (diskdata [index] / 256);
position++;
// 存入低字中的低位元組
string [position] = (char) (diskdata [index] % 256);
position++;
}
// 添加字元串結束標志
string [position] = '\0';
// 刪除字元串中空格
for (index = position - 1; index > 0 && ' ' == string [index]; index--)
string [index] = '\0';
return string;
}
// Windows NT/2000/XP下讀取IDE硬碟序列號
BOOL CGetHDSerial::WinNTReadIDEHDSerial(DWORD * buffer)
{
BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
BOOL bFlag = FALSE;
int drive = 0;
char driveName [256];
HANDLE hPhysicalDriveIOCTL = 0;
sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT/2000/XP下創建文件需要管理員許可權
hPhysicalDriveIOCTL = CreateFile (driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
GETVERSIONOUTPARAMS VersionParams;
DWORD cbBytesReturned = 0;
// 得到驅動器的IO控制器版本
memset ((void*) &VersionParams, 0, sizeof(VersionParams));
if(DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_VERSION,
NULL, 0, &VersionParams,
sizeof(VersionParams),
&cbBytesReturned, NULL) )
{
if (VersionParams.bIDEDeviceMap > 0)
{
BYTE bIDCmd = 0; // IDE或者ATAPI識別命令
SENDCMDINPARAMS scip;
// 如果驅動器是光碟機,採用命令IDE_ATAPI_IDENTIFY, command,
// 否則採用命令IDE_ATA_IDENTIFY讀取驅動器信息
bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10)?
IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
memset (&scip, 0, sizeof(scip));
memset (IdOutCmd, 0, sizeof(IdOutCmd));
// 獲取驅動器信息
if (WinNTGetIDEHDInfo (hPhysicalDriveIOCTL,
&scip,
(PSENDCMDOUTPARAMS)&IdOutCmd,
(BYTE) bIDCmd,
(BYTE) drive,
&cbBytesReturned))
{
int m = 0;
USHORT *pIdSector = (USHORT *)
((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
for (m = 0; m < 256; m++)
buffer[m] = pIdSector [m];
bFlag = TRUE; // 讀取硬碟信息成功
}
}
}
CloseHandle (hPhysicalDriveIOCTL); // 關閉句柄
}
return bFlag;
}
// WindowsNT/2000/XP系統下讀取SCSI硬碟序列號
BOOL CGetHDSerial::WinNTReadSCSIHDSerial (DWORD * buffer)
{
buffer[0]='\n';
int controller = 0;
HANDLE hScsiDriveIOCTL = 0;
char driveName [256];
sprintf (driveName, "\\\\.\\Scsi%d:", controller);
// Windows NT/2000/XP下任何許可權都可以進行
hScsiDriveIOCTL = CreateFile (driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
{
int drive = 0;
DWORD mmy;
for (drive = 0; drive < 2; drive++)
{
char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
SENDCMDINPARAMS *pin =
(SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
// 准備參數
memset (buffer, 0, sizeof (buffer));
p -> HeaderLength = sizeof (SRB_IO_CONTROL);
p -> Timeout = 10000;
p -> Length = SENDIDLENGTH;
p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
strncpy ((char *) p -> Signature, "SCSIDISK", 8);
pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
pin -> bDriveNumber = drive;
// 得到SCSI硬碟信息
if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,
buffer,
sizeof (SRB_IO_CONTROL) +
sizeof (SENDCMDINPARAMS) - 1,
buffer,
sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
&mmy, NULL))
{
SENDCMDOUTPARAMS *pOut =
(SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
if (pId -> sModelNumber [0])
{
int n = 0;
USHORT *pIdSector = (USHORT *) pId;
for (n = 0; n < 256; n++)
buffer[n] =pIdSector [n];
return TRUE; // 讀取成功
}
}
}
CloseHandle (hScsiDriveIOCTL); // 關閉句柄
}
return FALSE; // 讀取失敗
}
// Windows NT/2000/XP下讀取IDE設備信息
BOOL CGetHDSerial::WinNTGetIDEHDInfo (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
PDWORD lpcbBytesReturned)
{
// 為讀取設備信息准備參數
pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
pSCIP -> irDriveRegs.bFeaturesReg = 0;
pSCIP -> irDriveRegs.bSectorCountReg = 1;
pSCIP -> irDriveRegs.bSectorNumberReg = 1;
pSCIP -> irDriveRegs.bCylLowReg = 0;
pSCIP -> irDriveRegs.bCylHighReg = 0;
// 計算驅動器位置
pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
// 設置讀取命令
pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
pSCIP -> bDriveNumber = bDriveNum;
pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
// 讀取驅動器信息
return ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_DRIVE_INFO,
(LPVOID) pSCIP,
sizeof(SENDCMDINPARAMS) - 1,
(LPVOID) pSCOP,
sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
lpcbBytesReturned, NULL) );
}
⑨ 如何關閉linux smp中斷
在多 CPU 的環境中,還有一個中斷平衡的問題,比如,網卡中斷會教給哪個 CPU 處理,這個參數控制哪些 CPU 可以綁定 IRQ 中斷。其中的 {number} 是對應設備的中斷編號,可以用下面的命令找出:
cat /proc/interrupt
比如,一般 eth0 的 IRQ 編號是 16,所以控制 eth0 中斷綁定的 /proc 文件名是 /proc/irq/16/smp_affinity。上面這個命令還可以看到某些中斷對應的CPU處理的次數,預設的時候肯定是不平衡的。
設置其值的方法很簡單,smp_affinity 自身是一個位掩碼(bitmask),特定的位對應特定的 CPU,這樣,01 就意味著只有第一個 CPU 可以處理對應的中斷,而 0f(0x1111)意味著四個 CPU 都會參與中斷處理。
幾乎所有外設都有這個參數設置,可以關注一下。
這個數值的推薦設置,其實在很大程度上,讓專門的CPU處理專門的中斷是效率最高的,比如,給磁碟IO一個CPU,給網卡一個CPU,這樣是比較合理的。
現在的伺服器一般都是多核了,但是中斷很多時候都是只用一個核,如果有些中斷要求比較高,可以把它獨立分配給一個cpu使用。
⑩ windows 系統調用 是中斷門 還是陷阱門
windows
系統調用是陷阱門,中斷門用於外設,也就是CPU外部歲攜,屬於非同步中斷。異常包括故障、陷阱、中止。系統調用使用乎旅伏陷阱門並且區別於CPU內部常用異常的特點在於DPL=3。一般或者說多數DPL=0。
再看看別人怎鎮正么說的。