2020/6/10 JavaScript高級程序設計 BOM

BOM(瀏覽器對象模型):提供用於訪問瀏覽器的對象。

8.1 window對象

 window是BOM的核心對象,表示瀏覽器的一個實例。

  • JavaScript訪問瀏覽器窗口的接口
  • ECMAScript規定的Global對象

8.1.1 全局作用域

全局變量會成為window的屬性,但是定義全局變量和直接在window對象上定義屬性是有差別的——全局變量不能通過delete刪除,但window對象上定義的可以

這是因為使用var添加的window屬性[[Configurable]]被設置為false(不可刪除)。

訪問未聲明的變量會發生錯誤,但通過查詢window對象,可以知道某個可能未聲明的變量是否存在。

//這裡會拋出錯誤,因為oldValue未定義
var newValue = oldValue;

//這裏不會拋出錯誤,因為這是一次屬性查詢
var newValue = window.oldValue;  //newValue的值是undefined

8.1.2 窗口關係及框架

如果頁面中包含框架,則每個框架都擁有自己的window對象,並保存在frames集合中。在frames集合中可以通過數值索引/框架名稱來訪問相應的window對象。每個window對象都有一個name屬性,其中包含框架的名稱。

PS1:對於最高層窗口來說:除非最高層窗口是通過window.open()打開的,否則其window對象的name屬性不會包含任何值。

與框架有關的window對象屬性(同時也是對象):

  • top:始終指向最高(最外)層的框架,也就是瀏覽器窗口。使用它可以正確地在一個框架中訪問另一個框架。因為對任意一個框架中的代碼來說,window對象指向的都是那個框架的特定實例,而非最高層框架。
  • parent:始終指向當前框架的直接上層框架。在沒有框架的情況下,parent等於top。
  • self:始終指向window。引入self的目的僅僅是為了和top和parent對象對應,因此他不包含其他值。

8.1.3 窗口位置

用來確定window對象位置的屬性:screenLeft, screenTop / screenX, screenY,分別表示窗口相對於屏幕左邊和上邊的位置。

兩組方法分別支持的瀏覽器:

screenLeft, screenTop IE、Safari、Opera、Chrome
screenX, screenY Firefox、Safari、Chrome

跨瀏覽器取得窗口位置的代碼

var leftPos = (typeof window.screenLeft == "number") ?
                        window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ?
                        window.screenTop : window.screenY;

缺點:

  • screenTop表示的是由從屏幕上邊到window對象表示的頁面可見區域的距離(即頁面可見區域上方瀏覽器工具欄的像素高度)。
  • screenY表示整個瀏覽器窗口相對於屏幕的坐標值(0)。

將窗口精確移動到一個新位置的方法:

  • moveTo():接收最新位置的x,y坐標值。
  • moveBy():接收在水平和垂直方向上移動的像素數。

PS:這兩個方法很可能會被瀏覽器禁用(Opera和IE7+),且不適合框架,只能對最外層window對象使用。

8.1.4 窗口大小

  IE9+、Safari、Firefox Opera Chrome
innerWidth、innerHeight 視圖區大小 該容器中頁面視圖區的大小(減去邊框寬度) 視口大小
outerWidth、outerHeight 瀏覽器窗口本身的尺寸 頁面視圖容器的大小(單個標籤頁對應瀏覽器窗口的大小) 視口大小

document.documentElement.clientWidth / document.documentElement.clientHeight:保存了頁面視口的信息。

resizeTo()和resizeBy():調整瀏覽器窗口的大小。(分別接收新寬度高度和新窗口與原窗口的寬度和高度之差,同樣可能被瀏覽器禁用)

8.1.5 導航和打開窗口

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

第五屆中國國際新能源汽車論壇2015

第五屆中國國際新能源汽車論壇2015強勢回歸,5月18、19日重聚上海

2014年5月18-19日∣中國•上海

新能源汽車“智”造時代

為了全面促進我國新能源汽車產業的快速發展,給全球新能源汽車產業的參與者提供一個溝通交流的平臺,在連續四屆精彩紛呈的新能源汽車論壇的基礎上,由中國產業海外發展和規劃協會、德國電動車協會、上海交大密西根學院主辦,希邁商務諮詢承辦,並得到了亞太電動車協會的傾情指導的“第五屆中國國際新能源汽車論壇2015”將於2015年5月18日至19日在上海隆重召開。屆時將有三百位行業領導出席本次論壇。

互聯網智慧時代強勢來襲,且正悄然改變著汽車這個傳統的行業。汽車互聯網時代的到來也促進著新能源汽車、汽車租賃等新形態汽車業務有效開展。汽車智慧化、新能源、輕量化成為汽車發展的新趨勢。

在過去的四屆新能源汽車論壇上,主辦方成功的邀請了包括國家發改委能源研究所、世界電動車協會、亞太電動車協會、世界氫能協會、世界分散式能源聯盟、中國工程院、美國工程師學會、國家863重大項目組、北京公共交通集團、上海交通大學、清華大學、國家電網、中國南方電網、普天新能源等在內的政府單位與研究機構,以及包括寶馬、賓士、奇瑞捷豹路虎、大眾、奇瑞、奧迪、比亞迪、上汽、北汽、東風、本田、豐田、現代、吉利、宇通客車等在內的知名整車商,共同參與和討論,對新能源汽車行業政策趨勢、技術路線、技術難點、基礎設施建設、商業模式等進行了積極的探討,取得了豐碩的成果,獲得了業內外人士的一致好評。

在嶄新的2015年,組委會為感謝業內外人士對系列論壇長期以來的關注和支援,將傾情奉上第五屆中國國際新能源汽車論壇2015,本次論壇將以新能源汽車“智”造時代為主題。現誠摯邀請您參加本次會議共創輝煌。屆時將邀請全球範圍內的整車製造商、電網公司、電力公司、電池廠商、零部件供應商、核心技術提供商和政府官員近三百位行業嘉賓一起,就新能源汽車產業面臨的機遇、挑戰和對策進行為期兩天的富有建設性和戰略性的討論。

往屆會議精彩回顧

第一屆中國國際新能源汽車論壇 第二屆中國國際新能源汽車論壇
第三屆中國國際新能源汽車論壇 第四屆中國國際新能源汽車論壇

部分往屆知名發言人:

會議亮點

  • 參會嘉賓:
    270+高度滿意的企業決策者,90+業內知名企業,20+國家和地區
  • 參會嘉賓分析:
    17%+來自各國政府部門及權威機構,25%+來自知名整車商
  • 演講嘉賓:
    30+世界新能源汽車行業知名發言嘉賓
  • 交流機會:
    16+小時的交流機會:圓桌討論、VIP午宴和開放式問答
  • 會議形式:
    2天高品質的乾貨分享,整車廠商親臨電池企業對接洽談會

會議結構

  上午 下午
大會第一天

“智”造時代政策預測、製造趨勢及試點城市推廣情況

工信部、科技部、交通部、發改委及地方政府的政策支持
汽車智慧化、新能源、輕量化發展趨勢
國內外整車商新能源新動向
試點城市推廣情況介紹及遇到問題解決措施

新能源汽車動力總成電氣化及商業模式

新能源汽車開發特點及供應配套要求
動力總成電氣化
無人駕駛及無線充電

大會第二天

電池及儲能的研發、製造趨勢

動力電池未來商業模式、技術路線探索
燃料電池及材料研發
動力電池最新技術工藝及典型生產設備選型

微型電動車市場准入

政策准入前景
市場格局變化
電池技術路線選擇

整車廠商-電池企業

對接洽談會

第五屆中國國際新能源汽車論壇2015特色

新能源汽車“智”造時代,第五屆中國國際新能源汽車論壇2015將會邀請政府主管機構、整車商及行業各個領域的領先者,對行業現有的發展訴求及發展願景規劃做出積極的探討。

想瞭解詳細內容,請登陸官方網站:
連絡人:Hill ZENG(曾先生)
電話:+86-21-6045 1760
傳真:+86-21-6047 5887
郵箱:

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

2014年歐洲電動汽車銷量榜出爐 日產leaf市占率26%拔頭籌

據統計,2014年歐洲電動汽車總銷量達5.6萬輛,其中日產聆風(Leaf)的銷量佔據了主導地位,達14658輛,市場佔有率為26%。聆風目前與Juke在英國同一條生產線生產,因此價格有所降低,供應量也更大。2014年聆風電動汽車僅在英國就售出4051輛,比2013年的1812輛多出一倍以上。這款車型佔據了55%的英國純電動汽車市場。   另外,雷諾Zoe在歐洲的銷量為11227輛,排在電動汽車市場的第二位,市場佔有率為20%。特斯拉Model S電動汽車以8734輛的成績排名第三,考慮到其與奧迪A6相當的高昂售價,這一表現算得上十分出色。而BMWi3售出5804輛排在第四位,市場佔有率10%。但是i3在2014年年末剛剛上市而且受生產難度限制產量有限,也算是在電動車市場上為德國企業的表現扳回一成。   而電動車銷量榜的第5和第6位分別為大眾汽車的兩款車型。其中e-Up!電動車以5363輛的銷量幾乎比肩BMWi3。可能受限於34900歐元的售價和較晚的發售時間,其全新的電動版高爾夫(e-Golf)只售出3328輛。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

與特斯拉比拼!BMW 及福斯將在美國東西岸設 100 座快速充電站

  為了拉抬自家電動車買氣,BMW、福斯(Volkswagen)宣布與美國充電設施營運商 ChargePoint 合作,將在美國東岸與西岸設置共 100 座快速充電站。除了要藉此建立更完善的充電站網絡外,更希望能讓消費者不被充電便利性受限,而提高購買電動車的意願。   ChargePoint 是目前全美最大的充電設施營運商,在全國一共設置超過 2 萬座充電站,BMW、福斯與其合作,計畫在 2015 年底前,於美國東岸與西岸設置 100 座快速充電站,相當於平均每 50 英里(約 80.5 公里)就有一座快速充電站。   每座充電站配有 2 個輸出功率分別為 50 kW DC 或 24 kW DC 的 2 款高速充電樁,駕駛只要花 20 至 30 分鐘,就能讓電動車充滿 80% 的電量,相較於需花費好幾個小時充電的 ChargePoint 其他充電站,明顯快上許多。  
 

  (Source:)   據紐約時報報導,有別於特斯拉(Telsa)在全美設置的 358 座免費超級充電站(Supercharger),只能提供給自家車款使用,BMW 與福斯設置的充電站,則是與大多數電動車都相容,不過,使用這些充電站的駕駛就沒像特斯拉車主那麼好康了,得自掏腰包付「充電費」。   根據統計,2014 年美國電動車銷量約為 12 萬輛,較 2013 年成長 20%,但2014 年全美各類車種總銷量一共為 1,650 萬輛,電動車占比仍少得可憐。   或許是意識到快速充電樁數量稀少是影響電動車銷售量的一大因素,近來不少電動車製造商設法填補充電樁不足的缺口,希望能讓消費者不被充電便利性受限,好替電動車銷量帶來生機。   (首圖來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

動態追蹤技術之SystemTap

SystemTap

從春哥(章亦春)那看到的關於SystemTap的介紹,讓我對動態追蹤這個功能頗為感興趣,覺得這是一個非常有用的功能。

SystemTap對內核及用戶態程序提供了動態追蹤功能,用戶可以自定探測事件來跟蹤程序的運行情況,如函數的調用路徑、CPU佔用和磁盤IO等一系列可以探測的情況。有了systemtap,可以在程序不修改代碼,甚至不用重啟就能分析出程序的運行情況。

配合火焰圖的可視化,對程序的性能分析極其有利。(放一個FlameGraph的官方圖片)

原理

SystemTap 基本思想是命名事件,併為它們提供處理程序。每當發生指定的事件時,內核都會將處理程序視為子例程運行,然後繼續運行。有一系列的事件,例如進入或退出函數,計時器到期或整個SystemTap會話的開始和停止。處理程序是一系列腳本語言語句,用於指定事件發生時要完成的工作。這項工作通常包含從事件上下文中提取數據,將其存儲到內部變量或打印結果。

SystemTap 的工作原理是將腳本翻譯成C語言,執行C編譯器創建一個內核模塊。當模塊被加載后,通過掛載到內核來激活所有的探測事件。然後,當事件發生再任何處理器上時,編譯后的處理程序就運行,最終,SystemTap會話停止,Hook取消,內核模塊被移除,整個過程由命令行程序stap驅動。

原理圖如下:

安裝

需要內核級別的支持,依賴了三個rpm下載鏈接,

  1. kernel-debuginfo-common
  2. kernel-debuginfo
  3. kernel-devel

這三個包的版本必須匹配當前內核的版本,比如我自己的內核版本是 3.10.0-327, 那麼以上三個包版本都必須保持一致。

安裝 SystemTap:

$ yum install systemtap

測試是否成功安裝:

$ stap -ve ‘probe begin{printf(“Hello, World\n”); exit();}’

正常的話會輸出 Hello, World,但是不出意外會出現版本不一致的情況:

ERROR: module version mismatch (#1 SMP Fri Nov 20 11:12:42 CST 2015 vs #1 SMP Thu Nov 19 22:10:57 UTC 2015), release 3.10.0-327.el7.x86_64

出現這個的情況是版本相同但是打包事件不相同的情況,修改這個時間和uname -a 中的時間保持一致。

$ rpm -ql kernel-devel | xargs grep UTS_VERSION 2>/dev/null

/usr/src/kernels/3.10.0-327.el7.x86_64/include/generated/compile.h:#define UTS_VERSION "#1 SMP Fri Nov 20 11:12:42 CST 2015"

再次運行那個hello測試,出現緩存的錯誤,刪除緩存文件

  1. /root/.systemtap/cache/34/stap_34443d4ad1fe1d37c0352b7b8c691aee_975.c
  2. /root/.systemtap/cache/34/stap_34443d4ad1fe1d37c0352b7b8c691aee_975.ko

追蹤

最簡單的探測類型就是跟蹤事件。Systemtap支持許多內置事件,所有的事件家族見 tapset

可以探測的的常用事件:

  • begin, systemtap 會話開始
  • end, systemtap 會話結束
  • kernel.function(“sys_xxx”), 系統調用xx的入口
  • kernel.function(“sys_xxx”).return, 系統調用xx的返回
  • timer.ms(300), 每300毫秒的定時器
  • timer.profile, 每個CPU上周期觸發的定時器
  • process(“a.out”).function(“foo*”), a.out 中函數名前綴為foo的函數信息
  • process(“a.out”).statement(“*@main.c:200”), a.out中文件main.c 200行處的狀態

常用的可打印值(具體見 tapset):

  • tid(), 當前線程id
  • pid(), 當前進程id
  • uid(), 當前用戶id
  • execname(), 當前進程名稱
  • cpu(), 當前cpu編號
  • gettimeofday_s(), 秒時間戳
  • get_cycles(), 硬件周期計數器快照
  • pp(), 探測點事件名稱
  • ppfunc(), 探測點觸發的函數名稱
  • $$var, 上下文中存在 $var,可以使用該變量
  • print_backtrace(), 打印內核棧
  • print_ubacktrace(), 打印用戶空間棧

SystemTap 腳本

stap 腳本簡單,語法類似C;

  • 註釋
# fuck
// fuck
/* fuck */
  • 函數
function foo() {
    // exit(); // 退出 systemtap 會話
}
  • 基本的 if/else/while/for 控制結構
function if_expr() {
    i = 0
    if (i == 1)
        printf("[if] i = %d\n", i);
    else
        printf("[else] i = %d\n", i);
}

function while_expr() {
    i = 0;
    while (i != 2)
        printf("[while] i = %d\n", i++);
}

function for_expr() {
    for (i = 0; i < 2; i++)
        printf("[for] i = %d\n", i);
}

  • 字符串比較,拼接,轉換
function str() {
    uid = uid();
    s_uid = sprint(uid);
    f_uid = "fuck" . s_uid
    printf("uid: %d-%s-%s\n", uid, s_uid, f_uid); // uid: 0-0-fuck0

    // exit();
}
  • 元組
global t; // 聲明元組
global tpl[400]; // 聲明一個400容量的元組

t["fuck"]++;  // t["fuck"] 初始值默認為0, ++ 變成 1
t["fuck"] = 4396; // 賦值為4396

tpl["fuck", pid()]++; // 兩個元素
tpl["shit", tid()]++;
  • 聚集統計
// 包含4個維度 @count @avg @min @max
global t;

t["fuck", tid()] <<< 1
t["fuck", pid()] <<< 1
t[execname(), tid()] <<< 1
t["fuck", 5487] <<< 2
t["fuck", 5487] <<< 3
t["fuck", 5487] <<< 1

具體結構如下:
t["fuck",5487] @count=3 @min=1 @max=3 @sum=6 @avg=2
t["fuck",26060] @count=2 @min=1 @max=1 @sum=2 @avg=1
t["stapio",26060] @count=1 @min=1 @max=1 @sum=1 @avg=1


// 遍歷(升序), 限制5次循環
foreach([key, value] in t+ limit 5)
    printf("%s: %d\n", key, value)

// 結果
stapio: 2571
fuck: 2571
fuck: 5487

應用

stap 常用命令

Usage: stap [options] FILE                    Run script in file.
   or: stap [options] -e SCRIPT               Run given script.
   or: stap [options] -l PROBE                List matching probes.
   or: stap [options] -L PROBE                List matching probes and local variables.
[options]
   -T TIME    terminate the script after TIME seconds

除了直接執行腳本文件外,另外一個比較有用的功能 -L -l 現象,列出可探測點及局部變量

  • 列出程序中的可探測點
// 截取部分~
[root@localhost stp]# stap -l 'process("/tmp/limlog/build/tests/LogTest").function("*")'
process("/tmp/limlog/build/tests/LogTest").function("write@/tmp/limlog/limlog/Log.cpp:107")
process("/tmp/limlog/build/tests/LogTest").function("~LimLog@/tmp/limlog/limlog/Log.cpp:213")
process("/tmp/limlog/build/tests/LogTest").function("~LogLine@/tmp/limlog/limlog/Log.cpp:341")
process("/tmp/limlog/build/tests/LogTest").function("~LogSink@/tmp/limlog/limlog/Log.cpp:59")
process("/tmp/limlog/build/tests/LogTest").function("~_Impl@/usr/include/c++/4.8.2/thread:107")
process("/tmp/limlog/build/tests/LogTest").function("~_Impl_base@/usr/include/c++/4.8.2/thread:97")
  • 列出程序中的可探測點及局部變量(前綴為$)
[root@localhost stp]# stap -L 'process("/tmp/limlog/build/tests/LogTest").function("*")'
process("/tmp/limlog/build/tests/LogTest").function("id@/usr/include/c++/4.8.2/thread:73") $this:class id* const
process("/tmp/limlog/build/tests/LogTest").function("incConsumable@/tmp/limlog/limlog/Log.cpp:313") $this:class LimLog* const $n:uint32_t
process("/tmp/limlog/build/tests/LogTest").function("incConsumablePos@/tmp/limlog/limlog/Log.cpp:135") $this:class BlockingBuffer* const $n:uint32_t
process("/tmp/limlog/build/tests/LogTest").function("incConsumablePos@/tmp/limlog/limlog/Log.cpp:460") $n:uint32_t
process("/tmp/limlog/build/tests/LogTest").function("insert@/usr/include/c++/4.8.2/bits/basic_string.h:1319") $__c:char $__n:size_type $__pos:size_type $this:class basic_string<char, std::char_traits<char>, std::allocator<char> >* const

有這個功能,我們就可以看到函數所在源文件中的位置及可以根據的局部變量。

systemtap 腳本

探針事件的關鍵字是 probe, 由 probe 引出需要跟蹤的事件

// 腳本執行后显示 === begin ===
probe begin {
    printf("=== begin ===\n");
}

根據上述的可跟蹤的事件

  • begin/end, 分別是systemtap會話的起始和結尾
[root@localhost stp]# cat foo.stp
#!/usr/bin/env stap

probe begin {
    printf("=== begin ===\n");
}

probe end {
    printf("=== end ===\n");
}

// 執行腳本
[root@localhost stp]# stap foo.stp -T 1
=== begin ===
=== end ===
  • kernel.function(“sys_xxx”), 系統調用
// 調用open系統調用
[root@localhost stp]# cat foo.stp
#!/usr/bin/env stap

probe kernel.function("sys_open").call {
    printf("%s call %s\n", execname(), ppfunc());
}

// open系統調用返回
probe kernel.function("sys_open").call {
    printf("%s call %s over\n", execname(), ppfunc());
}

[root@localhost stp]# stap foo.stp -T 1
sh call SyS_open
sh call SyS_open over
sh call SyS_open
sh call SyS_open over
sh call SyS_open
sh call SyS_open over
  • 定時器調用
[root@localhost stp]# cat foo.stp
#!/usr/bin/env stap

// 定時調用函數
probe timer.ms(500) {
    printf("now: %d\n", gettimeofday_s());
}

[root@localhost stp]# stap foo.stp -T 3
now: 1593141081
now: 1593141081
now: 1593141082
now: 1593141082
now: 1593141083
  • 定時cpu採樣
// 取自春哥的sample-bt示例代碼,定時調用棧取樣
global bts;

probe timer.profile {
    if (pid() == 5291)
        bts[backtrace(), ubacktrace()] <<< 1
}

probe timer.s(10) {
    foreach([k, u] in bts-) {
        print_stack(k);
        print_ustack(u);
        printf("\\t%d\\n", @count(bts[k, u]));
    }
    exit();
}

// 結果為16進制地址,截取一部分數據,這部分數據需要進一步加工統計
[root@localhost stp]# stap foo.stp
 0xffffffff810d6244 : 0xffffffff810d6244
 0xffffffff810475fa : 0xffffffff810475fa
\t1\n 0xffffffffa0139f0d : 0xffffffffa0139f0d [xfs]
  • 指定程序中的函數事件(需要運行程序)
// 打印程序 LogTest 所有執行的函數
[root@localhost stp]# cat foo.stp
probe process("/tmp/limlog/build/tests/LogTest").function("*") {
    printf("function: %s\n", ppfunc());
}

// 庫函數也加載進來了
[root@localhost stp]# stap foo.stp
function: offsetOfPos
function: __distance<char*>
function: operator+<long int, std::ratio<1l, 1000000000l>, long int, std::ratio<1l, 1000000l> >
function: operator<<
  • 指定程序指定文件中的可追蹤事件
//打印 LogTest 程序屬於 Log.cpp 中的函數信息
[root@localhost stp]# cat foo.stp
probe process("/tmp/limlog/build/tests/LogTest").statement("*@Log.cpp") {
    printf("function: %s\n", ppfunc());
}

// 過濾了庫函數,只留下Log.cpp中的函數執行
[root@localhost stp]# stap foo.stp
function: singleton
function: produce
function: produce
function: produce
function: produce
function: used
function: used
function: consumable
function: operator<<
function: ~LogLine
  • 上下文變量
// 獲取上下文變量
[root@localhost stp]# stap -L 'process("/tmp/limlog/build/tests/LogTest").statement("*@Log.cpp")'
process("/tmp/limlog/build/tests/LogTest").statement("LimLog@/tmp/limlog/limlog/Log.cpp:185") $this:class LimLog* const
process("/tmp/limlog/build/tests/LogTest").statement("LogLine@/tmp/limlog/limlog/Log.cpp:336") $this:class LogLine* const $level:enum LogLevel $loc:struct LogLoc const&
process("/tmp/limlog/build/tests/LogTest").statement("append@/tmp/limlog/limlog/Log.cpp:346") $this:class LogLine* const $data:char const* $n:size_t
process("/tmp/limlog/build/tests/LogTest").statement("consumable@/tmp/limlog/limlog/Log.cpp:140") $this:class BlockingBuffer const* const
process("/tmp/limlog/build/tests/LogTest").statement("consume@/tmp/limlog/limlog/Log.cpp:146") $this:class BlockingBuffer* const $to:char* $n:uint32_t

// 這裏我們追蹤 consume 函數中的兩個參數
[root@localhost stp]# cat foo.stp
probe process("/tmp/limlog/build/tests/LogTest").function("consume") {
    printf("func = %s, $var(n) = %d, $var(to) = %p\n", ppfunc(), $n, $to);
}

[root@localhost stp]# stap foo.stp
func = consume, $var(n) = 406, $var(to) = 0x7f902a94d010
func = consume, $var(n) = 203, $var(to) = 0x7f902a94d1a6
func = consume, $var(n) = 790, $var(to) = 0x7f902a94d010
func = consume, $var(n) = 3319, $var(to) = 0x7f902a94d326
func = consume, $var(n) = 4235, $var(to) = 0x7f902a94d010
func = consume, $var(n) = 4235, $var(to) = 0x7f902a94d010
func = consume, $var(n) = 2326, $var(to) = 0x7f902a94d010
func = consume, $var(n) = 8470, $var(to) = 0x7f902a94d010

示例分析

在探測點被執行時打印這種簡單的用法外,還能進一步做一些其它的事情。

  1. 統計某一時間段內運行次數top k的函數
[root@localhost stp]# cat foo.stp
#!/usr/bin/env stap

global top_funcs;

probe begin {
    printf("=== begin ===\n");
}

probe process("/tmp/limlog/build/tests/LogTest").statement("*@Log.cpp") {
    top_funcs[ppfunc()]++;
}

probe end {
    foreach(func in top_funcs- limit 10)
        printf("%s: %d\n", func, top_funcs[func]);

    printf("=== end ===\n");
}

// LogTest 在3秒內執行最多的10個函數及次數
[root@localhost stp]# stap foo.stp -T 3
=== begin ===
produce: 1152
append: 720
singleton: 646
operator<<: 608
produceLog: 576
used: 576
consumable: 359
incConsumablePos: 64
getLogLevel: 32
LogLine: 32
=== end ===
  1. 統計系統調用某一時間段內被調用最頻繁的k個程序及次數
[root@localhost stp]# cat foo.stp
#!/usr/bin/env stap

global top_exec;

probe begin {
    printf("=== begin ===\n");
}

probe kernel.function("sys_write") {
    top_exec[execname()]++;
}

probe end {
    foreach(exec in top_exec- limit 10)
        printf("%s: %d\n", exec, top_exec[exec]);

    printf("=== end ===\n");
}

[root@localhost stp]# stap foo.stp -T 3
=== begin ===
qemu-kvm: 2948
sync: 2174
virsh: 673
libvirtd: 305
route: 28
grep: 21
ps: 21
ssh: 16
python: 16
nginx: 16
=== end ===
  1. 打印函數調用層次(用戶程序)

調用層次需要藉助 thread_indent 來打印合適的縮進,另外需要設置函數入口(call)和返回(return)的探測點。函數命名不足以使用function通配符來匹配,而 statement 雖然可以匹配我們想要的結果(過濾第三方函數),但是不支持 call 和return。雖然有一個比較傻但是的確可行的方式是,在腳本裏面手動寫入這些函數。

// 先取出需要關注的函數名稱
stap -L 'process("/tmp/limlog/build/tests/LogTest").statement("*@*.cpp")' |  sed 's/.*statement(\"\(.*\)@.*\".*/\1/g'  | sort -u

腳本如下:

#!/usr/bin/env stap

global f;

function init() {
    f["append"] = 1;
    f["benchmark"] = 1;
    f["consumable"] = 1;
    f["consume"] = 1;
    f["date"] = 1;
    f["datetime"] = 1;
    f["formatTimestamp"] = 1;
    f["getLogLevel"] = 1;
    f["gettid"] = 1;
    f["i16toa"] = 1;
    f["i2a"] = 1;
    f["i32toa"] = 1;
    f["i64toa"] = 1;
    f["incConsumable"] = 1;
    f["incConsumablePos"] = 1;
    f["LimLog"] = 1;
    f["~LimLog"] = 1;
    f["listStatistic"] = 1;
    f["log_10_diff_element_len"] = 1;
    f["log_10_diff_element_str"] = 1;
    f["log_10_diff_element_x1"] = 1;
    f["log_16_same_element_x6"] = 1;
    f["log_1_same_element_x6"] = 1;
    f["log_4_same_element_x6"] = 1;
    f["LogLine"] = 1;
    f["~LogLine"] = 1;
    f["LogSink"] = 1;
    f["~LogSink"] = 1;
    f["main"] = 1;
    f["now"] = 1;
    f["operator<<"] = 1;
    f["produce"] = 1;
    f["produceLog"] = 1;
    f["rollFile"] = 1;
    f["setLogFile"] = 1;
    f["setLogLevel"] = 1;
    f["setRollSize"] = 1;
    f["singleton"] = 1;
    f["sink"] = 1;
    f["sinkThreadFunc"] = 1;
    f["stringifyLogLevel"] = 1;
    f["test_blocking_buffer"] = 1;
    f["test_itoa"] = 1;
    f["test_timestamp"] = 1;
    f["time"] = 1;
    f["u16toa"] = 1;
    f["u2a"] = 1;
    f["u32toa"] = 1;
    f["u64toa"] = 1;
    f["used"] = 1;
    f["write"] = 1;
}

probe begin {
    printf("=== begin ===\n");
    init();
}

probe process("/tmp/limlog/build/tests/LogTest").function("*").call {
    fn = ppfunc()
    if (f[fn] == 1)
        printf("%s -> %s\n", thread_indent(4), ppfunc());
}

probe process("/tmp/limlog/build/tests/LogTest").function("*").return {
    fn = ppfunc()
    if (f[fn] == 1)
        printf("%s <- %s\n", thread_indent(-4), ppfunc());
}

probe end {
    printf("=== end ===\n");
}

函數的部分調用樹如下所示:

=== begin ===
     0 LogTest(25381):    -> main
   101 LogTest(25381):        -> setLogFile
   111 LogTest(25381):            -> singleton
   121 LogTest(25381):                -> LimLog
   129 LogTest(25381):                    -> LogSink
   270 LogTest(25381):                        -> now
   282 LogTest(25381):                        <- now
   288 LogTest(25381):                        -> date
   296 LogTest(25381):                            -> datetime
   453 LogTest(25381):                            <- datetime
   472 LogTest(25381):                        <- date
   478 LogTest(25381):                    <- LogSink
   576 LogTest(25381):                <- LimLog
   586 LogTest(25381):            <- singleton
   603 LogTest(25381):            -> rollFile
     0 LogTest(25382):    -> sinkThreadFunc
   650 LogTest(25381):            <- rollFile
   ···

樹狀調用可以很清楚的展示出來程序的執行邏輯,甚至可以看到多線程的處理:sinkThreadFunc 和 rollFile 之間的跨度。

  1. 開源庫對systemtap的集成
    像libguestfs 和libvirt都有支持,恰好工作環境這兩個庫也經常有一些難以排查的問題出現

觀察 libguestfs 的啟動過程及耗時,libvirt 支持function 和mark(有5個,大致邏輯上的埋點)

#! /usr/bin/env stap

global start_time, prev;

function display_time () {
  now = gettimeofday_us ()
  delta = (prev > 0 ) ? now - prev : 0
  printf ("%18d (+%10d): ", now - start_time, delta)
  prev = now
}

probe begin {
  start_time = gettimeofday_us ()
  prev = 0
  printf ("%-18s (+%10s): %s\n", "# time_usec",
          "delta usec", "event")
}

probe process("/usr/lib*/libguestfs.so.0*").function("*")
{
  display_time()
  printf ("%s\n", ppfunc())
}

打印的結果,如果使用 libguestfs-test-tools 執行失敗,可以根據產生的函數進入源代碼中進行排查,縮小排查的範圍

[root@localhost stp]# stap libguestfs.stp
# time_usec        (+delta usec): event
           1880754 (+         0): _init
           1880765 (+        11): frame_dummy
           1880768 (+         3): register_tm_clones
           1880772 (+         4): compile_regexp_re_hostname_port
           1880804 (+        32): init_libguestfs
           1881074 (+       270): guestfs_int_init_direct_backend
           1881079 (+         5): guestfs_int_register_backend
           1881083 (+         4): guestfs_int_init_libvirt_backend
           1881085 (+         2): guestfs_int_register_backend
           1881088 (+         3): guestfs_int_init_uml_backend
           ···

而 libvirt 中 example/ 目錄中就有包含一些關於 systemtap 的腳本文件。

火焰圖的生成

在函數調用樹之上更進一步,加入樣本的頻率得到svg格式的火焰圖,用戶可以點擊不同的圖層來查看更詳細的信息。

火焰圖工具為brendangregg開發的開源項目FlameGraph,配合春哥寫的systemtap工具,用一段簡單的shell腳本如下,可以得到一張svg的圖片

#!/bin/bash

# 火焰圖工具的路徑
FlameGraph_PATH="/FlameGraph"

# 春哥的棧收集工具
OR_Stap_PATH="/home/zxh/dev/openresty-systemtap-toolkit"

if [ $# != 1 ] ; then
        echo "Usage: sh $0 PID"
        echo "  e.g.: sh $0 4396"
        exit 1;
fi

${OR_Stap_PATH}/sample-bt -p $1 -t 180 -u > /tmp/bt-sample
${FlameGraph_PATH}/stackcollapse-stap.pl /tmp/bt-sample > /tmp/bt_stap.out
${FlameGraph_PATH}/flamegraph.pl /tmp/bt_stap.out > backtrace.svg

rm -rf /tmp/bt-sample
rm -rf /tmp/bt_stap.out

CPU定時採樣,根據採樣生成的 backtrace.svg 如下,橫軸為CPU佔用的時間比例,縱軸為函數調用的深度:

這是一個日誌庫的benchmark(博客園不支持上傳svg格式),而主要耗時也在阻塞隊列的入隊上,符合預期。

rpm 鏈接

  1. https://mirrors.ocf.berkeley.edu/centos-debuginfo/7/x86_64/kernel-debuginfo-common-x86_64-3.10.0-327.el7.x86_64.rpm
  2. https://mirrors.ocf.berkeley.edu/centos-debuginfo/7/x86_64/kernel-debuginfo-3.10.0-327.el7.x86_64.rpm
  3. ftp://ftp.pbone.net/mirror/ftp.scientificlinux.org/linux/scientific/7.0/x86_64/updates/security/kernel-devel-3.10.0-327.el7.x86_64.rpm

參考

  1. systemtap 原理圖, https://www.ibm.com/developerworks/cn/linux/l-cn-systemtap3/index.html?ca=drs-
  2. systemtap 官方教程(推薦),https://sourceware.org/systemtap/tutorial/1_Introduction.html
  3. systemtap 內置函數庫 tapset,https://sourceware.org/systemtap/tapsets/index.html
  4. 春哥的一系列stap工具,https://github.com/openresty/openresty-systemtap-toolkit
  5. 火焰圖工具,https://github.com/brendangregg/FlameGraph

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

互聯網是如何連接的:計網概述

當你在瀏覽器輸入網址之後會發生什麼

最直觀的感受當然是跳轉到網址所指向的頁面啦,但在網絡比較卡的時候,你可能注意到過,瀏覽器的左下角通常會有一些等待什麼什麼請求之類的小字。這時候,一個問題讓你搜索到了這篇博文,我輸入網址之後,瀏覽器到底幹了什麼?更要命的是,我想知道互聯網到底是如何把每個人連接起來的?

我們先來認識一下你的瀏覽器,雖然大多數時間你都在使用它愉快的網上衝浪。可能在你的印象里,這個玩意兒就是只能開開網頁,看看視頻,功能強大,但略顯單一。現在,隨便找個PDF文件然後打開,你的默認方式應該是你心愛的瀏覽器。如果不是,可以右鍵選擇打開方式,再用瀏覽器打開。

應該都能打開吧?這麼一說,好像我們從來沒注意過這傢伙居然還有別的用處。為什麼潛意思里覺得它就是看看網頁呢?這裏要更新一下名詞,實際上我們輸入的網址,更準確的叫法應該是URL。

URL: Uniform Resource Locator,統一資源定位符。詞聽起來有點繞口,你可以看看現在打開PDF標籤頁的地址欄,看看它的開頭是不是跟網址不一樣

URL有各種各樣的寫法“http:”、“https:”、“ftp:”、“file:”、“mailto:”,開頭部分表示了瀏覽器應當採取的訪問方式。那麼輸入網址之後,首先發生了什麼事就呼之欲出了。

瀏覽器先得解析URL

比如我們要訪問博客園的首頁,那麼應該在地址欄輸入https://www.cnblogs.com。瀏覽器看到URL的開頭是https,就會明白這是一個web請求,後面的www.cnblogs.com指的是Web服務器域名。

域名可以看成是IP地址的別名,你可以在搜索引擎里輸入IP,你會看到一連串的数字。沒有人會希望上個網還要先拿小本本把經常用到的IP地址記下來,再說,輸入這一連串的数字也很麻煩,一不小心就輸錯了。所以我們使用域名來代替IP地址,幫助記憶。

IP地址:你可以類比於現實中的住房地址,因特網上的計算機也擁有一個惟一標識符來區別它的網上鄰居(其他的電腦)。

APP支持IPv6網絡是怎麼回事?你可能在APP啟動界面的底部看到過這行小字,實際上IPv6之前是IPv4(互聯網通信協議第四版),就是一個給大家分配地址的協議,在這個版本里IP用32位的整數表示。32位?看起來很長的樣子,然而2011年的時候,IANA就宣布IPv4地址43億IP地址已經分配完畢。

後續的IPv6可謂是超級加強版,32位擴展到了128位意味着能給地球上每一粒沙子編號,他能分配大約3.4×10^38個IP地址!

向DNS查詢Web服務器的IP地址

域名對應着IP地址,那麼如何才能知道這個域名對應的IP地址是什麼呢?自然是得問拿小本本記下這些東西的人啦。

DNS : 一個可以將域名和IP地址相互映射的一個分佈式數據庫,能夠使人更方便的訪問互聯網,而不用去記住能夠被機器直接讀取的IP數串。

只用一台DNS服務器去存儲數不勝數的IP地址是不可能的,所以在分散保存的情況下,一台DNS是如何處理它查詢不到的域名信息呢?

實際上,如同域名一樣,DNS也是分級的。域名的最左邊部分表示機器名字,它隨後的部分則是該計算機所屬的組織,可能還會有子組織。最右邊則代表頂級域名,指定該計算機所屬組織的類型。大部分的頂級域都被用於美國的公司和組織,其他國家的計算機一般是用國家的特有頂級域,比如cn(中國)。

頂級域 主要應用
edu 教育機構
com 商業公司
org 非盈利組織
net 網絡供應商
cn 中國國家頂級域名

負責管理下級域的DNS服務器找不到該域名對應的IP地址就會發送一個請求到它們的上級DNS服務器中去尋找,然後上級DNS還找不到就到更上一級的DNS服務器中,以此類推。最上一級叫做根域,根域服務器的地址在配置DNS服務器的時候就已經寫入其配置文件裏面了。

分配給根域DNS服務器的IP地址在全世界僅有13個,很遺憾中國沒有。日本佔據一個,其他的全是歐美。

雖然IP地址只有13個,但實際上服務器的數量遠遠多於13個,因為根域DNS是使用多台服務器對應一個IP地址的。

不知道你是否有過瀏覽器突然不能訪問網頁的經歷,更離譜的是QQ居然能用,就他瀏覽器不行。這是為什麼呢?多半是DNS服務器地址的問題,在 控制面板\網絡和 Internet\網絡連接 右鍵屬性選擇IPv4 改成下圖一般就好了

為什麼QQ沒問題呢?因為QQ是直接通過IP連接的。

你訪問的其實是文件

現在不如點開一下我首頁的第一篇博客吧,或者直接訪問https://www.cnblogs.com/AD-milk/p/13171059.html然後按下F12打開開發者模式,讓我們看看都有些什麼?

我們請求了一個html文件,1317…好像就是輸入的網址里的那個。這麼說的話,這一個一個斜桿好像確實是像文件路徑的結構!

但如果你訪問博客園的首頁,你會發現路徑名那裡只有一個/,這表示根目錄,好像並沒有指定文件呀。這種省略文件名的情況下,一般是默認訪問根目錄下的index.html或者default.html這樣的文件。

html:超文本標記語言,你可以簡單的認為是可以在文本中嵌入音頻,圖片和鏈接的語言

按理說我們只是請求了13171059.html這個文件,但從圖中來看我們好像請求了不止一個文件,這是為什麼?回想一下,你會有過因為網卡而導致加載的頁面只有文字的情況?這一般是因為網絡問題,css文件以及圖片沒有被傳輸過來。瀏覽器在加載文件之前並不知道這裏還需要什麼圖片或者文件,只有加載之後才會繼續發送請求。

css文件是一種用來指定html樣式的文件。缺少了它頁面就沒有好看的風格了。

1 條請求消息中只能寫 1 個 URI。如果需要獲取多個文件,必須對每個文件單獨發送 1 條請求。

URI:Uniform Resource Identifier,統一資源標識符,URL是特殊的URI

眨眼間的旅途

你說的我都知道了,可你還是沒有回答我,互聯網到底是如何互聯的?

首先來考慮一個簡單的場景:兩台電腦之間如何互相通訊?當然是接跟線把兩個都連上啦,那再來五台怎麼辦?往電腦上再打五個接口?這顯然不現實,我們可以讓集線器幫我們的忙。它具有多個端口,可以實現其內部所有網絡設備的連通。不過集線器是個榆木腦袋,它唯一知道的事情就是:當某一個端口發出數據時,它就把這個數據複製到與其連接的其他端口,這樣所有連接到集線器的設備都可以獲得這個數據包。這跟個大喇叭一樣,太煩人了,說點悄悄話都不行。

之所以電纜不如光纖通信速率高,是因為電信號在提升通信速率的同時,其衰減率也會提高(信號在傳播過程中減弱),導致信號無法傳到目的地。相對地,光信號本來的衰減率就很低,提高通信速率也並不會提高衰減率。此外,光纖還不受電磁噪聲的影響,因此光纖能夠進行高速通信。

不是光信號本來就比電信號快啦!!!

為了解決廣播所帶來的安全問題,以及減少不必要的流量,我們可以換個聰明點的傢伙:交換機。交換機比集線器智能的地方在於,它記下了與其相連的主機的物理地址MAC,他把這些存儲在地址表裡面。那麼現在,當數據報從一個端口發出時,它能根據數據報提供的目標MAC,直接將數據發往預期的目的端口。終於可以和喜歡的女同學說悄悄話了,呼~~。

但集線器和交換機只能在局域網中交換信息,無法在外部網絡交換。因為要在互聯網上通訊需要識別IP地址,顯然集線器和交換機沒有這個功能。所以我們需要用到路由器:它是一個能根據IP地址,將數據報從一個路由轉發到另外一個路由的設備。這意味着它具有過濾功能,但一個數據報達到該路由時,它會檢查這是否是發給自己的,如果不是的話就將它轉發給其他路由。所以它相當於一個網絡的網關。

現在的路由器大多集成了三者的功能,成了“瑞士軍刀”。讓人想不到的是,儘管交換機比路由器簡單,但實際上路由器早於交換機問世。

現在從我們電腦發出的請求數據報就沿着電路,被多個路由器轉發,最後到達目的地。

至此,這眨眼間的漫長旅途迎來了終點。但其實網絡通訊遠不止這些,這裏省去了很多東西,其中最重要的就是各式各樣的協議了。缺少協議會使得網絡世界通訊困難,就好比現實生活中你覺得點頭表示OK,搖頭表示NO,但另外一個人卻持相反的認識,這時候你們倆的交流就會遇上大麻煩!

協議:定義了在兩個或多個通信實體之間交換的報文格式和順序,以及報文發送和接收一條報文或其他事件採取的動作

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

Mariadb之顯式使用表鎖和行級鎖

  首先我們來看看mariadb的鎖定概念,所謂鎖就是當一個進程或事務在操作某一資源時,為了防止其他用戶或者進程或事務對其進行資源操作,導致資源搶佔而發生衝突,通常在A進程操作該資源時,會對該資源進行加鎖,實現多進程或多用戶操作同一資源時,不會發生衝突;通常情況鎖的類型分讀鎖和寫鎖,所謂讀鎖就是共享鎖,它可以實現多個讀操作共享;而寫鎖就是排它鎖,獨佔鎖,一旦加了寫鎖,其他用戶的讀寫操作將被阻塞,直到該寫鎖被釋放或者因超時而被釋放,在其他用戶進行的讀寫操作,此時就會被執行;對於鎖定範圍來講,它又可以分為,表鎖和行鎖,從字面意思就可以理解到,表鎖就是針對整張表所施加的鎖,而這種鎖定力度相當粗糙,併發相對就比較低,但是維持鎖狀態鎖消耗的成本資源就較小;對於行鎖來說,它針對的範圍就是行級別所施加的鎖,這種鎖的粒度就相對要精細,同時併發相對較高,但是維護鎖狀態消耗的成本資源就相對要大;對於mysql來講又鎖分為存儲引擎級別的鎖和mysql server級別的鎖,存儲引擎級別的鎖指的是對於何時施加鎖或者釋放鎖由存儲引擎自行決定;mysql server級別鎖指的是用戶使用命令可自行決定施加鎖或釋放鎖;簡單講就是允許用戶顯式請求加鎖或釋放鎖;顯式鎖就是用戶手動用命令施加的鎖,隱式鎖指的是由存儲引擎根據需要自行施加的鎖;對於innodb存儲引擎來講,它支持事務,行級鎖;而早期的MyISAM存儲引擎它不支持事務,對鎖的粒度是表級鎖,不支持行級鎖;

  显示鎖的使用

  1)LOCK TABLES

    指令使用語法:

    LOCK TABLES  tbl_name  read|write, tbl_name read|write, …

  示例:

  提示:以上語句表示對test_tb這張表施加讀鎖操作,這意味着其他用戶或進程都不能對該表進行寫的操作,只能讀,因為讀鎖是共享鎖;

  測試:對test_tb表進行寫操作,看看是否能夠寫進去?

  提示:從上面的提示,它告訴我們test_tb這張表施加了讀鎖,不允許更新;這說明施加讀鎖,對於寫的操作就不能進行;

  測試:對test_tb表進行讀操作,看看是否能夠進行呢?

  提示:可以看到加了讀鎖的表,對於讀操作上可以繼續進行的;

  測試:對test_tb表施加寫鎖

  提示:釋放鎖用unlock tables即可釋放剛才的讀鎖;

  測試:對test_tb進行寫操作,看看是否能夠進行?

  提示:在當前終端(加寫鎖所在終端)上是可以進行讀寫操作的;

  測試:在其他終端看看是否能夠對test_tb表進行讀寫操作呢?

  提示:從上面的截圖可以看到當我們重新啟動一個終端對test_tb進行寫操作,它一直處於阻塞狀態;

  提示:對於對操作也是同樣的效果;一直阻塞着;

  總結:對於施加讀鎖的表,是可以進行讀操作的,但是不能進行寫操作,包括當前終端也不能寫操作;對於施加寫鎖的表,在當前施加鎖的終端上是可以對其進行讀寫操作的,但是在別的終端讀寫操作都將阻塞;

  除了以上指令來對錶進行加鎖外,還可以使用 flush tables指令來加讀鎖,具體語法請看下面;

  FLUSH TABLES tbl_name,… [WITH READ LOCK];

  測試:加讀鎖

  提示:以上flush tables 只能加讀鎖,不能加寫鎖;

  行級鎖:SELECT cluase [FOR UPDATE | LOCK IN SHARE MODE]

  行級排它鎖

  提示:以上紅框中的內容就是給第一行加了一個排它鎖,這意味着該事務沒有提交,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排它鎖,但是獲取排它鎖的事務是可以對數據就行讀取和修改。

  提示:可以看到我們重新啟動一個事務,然後對第一行進行更新操作,語句就阻塞在哪裡了;說明行級排它鎖對其他事務來講是不允許對加鎖的行進行寫操作;默認情況updeate更新會默認加上排它鎖,因為對於第一行來講,已經有一個排它鎖了,所以其他事務就不能對其在加其他鎖;而對於select語句來講,它執行時默認會加任何鎖的,所以我們執行select語句是可以正常的查看第一行數據;如果我們在select後面手動加鎖,它也會阻塞的;如下

  提示:從上面的截圖信息可以看到,我們手動加上排它鎖,查詢語句也不會順利執行;從上面信息還可以了解到,我們對第二行也沒法進行操作,這又是為什麼呢?

  提示:我們查看test_tb這張表上的索引信息,發現沒有索引,然後我們在上面創建了一個索引;創建索引時,需要把前面的事務提交了,才可創建成功,否則一直鎖在哪裡的;接下來我們在創建一個事務,把第一行加上排它鎖,然後在對第二行操作看看是否還會一直阻塞呢?

  提示:可以看到當我們創建就了索引后,再對第一行加鎖,然後更新第二行就可以正常更新了 ,對第一行還是處於阻塞狀態;這說明innodb存儲引擎的行級鎖的實現其實是依靠其對應的索引,所以如果操作的行並沒有用到索引,那麼用的還是表級鎖。施加行級排它鎖后,其他事務將不能對其在施加任何鎖;那麼對於獲取到排它鎖的是否能夠正常操作呢?

  提示:對於獲取到排它鎖的事務,是可以正常更新修改的;也可以給對應行施加其他鎖;

  行級共享鎖

  提示:以上紅框中的內容表示給第一行施加共享鎖,這意味着在其他事務鎖可以共享這把鎖看到數據,但是不能更新修改數據;

  測試:在當前事務中更新數據,看看是否可更新?

  提示:在當前事務中是可以正常修改數據的;也能正常查看數據;

  在其他事務中修改數據,看看是否可修改?

  提示:可以看到在其他事務中,就不能對有共享鎖的行進行修改操作,但是可以正常讀;

  總結:innodb存儲引擎的行級鎖依賴索引,如果沒有索引,就相當於表級鎖;對於排它鎖來講,獲取到排它鎖的事務是可以正常修改更新以及加共享鎖,對於沒有獲取到排它鎖的事務,是不能夠對有鎖的行進行修改更新以及加鎖的操作;對於共享鎖來講,對於當前事務(加鎖操作的事務)是可以正常修改更新有鎖的行,對於其他事務,是不可修改和更新有鎖的行;

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

福特攜兩款新智慧電動車 亮相MWC2015

在巴賽隆納舉辦的2015世界移動通信大會上,福特汽車公司宣佈了「智慧騎行」的試驗專案,首推智慧電動車,這也是一項通過在車載連接技術、移動出行、自動駕駛汽車、消費者體驗以及大資料方面的創新,説明改變世界出行方式的計畫。   首推的倆款智能電動車為MoDe:Pro與MoDe:Me。MoDe:Pro由福特團隊打造完成,用於商業用途。MoDe:Me在自行車製造商Dahon的協助下打造完成,便於摺疊存放。    

(圖片來源:騰訊)

    這兩款電動自行車都配備了200瓦的馬達和9安培小時的電池,提供電動踏板輔助,最高時速可達2萬5千公尺。原型電動自行車的技術可實現行車預警系統,在汽車超車時,透過車把手的震動向騎士們發出警告,還可通過開啟把手上的警示燈,提醒汽車司機注意電動自行車的存在。   MoDe:Me和MoDe:Pro可與一款名為MoDe:Link的原型應用程式配合使用,此款應用程式可與iPhone 6手機相容。通過應用程式中的即時資訊,電動自行車可實現導航、線路選擇、速度和舒適度調整等功能。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

【秒懂Java】【第1章_初識Java】01_編程語言

各位小夥伴們好哇!從今日起,我將開始更新《秒懂Java》系列文章,從0開始講解Java的方方面面,完全零基礎也可以看懂。後面也將推出配套的視頻版,歡迎大家保持關注!

  • 我會儘力辦到:在保證通俗易懂的同時,不丟失知識的嚴謹性和完整性
  • 不管你是否有編程經驗,只要你感興趣、細心閱讀,就能學會
  • 本文是《秒懂Java》系列的第1篇文章,主要認識幾個基礎概念

什麼是計算機?

一說到計算機(Computer),大家首先想到的可能是電腦(台式電腦、手提電腦)。

實際上,我們日常生活中使用的平板電腦智能手機也屬於計算機,它們的功能也跟電腦一樣非常強大。

還有KTV的點歌機、超市的自助收銀機等很多設備也都屬於計算機。

毋庸置疑,計算機是人類歷史上最偉大的發明之一,極大地提高了社會的生產力,目前它已經延伸到了生活、學習、工作等各個領域,無處不在。如今,我們會在計算機上安裝各種各樣的軟件(應用、遊戲),學習工作、衣食住行、吃喝玩樂一網打盡,極大地改變了我們的生活、學習、工作方式。

什麼是編程語言?

語言,是雙方進行溝通交流的主要表達方式。

  • 如果我要跟咱們中國人進行交流,應該用漢語
  • 如果我要跟美國人進行交流,應該用英語
  • 如果我要跟韓國人進行交流,應該用韓語

那如果我要跟計算機進行交流呢?那就應該用計算機編程語言

  • 是的,計算機編程語言,就是用來跟計算機進行溝通交流的語言
  • 一般把計算機編程語言簡稱為:編程語言(Programming Language)

注意:我們要學習的很多IT技術都源自西方國家(比如美國),因此,很多技術名詞,都是從英文翻譯過來的。為了保證描述的嚴謹性,當首次提及某個技術名詞時,我都會在它旁邊標註原本的英文單詞。

與計算機進行交流

那如何利用編程語言與計算機進行交流呢?

編程語言,顧名思義,就是可以用來“編寫程序”的語言。

  • 首先,利用編程語言編寫一段程序。例如上圖所示的程序,只包含了3行代碼,這裏簡單說一下代碼的大概意思(了解一下即可,不用去深究)
    • 第1行:創建了一個播放器
    • 第2行:設置播放器的音量為100
    • 第3行:開始播放某個mp4視頻
  • 最後,將程序運行到計算機上,計算機就會開始識別執行程序中的每一句代碼,完成相應的功能,最後成功播放視頻

我們平時使用的各種軟件(應用、遊戲)都是通過編程語言開發出來的,它們都由一大堆的代碼組成。當打開軟件時(將軟件運行到計算機上時),計算機就會開始識別執行軟件中包含的代碼,完成相應的功能。

所以,編程語言有一個非常重要的作用,那就是:開發軟件!

主流編程語言

世界上有上百種各式各樣的編程語言,目前比較常見的主流編程語言有

  • Java、C、C++、C#、PHP、Python、Go
  • JavaScript(簡稱JS)、TypeScript(簡稱TS)
  • Objective-C(簡稱OC)、Swift、Kotlin
  • Scala、Assembly Language(彙編語言) 等

每一門編程語言的作用都不太一樣,比如

  • Java、Kotlin:可以用來開發Android系統中的軟件
  • Objective-C、Swift:可以用來開發iOS、Mac系統中的軟件
  • C、C++、C#:可以用來開發Windows系統中的軟件

當然,上面列舉的僅僅是它們的部分功能,並沒有說完整。比如:

  • C、C++也可以開發Android、iOS、Mac、Linux等系統中的軟件
  • Java也可以開發Mac、Linux、Windows等系統中的軟件

其他的就不一一說明了,了解一下即可

語法

每當我們要學習一門新的語言時,都要先學習它的語法。

  • 比如,學習英語就要先學習它的語法,英語的語法規定了:英文句子可以怎麼寫、不可以怎麼寫
  • 同樣的,每一門編程語言都有自己的語法,編程語言的語法規定了:你的代碼可以怎麼寫、不可以怎麼寫
    • 比如,Java語言的語法規定:每一句代碼後面都必須以分號(;)結束
    • 代碼一旦出現了語法錯誤,就無法成功運行到計算機上

不同編程語言的語法是不一樣的,每一門編程語言都有自己特有的語法。比如,想讓計算機播放一個視頻,不同編程語言可能會有不同的寫法。

不難看出它們之間的一些差異(了解一下即可,不用去深究)

  • Java、OC都以分號(;)結束,而Python不需要以分號(;)結束
  • Java、Python中都使用了點(.)、小括號(()),而OC中使用了中括號([])、冒號(:)、@符號
  • Java、OC中都使用雙引號(“”),而Python中可以使用單引號(

雖然它們的寫法不一樣,但是都完成了一樣的功能:讓計算機播放一個視頻。如果想利用編程語言開發出強大優秀的軟件、控制計算機做更多的事情,首先要踏踏實實學好編程語言的語法。如果你連語法都不懂,怎麼可能寫出正確的代碼呢?

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

特斯拉 Model S 自駕模式「autopilot」將於 3 個月內推出

特斯拉執行長 Elon Musk 透露未來將透過 7.0 版本升級,為 Model S 車款帶來全新自動駕駛(self-driving)模式「autopilot」,預計在 3 至 4 個月內釋出軟體更新。  
  在新聞發佈會上,Elon Musk 公佈下一波 6.2 版本升級,新增里程保證(Range Assurance)和旅程規劃(Trip Planner)兩大關鍵功能。里程保證在於行駛過程中,系統會背景監控電力狀況並即時告知車主;旅程規劃則是在車主設定目的地之後,系統自動判斷行駛過程中需要充電的地點,規劃出最佳路線,這都是為了減輕部分車主的「里程焦慮」(Range Anxiety)問題。除了上述新功能之外,Elon Musk 還介紹了一些和主動安全相關的輔助功能,例如自動緊急剎車、盲區警告以及側面碰撞警告等。   不過,新聞發佈會上最令人興奮的是,Elon Musk 透露未來將透過 7.0 版本升級,為 Model S 車款帶來全新自駕模式「autopilot」。   Elon Musk 指出,擁有 Model S 車款的車主基本上可透過 autopilot 模式,做到往返舊金山和西雅圖之間無須任何操控動作。不過他也謹慎地表示,這還不算是真正的自動駕駛技術,只不過是強大的自動轉向系統。autopilot 不足之處,在於它僅適用於行駛在高速公路上,以該公司目前的技​​術,可能還無法安全地駛入郊區,畢竟街上難免還是會有孩童或路人竄出。欲使用 autopilot 模式,車主還需要選配特斯拉所提供價值 4,250 美元的 optional tech 方案。     本文全文授權轉載自《科技新報》─〈〉

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案