2021 小米年貨節將於 1/19~1/25 開跑!活動優惠整理_如何寫文案

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

近期小米台灣除了在台灣推出「小米智慧攝影機雲台版2K」和「小米 WiFi 訊號延伸器 Pro」,也預告將在 1 月 19 日上午 10 點開賣「小米手錶超值版」與「米家螢幕掛燈」,想必大家也有預感又有新活動要來臨吧?今日稍早小米正式宣佈「2021 小米年貨節」將在 1 月 19 日至 1 月 25 日正式開跑囉!

2021 小米年貨節將於 1/19~1/25 開跑!活動優惠整理

去年有哪些小米產品要買卻錯過優惠嗎?今日稍早小米台灣正式宣佈 2021 小米年貨節將在明(19)日起至 1 月 25 日推出囉!這次除了幾款小米新品搭上活動開賣外,消費者可在每日完成指定任務獲得現金券、透過積分獲得額外的現金券,也有像是滿額贈品、滿額折扣以及最直接的直降商品優惠!

2021 小米年貨節(1/19~1/25)
活動頁面:點我前往|活動規則:點我前往

簽到領積分

於 1 月 19 日 10:00 至 1 月 25 日期間簽到領取限量發放簽到積分,連續簽到 7 天另可獲得「NT$100 無門檻現金券」,簽到禮睬每日限量發放、先完成先取得。

小米年貨節優惠券

活動期間每日 10:00 限量發放 NT$100~NT$1500 現金券(手機及新品不適用),每筆小米帳號單日各現金券限領取 1 張,數量有限、領完為止。

頁面領券現金券(手機及新品不適用):

  • NT$100 現金券(滿 NT$1,000 使用)
  • NT$200 現金券(滿 NT$2,000 使用)
  • NT$550 現金券(滿 NT$5,000 使用)
  • NT$850 現金券(滿 NT$7,000 使用)
  • NT$1,500 現金券(滿 NT$10,000 使用)

限量秒殺券&指定商品秒殺券

限量秒殺券於活動期間每日指定時段(10:00、12:00、14:00、18:00、20:00)限量發放,指定商品現金券則於指定日期 10:00 限量發放。限量秒殺券與指定商品秒殺券每個小米帳號活動期間限領取 1 張(數量有限,領完為止)。

限量秒殺券(手機及新品不適用現金券):

  • NT$500現金券(滿 NT$1,000 使用)
  • NT$1,000 現金券(滿 NT$2,021 使用)

指定商品秒殺券:

  • 1月19日:NT$400現金券(僅限購買米家掃拖機器人 G1 使用)
  • 1月20日:NT$400現金券(僅限購買米家空氣淨化器 Pro 使用)
  • 1月21日:NT$800現金券(僅限購買小米手環 5 滿2件及以上使用)
  • 1月22日:NT$200現金券(僅限購買米家無線吸塵器 G10 使用)
  • 1月23日:NT$400現金券(僅限購買小衛質品泡沫洗手液 六瓶裝 滿2件及以上使用)
  • 1月24日:NT$200現金券(僅限購買小米小愛音箱 Art 使用)
  • 1月25日:NT$200現金券(僅限購買小米真無線藍牙耳機 2S 使用)

積分兌換禮

小米年貨節活動期間,用戶可透過分享、下載App、註冊積分會員等方式賺取積分,並能積分兌換現金券使用,積分兌換禮採每日 10:00 限量發放。

超值滿額禮

活動期間單筆訂單滿指定金額,即可獲得相關贈品或現金券:

滿額贈內容:

活動1|消費單筆訂單(不含手機)滿 NT$3,000:
贈小米手環 4C 或 米家 wiha 8合1 棘輪螺絲起子(單筆訂單只贈送一個)

活動2|消費單筆訂單(不含手機)滿 NT$6,000:
贈小米小愛音箱 Play 或 10000 小米行動電源 3 無線版 超值版 白色(單筆訂單只贈送一個)

活動3:消費單筆訂單(不含手機)滿 NT$9,000:
贈小米手環 5 或 米家電動刮鬍刀 S500(單筆訂單只贈送一個)

活動4:消費單筆訂單(不含手機)滿 NT$14,000:
贈小米小愛音箱 Art,單筆訂單只贈送一個
訂單金額滿 NT$14,000 時,活動 1 、2、3、4 需四選一(數量有限,贈完為止)

消費單筆訂單(不含手機)滿 NT$25,000:
贈 NT$3,000 現金券包(包含:NT$800 現金券 2 張、NT$500 現金券 2 張、NT$200 現金券 2 張)

2021 小米年貨節(1/19~1/25)
活動頁面:點我前往|活動規則:點我前往

超值組合

於小米年貨節活動期間購買以下商品套餐組合,即可享套餐優惠價。

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

超值組合內容:

  1. 米家無線吸塵器G10/G9 HEPA 濾芯套裝+米家無線吸塵器mini HEPA濾芯(兩個裝)任意兩件,組合價:NT$360
  2. 米家聲波電動牙刷 T500+米家聲波電動牙刷頭 通用型 / 敏感型(刷頭二選一),組合價:NT$1100
  3. 小米便攜相片印表機+小米便攜印表機即貼相紙,組合價:NT$1,790
  4. 小米34型曲面螢幕+小米木紋滑鼠墊+小米無線雙模滑鼠 靜音版,組合價:NT$13,360
  5. 米家 LED 智慧燈泡 Lite 彩光版 白色 3支裝,組合價:NT$945
  6. 米家電動刮鬍刀 S500+米家電動刮鬍刀S500刀頭,組合價:NT$995
  7. 米家便攜電動刮鬍刀 1S(往復雙刀頭)+刀頭,組合價:NT$1,100
  8. 米兔兒童聲波電動牙刷+刷頭,組合價:NT$1,100
  9. 小米液晶手寫板 兩個裝,組合價:NT$840
  10. 小米濾水壺濾芯三支裝 兩個裝,組合價:NT$690
  11. 小衛質品泡沫洗手液(九瓶裝),組合價:NT$385
  12. LINE FRIENDS 20吋旅行箱 莎莉限定版+小米迷你雙肩包,組合價:NT$1,995
  13. 米家吸頂燈 450+Yeelight 遙控器,組合價:NT$1,790
  14. 米家掃拖機器人類配件,買2件減NT$80,買3件減 NT$150 配件包含:
  • 米家掃拖機器人 1C 塵盒濾網
  • 米家掃拖機器人1C 邊刷
  • 米家掃拖機器人 1C 主刷罩
  • 米家掃拖機器人 1C 主刷
  • 米家掃拖機器人邊刷
  • 米家掃拖機器人拖布
  • 米家掃拖機器人 1C 防潮墊
  • 米家掃地機器人虛擬牆
  • 米家掃拖機器人主刷罩
  • 米家掃拖機器人G1 主刷罩
  • 米家掃拖機器人G1 主刷
  • 米家掃拖機器人G1 一次性拖布
  • 米家掃拖機器人G1 集塵盒濾網
  • 米家掃拖機器人G1 拖布
  • 米家掃拖機器人G1 邊刷

超值加價購

於小米年貨節活動期間購買指定商品,即可以優惠價加價購指定商品。

超值加價購內容:

  • 買米家無線吸塵器 G10 加 NT$140 購米家無線吸塵器G10/G9 HEPA 濾芯套裝一個
  • 買米家無線吸塵器 G10 加 NT$1,495 購米家無線吸塵器G10/G9 增程電池一個
  • 買小米手環 5 加 NT$10 購腕帶一條 或 充電線 一個
    (同一筆訂單購買兩個手環可以加購兩個相同顏色的腕帶,如需不同顏色,可分開下單)
  • 買小米GaN充電器 Type-C 65W 加 NT$10 購線材一條:
    小米二合一傳輸線 100cm / 小米 USB-C 傳輸線 編織線版 100cm 紅色 / 小米 Micro USB 傳輸線 編織線版 100cm 紅色 / 小米 Micro USB 傳輸線 編織線版 100cm 黑色 / 小米二合一傳輸線 30cm / 小米 USB-C 傳輸線 編織線版 100cm 黑色 / 小米 USB type-c to type-c 傳輸線 150cm
  • 買小米GaN充電器 Type-C 65W 加 NT$95 購線材一條:
    小米Type-C轉Lightning傳輸線(1m)
  • 買米家掃拖機器人 G1 加 NT$95 購配件一個(可累計加購,限加購不同配件)配件包含:
    主刷罩/主刷/一次性拖布/集塵盒濾網/拖布/邊刷
  • 買米家掃拖機器人 1C 加 NT$95 購配件一個(可累計加購,限加購不同配件)配件包含:
    塵盒濾網/邊刷/主刷罩/主刷/防潮墊/拖布
  • 買米家無線吸塵器 mini 加 NT$95 購 HEPA 濾芯(兩個裝)一個
  • 買米家自動感應洗手機 單機版 加 NT$255 購洗手液(六瓶裝)一個

2021 小米年貨節(1/19~1/25)
活動頁面:點我前往|活動規則:點我前往

精選年貨,商品直降活動

小米年貨節活動期間,凡參與優惠活動的商品在活動頁面上會顯示「省xxx」標籤,消費者可在小米年貨節活動期間點擊「立即購買」標籤查看參與活動的相關商品型號,參與直降活動的商品內容與幅度依照台灣小米公佈為準。

小米年貨節直降商品清單(完整商品內容依照小米官方公佈為準):

和過去的活動一樣,小米活動頁面的商品並未按照商品類型排列,為方便各位更容易閱讀,筆者也將小米年貨節活動頁面的商品清單重新整理了優惠商品清單如下:

  • 米家無線吸塵器 G10:NT$6,995(省 NT$500)
  • 米家手持無線吸塵器 Lite:NT$4,495(省 NT$500)
  • 米家掃拖機器人 白色: NT$7,995(省 NT$1,000)
  • 米家掃地機器人 白色:NT$7,295(省 NT$600)
  • 米家掃拖機器人 1C:NT$6,095(省 NT$500)
  • 米家掃拖機器人 G1:NT$4,395(省 NT$600)
  • 米家空氣淨化器 Pro:NT$5,495(省 NT$1,400,每天 10:00 限量開賣、預計 1 月下旬發貨)
  • 90分金屬旅行箱 銀色:NT$4,495(省 NT$500)
  • 小米旅行箱 20吋 灰色:NT$1,495(省 NT$100)
  • 米家電磁爐:NT$1,595(省 NT$200)
  • 米家 IH 電子鍋 白色:NT$2,395(省 NT$100)
  • 米家恆溫電水壺 白色:NT$1,095(省 NT$100)
  • 米家直流變頻電風扇:NT$1,595(省 NT$200)
  • 米家吸頂燈 450:NT$1,695(省 NT$100)
  • 米家床頭燈:NT$895(省 NT$400)
  • 米家便攜相片印表機:NT$1,495(省 NT$170)
  • 小米真無線藍牙耳機 2S:NT$1,795(省 NT$200)
  • 小米藍牙耳機 Earbuds 超值版:NT$505(省 NT$40)
  • 小米小愛音箱 Art:NT$1,295(省 NT$200)
  • 小米小愛音箱 Play:NT$535(省 NT$60)
  • 小米手環 5:NT$845(省 NT$100)
  • 小米手環 4C:NT$445(省 NT$50)
  • 米家電動刮鬍刀 S500 黑色:NT$895(省 NT$100)
  • 米家聲波電動牙刷 T500:NT$895(省 NT$100)
  • 20000 小米行動電源 3 高配版:NT$945(省 NT$50)
  • 10000 小米行動電源 3 無線版 超值版 白色:NT$545(省 NT$50)
  • 10000 小米行動電源 QC3.0 高配版 灰色:NT$645(省 NT$150)
  • 米家電動打氣機:NT$945(省 NT$50)
  • 小米無線車充:NT$845(省 NT$100)
  • 小米車用充電器 快充版 37W:NT$245(省 NT$20)
  • 米家電動起子機:NT$795(省NT$100)
  • 米家 wiha 8合1 棘輪螺絲起子 黑色:NT$495(省 NT$50)
  • 小米 USB 3.0 HUB:NT$185(省 NT$40)

2021 小米年貨節(1/19~1/25)
活動頁面:點我前往|活動規則:點我前往

滿 NT$1,000 減 NT$100

除了上述「直降」優惠,部分指定商品另享美滿 NT$1,000 減 NT$100  優惠,參與直降活動商品與優惠幅度一樣依照小米官方公佈為準。

滿 NT$1,000 減 NT$100 商品清單:

部分商品消費滿 NT$1,000 可減價 NT$100 ,筆者也將活動頁面商品重新整理方便各位閱讀:

  • 90分金屬旅行箱 銀色
  • 小米旅行箱 20 吋 灰色
  • 小米極簡都市雙肩包 2
  • 小米經典商務雙肩包 2 深灰
  • 小米經典商務雙肩包 黃色
  • 米家水離子吹風機 白色
  • 米家自動感應洗手機 單機版
  • 米家兒童聲波電動牙刷
  • 米家兒童聲波電動牙刷頭 3 支裝
  • 米家聲波電動牙刷頭 敏感型 3 支裝
  • 米家聲波電動牙刷頭 通用型 3 支裝
  • 貝醫生巴氏牙刷 四色裝
  • 米家便攜電動刮鬍刀 刀頭
  • 米家電動刮鬍刀 S500 刀頭 黑色
  • 米家電動刮鬍刀 S500 黑色
  • 米家便攜電動刮鬍刀 1S(往復雙刀頭)
  • 米家掃地機器人塵盒濾網
  • 米家掃地機器人主刷罩
  • 米家掃地機器人主刷 橘色
  • 米家掃地機器人邊刷
  • 米家掃拖機器人 1C 拖布 灰色
  • 米家掃拖機器人 G1 集塵盒濾網
  • 米家掃拖機器人 G1 拖布
  • 米家掃拖機器人 G1 主刷罩
  • 米家掃拖機器人 G1 主刷
  • 米家掃拖機器人 G1 邊刷
  • 米家掃拖機器人G1一次性拖布
  • 米家掃拖機器人塵盒濾網 白色
  • 米家掃拖機器人主刷 橘色
  • 米家掃拖機器人水箱 黑色
  • 米家掃拖機器人一次性拖布 白色
  • 米家無線吸塵器G10/G9 HEPA 濾芯套裝
  • 米家無線吸塵器mini HEPA濾芯(兩個裝)
  • 米家空氣淨化器濾芯 除甲醛增強版 1S
  • 米家空氣淨化器濾芯 抗菌版
  • 知吾煮湯鍋 米家定製
  • 小米濾水壺 白色
  • 小米濾水壺濾芯三支裝 白色
  • 米家恆溫電水壺 1S
  • 米家調理機
  • 米家電動起子機
  • 小米液晶手寫板
  • 米家自動傘
  • 小米體重計 2
  • 米家 wiha 8合1 棘輪螺絲起子 黑色
  • 米家精修螺絲起子套裝組
  • 小米雙單元半入耳式耳機 黑色
  • 小米圈鐵耳機 Pro 銀色
  • 小米戶外藍牙喇叭
  • 小米方盒子藍牙喇叭 2
  • 小米小愛音箱 Play
  • 小米戶外藍牙喇叭 mini
  • 米家智慧攝影機
  • 米家床頭燈 2 白色
  • 米家床頭燈 金色
  • 米家感應夜燈 2 白色
  • 米家感應夜燈 2 藍牙版
  • 米家 LED 充電式檯燈 白色
  • 米家 LED 智慧燈泡 白光版
  • 米家 LED 智慧燈泡 Lite 彩光版 白色
  • 米家人體感應器 白色
  • 米多功能網關 2
  • 米家智慧插座 ZigBee
  • 米家門窗感應器
  • 小米光照度感應器
  • 米家無線開關
  • Yeelight 遙控器
  • 米家藍牙溫濕度計 2
  • 小米 50W 雙模行動電源 1A1C
  • 小米GaN充電器 Type-C 65W
  • 小米 USB 充電器 36W 快充版
  • 5000 小米行動電源 2 銀色
  • Redmi行動電源 10000 標準版 黑色
  • 10000 小米行動電源 3 快充版 銀色
  • 10000 小米行動電源 QC3.0 高配版 灰色
  • 10000 小米行動電源 3 無線版 超值版 白色
  • 20000 小米行動電源 3 快充版
  • 小米 Micro USB 傳輸線 編織線版 100cm 紅色
  • 小米Type-C轉Lighthing傳輸線(1m)
  • 小米 USB type-C to type-C 傳輸線 150cm
  • 小米 USB-C 傳輸線 編織線版 100cm 紅色
  • 小米 USB-C 傳輸線 編織線版 100cm 黑色
  • 小米二合一傳輸線 100cm
  • 小米二合一傳輸線 30cm
  • 小米 USB3.0 HUB
  • 小米車用充電器 2 快充版 18W
  • 小米車用充電器 快充版 37W
  • 小米延長線 黑色
  • 小米延長線 白色
  • 米家魔方延長線
  • 小米藍牙自拍桿 黑色
  • 小米支架式自拍桿 灰色
  • 小米無線雙模滑鼠 靜音版 黑色
  • 小米木紋滑鼠墊
  • 小米便攜印表機即貼相紙
  • 小米隨身風扇 白色
  • 小米手環 5
  • 小米手環 5 專用充電線
  • 小米手環 5 腕帶 深青色
  • 小米手環 4C
  • 小米手環 4 專用充電線 黑色
  • 小米手環 4C 腕帶 深空藍
  • 小米手環 4C 腕帶 橄欖綠

超夯新品

小米年貨節也推出「小米手錶超值版」、「米家螢幕掛燈」、「米家無線吸塵器 G10/G9 增程電池」以及限量開賣「小米智慧顯示器 65 型」。

超夯新品內容(新品不適用現金券):

  • 小米手錶 超值版:NT$1,495
  • 米家螢幕掛燈:N%T$995
  • 小米智慧顯示器 65 型:NT$18,999
  • 小米 WiFi 訊號延伸器 Pro:NT$365
  • 小米智慧攝影機 雲台版 2K:NT$1,095
  • 米家無線吸塵器 G10/G9 增程電池:NT$1,995

2021 小米年貨節(1/19~1/25)
活動頁面:點我前往|活動規則:點我前往

圖片/消息來源:小米台灣

延伸閱讀:
小米智慧顯示器65型開箱:搭載 4K HDR 10-bit超高畫質面板、DTS-HD 杜比音效無敵性價比的聯網電視

小米摺疊螢幕手機工程機曝光!再次於地鐵車廂被捕獲,只是螢幕摺痕有點顯眼

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

iOS 14 現在會因偵測到非原廠相機零件而顯示警告通知_網頁設計公司

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

iPhone 手機過保固後的維修價格實在不便宜,很多人會選擇在保固期結束之後尋求民營小維修工作室的服務,雖然並非使用原廠零件更換,但顯然維修費用便宜許多。不過近日國外媒體發現 iOS 14 開始會檢查用戶的相機零件,如果使用非原廠相機模組將會跳出通知來提醒。

iOS 14 現在會因偵測到非原廠相機零件而顯示警告通知

根據國外媒體 MacRumors 發現,且透過 ZDNet 證實 ,從近日剛釋出的 iOS 14.4 開發者 Beta 2 版本中出現了一個之前沒有過的錯誤訊息,警告用戶目前手機上所裝載的相機零件並非真正的 Apple 零件。在過去 Apple 就已經針對非原廠電池實施同樣的策略,不過當時是針對非原廠電池禁用了電池剩餘最大容量的健康狀況功能,不影響手機正常使用,所以推出該非原廠相機訊息視窗並不會影響手機的功能或顯示,但後續會有怎樣的動作還有待觀察。

使用非原廠相機零件可能會引導用戶取得 Apple 的支援,強調 iPhone 維修的重要性,並且提倡用戶將手機交由授權維修中心裡面通過原廠訓練的人員完成。在去年時,根據知名維修網站 iFixit 報告中,授權技術人員在維修時必須運行 Apple 專有的雲端系統設置應用,以完成整個 iPhone 12 機型的相機和顯示器維修,倘若沒有完成此步驟則可能導致相機在短時間內遇到問題或完全不回應。

以目前的收費標準來看,Apple 的收費顯然較高,甚至超過一般用戶可以接受的範圍,所以才會使得用戶尋求第三方服務,其實要能夠讓用戶捨棄第三方零件最簡單的方法就是降低整個維修費用。

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

◎資料來源:MacRumors、ZDNet

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

數據加密 第五篇:非對稱密鑰_如何寫文案

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

非對稱密鑰(Asymmetric Keys)跟對稱密鑰相對,它使用一對密鑰(算法),一個密鑰用於加密,另一個密鑰用於解密,加密的密鑰稱為私鑰(private key),解密的密鑰稱為公鑰(public key)。私鑰由一方安全保管,不能外泄,而公鑰則可以發給任何請求它的人。比如,你向銀行請求公鑰,銀行將公鑰發給你,你使用公鑰對消息加密,那麼只有私鑰的持有人——銀行才能對你的消息解密。與對稱加密不同的是,銀行不需要將私鑰通過網絡發送出去,因此安全性大大提高。

跟對稱密鑰相比,非對稱密鑰提供的安全級別更高,付出的代價是消耗的資源更多。我們建議開發者避免使用非對稱密鑰對大量的數據進行加密和解密操作,推薦的做法是:對數據進行壓縮,使用對稱密鑰來加密壓縮之後的數據,由於對稱密鑰可能在數據傳遞過程中被竊取和破譯,因此,推薦使用非對稱密鑰來保護對稱密鑰。

舉個例子,發送方把對稱加密的密鑰使用非對稱加密的公鑰進行加密,發送出去;接收方使用私鑰進行解密得到對稱加密的密鑰,這樣,雙方使用對稱加密來進行溝通。

ENCRYPTBYASYMKEY()函數使用非對稱密鑰來加密數據,該函數加密的數據字節長度是有限度的,根據算法的不同,加密的長度限制不同:

  • 對於RSA_512算法,最多加密53bytes;
  • 對於RSA_1024算法,最多加密117bytes;
  • 對於RSA_2048算法,最多加密245bytes;

在SQL Server中,證書和非對稱密鑰都使用RSA密鑰,是RSA密鑰的包裝(wrapper)。

非對稱密鑰是數據庫級別的安全實體。 默認情況下,該實體同時包含公共密鑰和私有密鑰。默認情況下,私鑰受數據庫主密鑰保護。 如果尚未創建數據庫主密鑰,則需要密碼來保護私鑰。

一,創建非對稱密鑰

非對稱密鑰可以通過文件來導入,也可以在SQL Server中創建。

CREATE ASYMMETRIC KEY asym_key_name    
   [ FROM FILE = 'path_to_strong-name_file'   ]  
   [ WITH ALGORITHM = <algorithm>  ] 
   [ ENCRYPTION BY PASSWORD = 'password' ] 
  
<algorithm> ::=  
      { RSA_4096 | RSA_3072 | RSA_2048 | RSA_1024 | RSA_512 }   
     

參數註釋:

FROM FILE = ‘path_to_strong-name_file’:從文件導入已有的密鑰對,或從程序集或DLL文件導入公共密鑰。

在不使用FROM子句的情況下執行時,CREATE ASYMMETRIC KEY會生成一個新的密鑰對。加密的算法,推薦使用RSA_4096、RSA_3072和RSA_2048,而RSA_1024 和 RSA_512已經過時了。

對於新建的非對稱密鑰,可以使用密碼來保護私鑰,這需要在ENCRYPTION BY PASSWORD = ‘password’ 設置,如果省略該子句,那麼使用數據庫主密鑰來保護私鑰。

舉個例子,創建一個新的非對稱密鑰,使用密碼保護密鑰:

CREATE ASYMMETRIC KEY PacificSales09   
    WITH ALGORITHM = RSA_2048   
    ENCRYPTION BY PASSWORD = '<enterStrongPasswordHere>';   
GO  

二,修改非對稱密鑰

修改非對稱密鑰,可以移除密鑰的私鑰,也可以修改保護私鑰的密碼。修改非對稱密鑰的語法如下:

ALTER ASYMMETRIC KEY Asym_Key_Name <alter_option>  
 
<alter_option> ::=  
      <password_change_option>   
    | REMOVE PRIVATE KEY   

<password_change_option> ::=  
    WITH PRIVATE KEY ( <password_option> [ , <password_option> ] )  

<password_option> ::=  
      ENCRYPTION BY PASSWORD = 'strongPassword'  
    | DECRYPTION BY PASSWORD = 'oldPassword'

參數註釋:

  • REMOVE PRIVATE KEY:移除私鑰,但是保留公鑰
  • ENCRYPTION BY PASSWORD =’strongPassword‘: 用於指定一個新的密鑰來保護私鑰
  • DECRYPTION BY PASSWORD =’oldPassword‘:用於指定解密私鑰的舊密碼,如果私鑰被DMK保護,那麼不需要改子句。

舉個例子,修改保護私鑰的密碼:

ALTER ASYMMETRIC KEY PacificSales09   
    WITH PRIVATE KEY (  
    DECRYPTION BY PASSWORD = '<oldPassword>',  
    ENCRYPTION BY PASSWORD = '<enterStrongPasswordHere>');  
GO

三,使用非對稱密鑰來加密和解密數據

用非對稱密鑰來加密和解密數據,需要用到以下函數:

ASYMKEY_ID ( 'Asym_Key_Name' )  
EncryptByAsymKey ( Asym_Key_ID , { 'plaintext' | @plaintext } ) 
DecryptByAsymKey (Asym_Key_ID , { 'ciphertext' | @ciphertext } [ , 'Asym_Key_Password' ] )   

在解密數據時,如果私鑰是用密碼來保護的,需要提供密碼(設置參數’Asym_Key_Password’)來解密,如果密鑰是用DMK來解密的,那麼不需要提供解密私鑰的密碼。

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

示例1,用非對稱密鑰來加密:

EncryptByAsymKey(AsymKey_ID('JanainaAsymKey02'), @cleartext)

示例2,用非對稱密鑰來解密,密鑰用密碼來解密。

 DecryptByAsymKey( AsymKey_Id('JanainaAsymKey02'), CipherData, N'pGFD4bb925DGvbd2439587y' )

四,舉個例子

雖然非對稱加密很安全,但是和對稱加密比起來,它非常的慢,所以我們還是要用對稱加密來傳送消息,但對稱加密所使用的密鑰我們可以通過非對稱加密的方式發送出去。為了解釋這個過程,請看下面的例子:

(1) Alice需要在銀行的網站做一筆交易,她的瀏覽器首先生成了一個隨機數作為對稱密鑰。

(2) Alice的瀏覽器向銀行的網站請求公鑰。

(3) 銀行將公鑰發送給Alice。

(4) Alice的瀏覽器使用銀行的公鑰將自己的對稱密鑰加密。

(5) Alice的瀏覽器將加密后的對稱密鑰發送給銀行。

(6) 銀行使用私鑰解密得到Alice瀏覽器的對稱密鑰。

(7) Alice與銀行可以使用對稱密鑰來對溝通的內容進行加密與解密了。

 

 

 

參考文檔:

CREATE ASYMMETRIC KEY (Transact-SQL)

ENCRYPTBYASYMKEY (Transact-SQL)

DECRYPTBYASYMKEY (Transact-SQL)

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

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

月收入5000也能買車 經濟實惠的家用車買這些夠用了!_如何寫文案

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

內飾是長安家族式的設計,風格更加年輕時尚,雙炮台式的儀錶盤非常經典,無鑰匙進入/啟動、ESp、上坡輔助、倒車影像等配置應有盡有。逸動的軸距達到2660mm,空間上面令人滿意,較寬的車身寬度也很好的提升了乘坐舒適性。

一汽奔騰-奔騰B30

指導價:6.98-9.28萬

奔騰B30的誕生無非就是為了細分市場的興起,是一款定位緊湊型車的入門級產品,前兩設計非常的個性誇張,偏向於年輕運動化的設計風格,飄逸的腰線很有特點;內飾看起來很規整,實用為主,沒有太多花哨的地方,胎壓監測、上坡輔助、定速巡航、倒車影像等配置比較齊全;2630mm軸距帶來的空間感受還是蠻寬敞的,儲物空間設計也比較到位,中控台底部空間和杯架深度合理,滿足家用需求;1.6L發動機技術成熟,最大功率109馬力,搭配5擋手動或者6擋手自一體變速箱,日常駕駛很順暢,

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

底盤整體感強。

優惠:購置稅全免,尊享1年0零利率分期禮遇,尊享置換補貼3000元

長安汽車-逸動

指導價:8.09-24.99萬

無可否認,長安造車非常符合國人的審美要求,逸動外觀沒有過多花哨的地方,整車線條流暢優雅,門把手與其腰線有機的融合成一體,簡潔耐看,5幅式雙色輪圈視覺效果不錯;內飾是長安家族式的設計,風格更加年輕時尚,雙炮台式的儀錶盤非常經典,無鑰匙進入/啟動、ESp、上坡輔助、倒車影像等配置應有盡有;逸動的軸距達到2660mm,空間上面令人滿意,較寬的車身寬度也很好的提升了乘坐舒適性;動力系統上採用了有缸內直噴技術的1.6L發動機,最大功率128馬力,搭配5擋手動變速箱,在頭段和中段加速時動力很充足,在市區行駛來說游刃有餘,是一輛質優價廉的好車。

優惠:現金優惠5千元左右,享購置稅減半政策優本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

哥倫比亞砍伐森林 面積相當一個聖保羅_如何寫文案

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

摘錄自2020年7月10日中央廣播電台報導

根據9日公佈的官方報告指出,哥倫比亞2019年砍伐了15萬9千公頃的森林,面積相當於巴西大城聖保羅(Sao Paulo)。儘管如此,相較於2018年遭砍伐的19萬7千公頃,這代表在森林砍伐上減少了19%,而2017年的砍伐面積更高達21萬9千公頃。

哥倫比亞環境與永續發展副部長賈西亞(Maria Claudia Garcia)表示,「我們已設法控制森林砍伐的上升趨勢。」「這項結果顯示大有可為,但這並不是一個勝利的訊息。」

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

約有62%的森林砍伐發生在「地球之肺」亞馬遜(Amazon)雨林。造成森林損失的主因在於農田增加、非法砍伐原木、開礦、以及毒品農場。根據聯合國2019年的估算,毒品種植面積達到15萬4千公頃。

生物多樣性
國際新聞
哥倫比亞
亞馬遜
森林砍伐
森林

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

Microsoft 365 還是 Google Workspace?一文看懂企業生產力工具選哪套_如何寫文案

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

不管是微軟或是 Google,都在積極推動以雲端為基礎的生產力軟體與服務套裝工具,希望能夠幫助用戶在激烈的競爭中贏得勝利,而兩家巨頭所推出的解決方案就是 Microsoft 365 與 Google Workspace(以前的 G Suite),這次「一文看懂」就要來帶大家仔細看看這兩套不同生產力工具之間差異與不同。

Microsoft 365 還是 Google Workspace?一文看懂企業生產力工具選哪套

微軟與 Google 都想成為用戶首選的一站式生產力工具服務,各自推出的訂閱商品也擁有各自的特色。Microsoft 365 與 Google Workshop 這兩套不同工具都具備有下面這些功能:

  • 可自訂域名的工作用電子郵件信箱和共用行事曆功能
  • 擁有線上儲存、協作的共用空間,而且每個使用者帳號都分配有大量個人儲存空間
  • 可用於建立和協作文件、表格和簡報的生產力應用程式
  • 都有自家企業通信軟體,裡面都有傳訊、線上會議和視訊會議功能
  • 管理介面具備企業用戶的合規性與歸檔等高階功能以及包含雙重身份驗證等在內的安全功能

這兩巨頭的服務皆以強大、可靠性高的雲端基礎架構為核心,並擁有自家的全球數據中心,且兩家企業在生產力工具市場皆佔據了主導地位,其他小型競爭對手根本沒得打。儘管表面上看起來功能性差不多,但 Microsoft 與 Google Workshop 在雲端結構和應用程式的設計方面明顯採取不同的邏輯與方式,對大多數人來說,選擇使用哪一款的最直接方式就是從硬體合適度來著手。

微軟的方式在於構築自家的 Office 專有權(過去稱為 Office 365,現在叫 Microsoft 365),所包含的應用程式皆為可自動更新的同捆之中,點對點服務(包括 Exchange Online、OneDrive Business、SharePoint Online 和 Microsoft Teams)讓團隊從本地伺服器遷移到雲端提供了簡易途徑,員工可以利用熟悉的電腦版應用來造訪包含 Outlook、Word、Excel 和 PowerPoint 等服務,也可以使用網頁版的替代方案。相比之下,Google 的方式是以雲端原生工具和瀏覽器為中心,包含 Gmail、Google 雲端硬碟、Google 文件和 Google 試算表等基於網頁服務與員工已經熟悉的個人工具相同,當與 Chrome 瀏覽器一起使用時,這些應用程式可支援離線儲存文件與檔案。

這兩種服務都內含專為中型與大型企業設計的網頁版本管理介面,而這些管理工具對於沒有全職 IT 工程師的小型企業中可能會讓人感到棘手。如果是企業採購相關方案,還是與認證經銷合作會是最好的選擇,後續服務方面也較為完善。

套裝價格

若要看到 Microsoft 365 與 Google Workshop 的明顯差異,可以從兩家廠商提供訂閱的各項計劃內容來看。
Google 保有其簡單明瞭的概念,共推出有四種不同的方案,分別為入門型的 Business Starter(每月 6 美元)、標準型的 Business Standard(每月 12 美元)、進階型的 Business Plus(每月 18 美元) 與企業大量授權型的 Enterprise(需另外詢價)。

相形之下,Microsoft 365 的方案就讓人較為眼花撩亂。三種針對小型企業的訂閱記劃(Microsoft 365 E3、E5 與 F3),以及僅包含有電腦應用和雲端儲存的 Microsoft 365 APPS 企業版,另外還沒有重新命名的 Office 365 E1、E3 與 E5 企業方案,還有專為大型組織從每台電腦授權和本地伺服器過渡的方案,另外對於教育機構、政府機關和非營利組織還有單獨的 Microsoft 365 計劃。Microsoft 365 的收費從每人每月 300 元至 1040 元不等,最貴的方案包含了 Windows 10 企業版 E3 和企業行動性 + 安全 E3 的許可。如果上面這些方案都不適合你的需求,你還可以混合搭配各種服務以建立個人化的訂閱方案。

兩種服務之間儘管有些相似之處,但很難進行一項一項的比較,由於內含 Office 桌面應用,大多數 Microsoft 365 計劃的費用都高於 Google Workspace。

Google 所有方案皆包含下面的功能:
Gmail for Business
Meet(視訊與語音會議)
Chat(安全訊息)
共用行事曆
Google 文件、試算表和簡報
Keep(共用筆記)
表單(可製作問券)
協作平台(Sites,可在沒有程式基礎下快速建立協作平台)
Currents(Google Workshop 中的 Google+ 替代品)
至少 30GB 的雲端儲存容量(Google 雲端硬碟)
安全和行政控制

而所有 Microsoft 365 計劃都內含一組雲端功能,或有權在最多 15 部裝置上下載安裝 Office 應用程式(5 台 Windows 電腦或 Mac、5 台平板電腦和 5 部智慧型手機),或是兩者皆有。電腦版應用程式包括 Outlook、Word、Excel、PowerPoint 和 OneNote(僅在 Windows 電腦上提供訪問和創建),以及每個使用者至少 1TB 的 OneDrive 儲存容量,與網頁版本的 Word、Excel、PowerPoint 和 OneNote。

Microsoft 365 的雲端服務包含下面這些:
Exchange 最大收件匣容量為 50 或 100GB 的線上電子郵件託管
網頁版 Word、Excel、PowerPoint 和 Outlook
每個使用者至少 1TB 的 OneDrive 用於業務檔案存儲
SharePoint 線上團隊網站
高解析視訊會議
線上會議(Skype 會議廣播或 Microsoft Teams 即時活動)
安全訊息傳遞和協作(Microsoft Teams)
安全和行政控制

商務計劃還包含有約會計劃應用、Microsoft Bookings 和 MileIQ 費用追蹤軟體。而企業計劃則包含有任務管理軟體 Microsoft Planner、高級分析工具的MyAnalytics 和 Power BI Pro、流程管理工具 Power Apps 與 Power Automate、協作軟體 Yammer 以及眾多進階功能,像是 Microsoft Advanced Threat Protection、Microsoft Bookings 等功能,以及 150 或更多人員的免費部屬支援。

兩者間的比較

Microsoft 365 與 Google Workspace 都有讓人印象深刻的眾多功能清單,事實上兩種服務之間最大的區別不是特定功能是否存在,而是如何實現這些功能,總結是指兩個服務之間的風格差異。

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

  • 電子郵件
    Microsoft 具有 Exchange Online,針對 Outlook 電腦版進行了最佳化;Google 的 Gmail 服務,針對 Chrome 瀏覽器和行動應用進行了最佳化。除了這些基本的體系結構差異外,功能項目裡面還包括企業電子郵件管理員想要的所有內容,包括反惡意軟體防護、垃圾郵件過濾和群組別名。

    Google Workspace 的 Business Starter 方案中,最大收件匣容量為 30GB(或更少),該空間與使用者的雲端硬碟儲存容量共用。此限制隨著 Google Workspace 更高階的訂閱方案而消失。Microsoft  365 電子郵件信箱大小上限為 50GB 或 100GB,具體取決於選購的計劃,對於啟用存檔的企業帳戶,存檔郵箱容量則為無限制。

  • 生產力應用
    Google 的旗艦生產力應用專為在瀏覽緝獲行動應用中工作而設計,相比之下較為主流的 Microsoft 365 方案中還包含了 Windows PC 和 Mac 上最新版本 Office 桌面應用軟體,此外還有功能日益完整的網頁版核心應用。

    這些 Office 桌面應用可用性是某些組織或企業的必須項目,當 Office 文件格式的保真度至關重要時,情況尤其如此。導入和匯出 Google 文件和表格很容易,但 Office 文件卻不能保證在兩個環境之間無損往來。在這些格式沒什麼大不了的,而且在相對成員較為年輕化的團體在 Gmail 和 Google 文件的使用較為順手,瀏覽器介面或許可以被視為一種優勢。

  • 雲端儲存
    OneDrive for Business 曾是 SharePoint 的笨重副產品,現在與消費者共用相同的同步引擎,已經發展成與 Microsoft 365 和 Windows 能有高整合度的可靠服務,它在 Mac 和行動裝置運行狀況也不錯。預設情況下,每個 OneDrive for Business 用戶都會獲得 1TB 的個人雲端空間,只要企業帳戶有至少五位用戶這個上限就消失了。對於所有帳戶類型,團隊可獲取 SharePoint  1TB 儲存容量(再加上每個使用者 10GB)。

    如前面提過的,Google 雲端硬碟儲存分配與 Gmail 共用。在基本帳戶上,上限為 30GB,升級帳戶的限制將限制為 1TB,對於至少有五個使用者的 Google Workspace 商務和企業計劃則為無上限。管理員可以使用設備策略控制離線儲存,並可以控管使用者是否可以將雲端檔案同步到電腦或行動裝置中。

  • 溝通與協作
    無論是 Google Workspace 或 Microsoft 365,都提供用戶各種通訊和協作工具。這兩種服務都允許用戶在網頁瀏覽器上同時編輯文件,以便團隊處理共享專案;對於儲存在 OneDrive 上的檔案,你也可以使用 Office 電腦版應用進行協作。

    Google 已經將旗下的原本的 Hangouts 聊天應用程式改名為 Meet,可用於進行線上會議、視訊會議和語音通話,也能簡單地傳送文字訊息對話;Microsoft 365 則透過 Microsoft Teams 取代 Skype 商務版和古老的 Lyc 來提供同樣的功能。

Google Workspace 或 Microsoft 365,不管哪一套工具,在現在工作型態轉為遠端的時局下,都以提供無縫的團隊協作與即時溝通為主要重點,打破不在一地工作時距離與時間帶來的障礙,讓企業與商務生產力保有往常的水準。

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

一篇文章帶你快速弄清楚什麼是終端_網頁設計

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

Linux的使用者可能每天都會接觸到 Bash、Shell、控制台、終端。它們之間有什麼不同嗎?本文為你快速解釋這些概念以及它們的區別。

  

什麼是終端

 

首先我們來弄清楚什麼是終端(terminal)。按照百度百科的解釋是:“經由通信設施向計算機輸入程序和數據或接收計算機輸出處理結果的設備。” 聽起來似乎有點晦澀,其實用台式PC機來舉例就很容易理解了。一台台式機是由主機(機箱)和很多外圍設備組成的。主機裡邊包括主板、CPU、內存、硬盤、和其他芯片等等。外圍設備包括显示器、鼠標、鍵盤、耳機、麥克風、和攝像頭等等。這些外圍設備就被稱為終端,負責向主機輸入數據的就叫輸入終端,比如鼠標、鍵盤、麥克風、攝像頭,負責接收主機輸出數據的設備就被稱作輸出終端,比如显示器、耳機。

 

 

所以有兩個概念我們這裏就清楚了:

計算機 = 主機 + 終端

終端 = 輸入終端 + 輸出終端

  

終端的類型

 

終端,除了可以分為輸入終端與輸出終端外,還可以按照與主機的距離可以本地終端和遠程終端,或者按照與主機的連接方式分成物理終端和虛擬終端。

 

舉個例子,比如我們在杭州的某個機房裡有一台服務器,用VGA線接了一台显示器,用USB連接了鍵盤,那麼這台显示器和這個鍵盤就是服務器的本地終端。假如我們在隔壁機房用串口線又接了一個显示器和鍵盤,那它們就可以稱為遠程終端。不管是在本地機房還是隔壁機房,因為這幾個終端和服務器都是通過物理設備直接連接的,所以它們都被稱為物理終端。物理終端在 Linux中被標識為 tty。它是teletype的縮寫,因為在計算機早期的時候,Ken Thompson 和 Dennis Ritchie用電傳打印機作為他們  Unix 服務器的終端(參考《Linux,Unix,GNU 到底有什麼樣的淵源?》),所以這個名字就這樣被沿用了下來。

 

假如我們在上海的家裡通過 ssh 遠程登陸杭州的服務器,那麼我們在家中用的設備就是服務器的遠程終端,也是一個虛擬終端(因為沒有與服務器在本地用物理設備連接)。虛擬終端在 Linux 中用 pts (pseudo termial slave)來標識。用 who 命令可以查看當前登陸系統的用戶,以及他們所使用的終端類型。

 

 

什麼是控制台

 

控制台(console)與終端現在已經幾乎表示同一個意思了,但是在計算機發展的早期它們還是有本質區別的。最初,大型計算機(可能有幾間屋子那麼大)只有一個終端,被稱為”控制台“,而它真的是一個控制台,就像下面這張圖這樣,有很多的儀錶和開關,技術人員就是通過它來對計算機發出指令。那個時候計算機雖然很大,但每次只能有一個人來操作,並且一次也只能運行一個程序。後來Ken Thompson 和 Dennis Ritchie發明了Unix,於是操作系統可以同時運行多個程序,並且支持多個用戶同時登陸。這樣一來,僅有一個控制台就顯得不夠了。因為控制台又很貴,所以 Ken Thompson 和 Dennis Ritchie就用了相對便宜的電傳打字機作為新增加的終端連接到他們的計算機上。雖然一台計算機可以連接很多個終端,但這裏邊只能有一個控制台,並且控制台的權限要遠大於其他的終端,比如當系統發生啟動錯誤時,只有控制台會显示錯誤消息,而其他終端不會;或者當系統進入單用戶登陸模式時,只有通過控制台才能進行登陸,而通過其他終端沒有辦法登陸。所以如果用一句話來總結控制台與終端的區別,可以說控制台是計算機最早的以及權限最大的一個終端。

 

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

  

什麼是 Shell 和 Bash

 

終端和主機雖然連接起來了,但是計算機還是需要一個程序才能明白我們輸入的命令,這個程序就是 Shell。我們的命令就是通過終端輸入到 Shell 里,再由 Shell 轉換成計算機明白的指令,然後計算機才能運行。

 Shell 有很多種,我們最常用的是 Bash,另外還有Csh, Ksh, Zsh等等。對於Bash,Linux的用戶應該每天都在使用,這裏就不再展開介紹了。

  

最後

 

控制台、終端、Shell、Bash 這些名詞經常被大家混淆,雖然今天在很多場合它們經常被替換使用,大家也都明白,不過希望通過本文大家可以弄清楚它們之間的區別和聯繫。

 

 

推薦閱讀:

《一篇文章看清楚 Linux 的職業發展方向》

《2020年你最需要掌握的11種編程語言》

《微軟:懸賞10萬美金破解 Linux 系統》

《安卓到底是不是Linux》

《在 Linux 系統中如何管理 systemd 服務》

《Linux的運行級別與目標》

《軟鏈接 vs. 硬鏈接》

 

 

 

歡迎大家關注我的微信公眾號,獲取知識乾貨、增加面試經驗、了解程序人生。
回復【面試】,獲取技術大廠面試寶典

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

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

SpringBoot整合Flyway(數據庫版本遷移工具)_台中搬家公司

※推薦台中搬家公司優質服務,可到府估價

台中搬鋼琴,台中金庫搬運,中部廢棄物處理,南投縣搬家公司,好幫手搬家,西屯區搬家

簡介

在團隊開發當中,有可能每個人都是使用自己本地的數據庫。當數據庫的表或者字段更新時,往往需要告知團隊的其他同事進行更新。
Flyway數據庫版本遷移工具,目的就是解決該問題而誕生的(我自己想的)。每當我們更新數據庫的時候,只需要添加SQL文件到指定目錄中。Flyway會在數據庫創建一個表,專門記錄已更新的SQL文件。當我們下次執行時則不會執行已記錄並且執行成功的SQL文件。

整合

maven

現在的Flyway的最新版本已經到了6.4.2。我用的是6.3.3

<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>6.3.3</version>
</dependency>

application配置

搞定了Flyway的依賴后,修改一下SpringBoot的application.ymlapplication.xml配置。

spring:
  flyway:
    url: jdbc:mysql://192.168.138.132:3306/hotel-server?useUnicode=true&characterEncoding=UTF-8 
    user: johnson 
    password: 123456 
    table: flyway_schema_history
    enabled: true
    locations: classpath:db/migration
    clean-disabled: false

flyway配置詳解

url:連接數據庫的Url 默認為spring.datasource.url
user:連接數據庫的賬號 默認為spring.datasource.username
password:連接數據庫的密碼 默認為spring.datasource.password
table:自定義數據庫版本管理表 默認為 flyway_schema_history
enabled:是否開啟 默認為開啟
locations:SQL文件存放路徑 默認 classpath:db/migration

SQL文件

上面的locations參數配置的SQL文件存放路徑為 classpath:db/migrationclasspath對應的目錄就是resources目錄,創建后的目錄如下圖:

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

還在煩惱搬家費用要多少哪?台中大展搬家線上試算搬家費用,從此不再擔心「物品怎麼計費」、「多少車才能裝完」

SQL文件如上圖,SQL文件名必須為V1.0.x__xxx.sql注意:這裏的下劃線為兩個_,我也是掉坑了才知道),這樣可以對應SQL更新的版本號。啟動了SpringBoot項目后,就會自動幫你執行SQL文件,可以看到數據庫版本控製表中生成的數據:

clean操作

Flyway的clean操作:徹底清除已配置的架構,它將有效地為您提供一個全新的起點。所有對象(表,視圖,過程等)都將被刪除。

spring:
  flyway:
    clean-on-validation-error: true
    clean-disabled: false

clean-on-validation-error:發生驗證的錯誤時是否執行clean操作(如SQL執行失敗),默認false,生產中必須使用false。
clean-disabled:是否禁用clean操作,默認false,生產中必須使用true

如果我們設置 clean-on-validation-error = trueclean-disabled = false
當我們的SQL文件執行失敗,在數據庫版本控製表flyway_schema_history會添加一條失敗的記錄,success字段為0,此時並不會執行clean操作。
當把SQL文件修改正確並執行完后,此時flyway_schema_history會把失敗記錄的success字段由0改為1。並且會執行clean操作!!!!!整個數據庫的表裡面的數據都被清空了!(除非你在SQL文件中添加了insert操作)
其實在開發環境我也是不建議使用clean,畢竟填數據也是要時間的。。。

總結

團隊開發當中的必備工具啊!不過生產環境當中記得把clean-disabled改為true

個人博客網址: https://colablog.cn/

如果我的文章幫助到您,可以關注我的微信公眾號,第一時間分享文章給您

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

※推薦台中搬家公司優質服務,可到府估價

台中搬鋼琴,台中金庫搬運,中部廢棄物處理,南投縣搬家公司,好幫手搬家,西屯區搬家

QTI EAS學習之find_energy_efficient_cpu_如何寫文案

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

Energy Awareness Scheduler是由ARM和Linaro開發的新的linux kernel調度器。

原先CFS調度器是基於policy進行調度,並有不同的吞吐量。例如,有一個新的task創建,同時也有一個idle cpu時,CFS始終會把新的task放到這個idle cpu上運行。但是,這樣對節省功耗來說,並不是一個最好的決定。而EAS就是為了解決這樣的問題。在不影響性能的前提下,EAS會在調度時實現節省功耗。

從SDM845開始,QTI在EAS基礎上進行了一些修改,以滿足移動市場的需要。所以QTI在EAS基礎上添加了一些feature,來獲得更好的性能和功耗。

Energy model

 在dts中,針對不同的cpu平台,已定義好不同的energy model。模型主要是由【頻率,能量】的數組構成,對應了CPU和cluster不同的OOP(Operating Performance Point);同時也提供了不同idle state的能量消耗:idle cost。

CPU0: cpu@0 {
            device_type = "cpu";
            compatible = "arm,armv8";
            reg = <0x0 0x0>;
            enable-method = "psci";
            efficiency = <1024>;
            cache-size = <0x8000>;
            cpu-release-addr = <0x0 0x90000000>;
            qcom,lmh-dcvs = <&lmh_dcvs0>;
            #cooling-cells = <2>;
            next-level-cache = <&L2_0>;
            sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;  //小核都用CPU_COST_0 CLUSTER_COST_0
 。。。。。。
        CPU4: cpu@400 {
            device_type = "cpu";
            compatible = "arm,armv8";
            reg = <0x0 0x400>;
            enable-method = "psci";
            efficiency = <1740>;
            cache-size = <0x20000>;
            cpu-release-addr = <0x0 0x90000000>;
            qcom,lmh-dcvs = <&lmh_dcvs1>;
            #cooling-cells = <2>;
            next-level-cache = <&L2_400>;
            sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;  //大核都用CPU_COST_1 CLUSTER_COST_1
。。。。。。。

對應的數組如下,

    energy_costs: energy-costs {
        compatible = "sched-energy";

        CPU_COST_0: core-cost0 {
            busy-cost-data = <
                 300000   31
                 422400   38
                 499200   42
                 576000   46
                 652800   51
                 748800   58
                 825600   64
                 902400   70
                 979200   76
                1056000   83
                1132800   90
                1209600   97
                1286400  105
                1363200  114
                1440000  124
                1516800  136
                1593600  152
                1651200  167 /* speedbin 0,1 */
                1670400  173 /* speedbin 2 */
                1708800  186 /* speedbin 0,1 */
                1747200  201 /* speedbin 2 */
            >;
            idle-cost-data = <
                22 18 14 12
            >;
        };
        CPU_COST_1: core-cost1 {
            busy-cost-data = <
                300000   258
                422400   260
                499200   261
                576000   263
                652800   267
                729600   272
                806400   280
                883200   291
                960000   305
                   1036800   324
                   1113600   348
                   1190400   378
                   1267200   415
                   1344000   460
                   1420800   513
                   1497600   576
                   1574400   649
                   1651200   732
                   1728000   824
                   1804800   923
                   1881600  1027
                   1958400  1131
                   2035000  1228 /* speedbin 1,2 */
                   2092000  1290 /* speedbin 1 */
                   2112000  1308 /* speedbin 2 */
                   2208000  1363 /* speedbin 2 */
            >;
            idle-cost-data = <
                100 80 60 40
            >;
        };
        CLUSTER_COST_0: cluster-cost0 {
            busy-cost-data = <
                 300000   3
                 422400   4
                 499200   4
                 576000   4
                 652800   5
                 748800   5
                 825600   6
                 902400   7
                 979200   7
                1056000   8
                1132800   9
                1209600   9
                1286400  10
                1363200  11
                1440000  12
                1516800  13
                1593600  15
                1651200  17 /* speedbin 0,1 */
                1670400  19 /* speedbin 2 */
                1708800  21 /* speedbin 0,1 */
                1747200  23 /* speedbin 2 */
            >;
            idle-cost-data = <
                4 3 2 1
            >;
        };
        CLUSTER_COST_1: cluster-cost1 {
            busy-cost-data = <
                300000  24
                422400  24
                499200  25
                576000  25
                652800  26
                729600  27
                806400  28
                883200  29
                960000  30
                   1036800  32
                   1113600  34
                   1190400  37
                   1267200  40
                   1344000  45
                   1420800  50
                   1497600  57
                   1574400  64
                   1651200  74
                   1728000  84
                   1804800  96
                   1881600 106
                   1958400 113
                   2035000 120 /* speedbin 1,2 */
                   2092000 125 /* speedbin 1 */
                   2112000 127 /* speedbin 2 */
                   2208000 130 /* speedbin 2 */
            >;
            idle-cost-data = <
                4 3 2 1
            >;
        };
    }; /* energy-costs */

在代碼kernel/sched/energy.c中遍歷所有cpu,並讀取dts中的數據

    for_each_possible_cpu(cpu) {
        cn = of_get_cpu_node(cpu, NULL);
        if (!cn) {
            pr_warn("CPU device node missing for CPU %d\n", cpu);
            return;
        }

        if (!of_find_property(cn, "sched-energy-costs", NULL)) {
            pr_warn("CPU device node has no sched-energy-costs\n");
            return;
        }

        for_each_possible_sd_level(sd_level) {
            cp = of_parse_phandle(cn, "sched-energy-costs", sd_level);
            if (!cp)
                break;

            prop = of_find_property(cp, "busy-cost-data", NULL);
            if (!prop || !prop->value) {
                pr_warn("No busy-cost data, skipping sched_energy init\n");
                goto out;
            }

            sge = kcalloc(1, sizeof(struct sched_group_energy),
                      GFP_NOWAIT);
            if (!sge)
                goto out;

            nstates = (prop->length / sizeof(u32)) / 2;
            cap_states = kcalloc(nstates,
                         sizeof(struct capacity_state),
                         GFP_NOWAIT);
            if (!cap_states) {
                kfree(sge);
                goto out;
            }

            for (i = 0, val = prop->value; i < nstates; i++) {    //將讀取的[freq,energy]數組存放起來
                cap_states[i].cap = SCHED_CAPACITY_SCALE;
                cap_states[i].frequency = be32_to_cpup(val++);
                cap_states[i].power = be32_to_cpup(val++);
            }

            sge->nr_cap_states = nstates;      //state為[freq,energy]組合個數,就是支持多少個狀態:將所有數據flatten之後,再處以2
            sge->cap_states = cap_states;

            prop = of_find_property(cp, "idle-cost-data", NULL);
            if (!prop || !prop->value) {
                pr_warn("No idle-cost data, skipping sched_energy init\n");
                kfree(sge);
                kfree(cap_states);
                goto out;
            }

            nstates = (prop->length / sizeof(u32));
            idle_states = kcalloc(nstates,
                          sizeof(struct idle_state),
                          GFP_NOWAIT);
            if (!idle_states) {
                kfree(sge);
                kfree(cap_states);
                goto out;
            }

            for (i = 0, val = prop->value; i < nstates; i++)
                idle_states[i].power = be32_to_cpup(val++);    //將讀取的idle cost data存放起來

            sge->nr_idle_states = nstates;        //idle state的個數,就是idle cost data的長度
            sge->idle_states = idle_states;

            sge_array[cpu][sd_level] = sge;      //將當前cpu獲取的energy模型存放再sge_array[cpu][sd_level]中。其中cpu就是對應哪個cpu,sd_level則對應是哪個sched_domain,也就是是cpu level還是cluster level
        }
    }

Load Tracking

QTI EAS使用的負載計算是WALT,是基於時間窗口的load統計方法,具體參考之前文章:https://www.cnblogs.com/lingjiajun/p/12317090.html

其中會跟蹤計算出2個比較關鍵的數據,就是task_util和cpu_util 

當執行wakeup task placement,scheduler就會使用task utilization和CPU utilization

可以理解為將load的情況轉化為Utilization,並且將其標準化為1024的值。

task_util = demand *1024 / window_size

    = (delta / window_size) * (cur_freq / max_freq) * cpu_max_capacity

—–delta是task在一個window中運行的真實時間;window_size默認是20ms;

   cur_freq為cpu當前頻率;max_freq為cpu最大頻率;

Task utilization boosted = Task utilization + (1024-task_util) x boost_percent —–boost percent是使用schedtune boost時,所需要乘上的百分比

CPU utilization = 1024 x (累計的runnable均值 / window size)——–累計的runnable均值,個人理解就是rq上所有task util的總和

 

Task placement的主要概念:

EAS是Task placement 是EAS影響調度的主要模塊。 其主要keypoint如下:

1、EAS依靠energy model來進行精確地進行選擇CPU運行

2、使用energy model估算:把一個任務安排在一個CPU上,或者將任務從一個CPU遷移到另一個CPU上,所發生的能量變化

3、EAS會在不影響performance情況下(比如滿足滿足最低的latency),趨向於選擇消耗能量最小的CPU,去運行當前的task

4、EAS僅發生在system沒有overutilized的情況下

5、EAS的概念與QTI EAS的一樣

6、一旦系統處於overutilized,QTI EAS仍然在wake up的path下進行energy aware。不會考慮系統overutilized的情形。

補充:

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

overutilization,一個cpu_util大於cpu capacity的95%(sched_capacity_margin_up[cpu]),那麼就認為這個cpu處於overutilization。並且整個系統也被認為overutilizaion。

 

EAS核心調度算法

不同版本的EAS在不同版本下的主要task placement實現函數(針對CFS task):

Zone scheduler: select_best_cpu()
QTI EAS r1.2: energy_aware_wake_cpu()
QTI EAS r1.5: find_energy_efficienct_cpu()

 

task placement調用路徑:

QTI EAS r1.5 (Kernel 4.14)

Task wake-up: try_to_wake_up() →select_task_rq_fair() →invokes find_energy_efficient_cpu()

Scheduler tick occurs: scheduler_tick() →check_for_migration() →invokes find_energy_efficient_cpu()

New task arrives: do_fork() →wake_up_new_task() →select_task_rq_fair() →invokes find_energy_efficient_cpu()

 

EAS的task placement代碼流程,主要目標是找到一個合適的cpu來運行當前這個task p。

主要代碼就是find_energy_efficient_cpu()這個函數裏面,如下:

  1 /*
  2  * find_energy_efficient_cpu(): Find most energy-efficient target CPU for the
  3  * waking task. find_energy_efficient_cpu() looks for the CPU with maximum
  4  * spare capacity in each performance domain and uses it as a potential
  5  * candidate to execute the task. Then, it uses the Energy Model to figure
  6  * out which of the CPU candidates is the most energy-efficient.
  7  *
  8  * The rationale for this heuristic is as follows. In a performance domain,
  9  * all the most energy efficient CPU candidates (according to the Energy
 10  * Model) are those for which we'll request a low frequency. When there are
 11  * several CPUs for which the frequency request will be the same, we don't
 12  * have enough data to break the tie between them, because the Energy Model
 13  * only includes active power costs. With this model, if we assume that
 14  * frequency requests follow utilization (e.g. using schedutil), the CPU with
 15  * the maximum spare capacity in a performance domain is guaranteed to be among
 16  * the best candidates of the performance domain.
 17  *
 18  * In practice, it could be preferable from an energy standpoint to pack
 19  * small tasks on a CPU in order to let other CPUs go in deeper idle states,
 20  * but that could also hurt our chances to go cluster idle, and we have no
 21  * ways to tell with the current Energy Model if this is actually a good
 22  * idea or not. So, find_energy_efficient_cpu() basically favors
 23  * cluster-packing, and spreading inside a cluster. That should at least be
 24  * a good thing for latency, and this is consistent with the idea that most
 25  * of the energy savings of EAS come from the asymmetry of the system, and
 26  * not so much from breaking the tie between identical CPUs. That's also the
 27  * reason why EAS is enabled in the topology code only for systems where
 28  * SD_ASYM_CPUCAPACITY is set.
 29  *
 30  * NOTE: Forkees are not accepted in the energy-aware wake-up path because
 31  * they don't have any useful utilization data yet and it's not possible to
 32  * forecast their impact on energy consumption. Consequently, they will be
 33  * placed by find_idlest_cpu() on the least loaded CPU, which might turn out
 34  * to be energy-inefficient in some use-cases. The alternative would be to
 35  * bias new tasks towards specific types of CPUs first, or to try to infer
 36  * their util_avg from the parent task, but those heuristics could hurt
 37  * other use-cases too. So, until someone finds a better way to solve this,
 38  * let's keep things simple by re-using the existing slow path.
 39  */
 40 
 41 static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu,
 42                      int sync, int sibling_count_hint)
 43 {
 44     unsigned long prev_energy = ULONG_MAX, best_energy = ULONG_MAX;
 45     struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
 46     int weight, cpu = smp_processor_id(), best_energy_cpu = prev_cpu;    //cpu:當前執行的cpu
 47     unsigned long cur_energy;
 48     struct perf_domain *pd;
 49     struct sched_domain *sd;
 50     cpumask_t *candidates;
 51     bool is_rtg;
 52     struct find_best_target_env fbt_env;
 53     bool need_idle = wake_to_idle(p);                //是否set flag PF_WAKE_UP_IDLE
 54     int placement_boost = task_boost_policy(p);        //獲取task sched boost policy:none/on_big/on_all 與sched_boost、schedtune設置也有關
 55     u64 start_t = 0;
 56     int delta = 0;
 57     int task_boost = per_task_boost(p);            //僅網絡有打開該boost,這裏可以認為沒有boost
 58     int boosted = (schedtune_task_boost(p) > 0) || (task_boost > 0);    //查看task的schedtune有沒有打開boost
 59     int start_cpu = get_start_cpu(p);        //獲取從哪個cpu core開始,嘗試作為target cpu
 60 
 61     if (start_cpu < 0)
 62         goto eas_not_ready;
 63 
 64     is_rtg = task_in_related_thread_group(p);    //判斷task是否在一個group內
 65 
 66     fbt_env.fastpath = 0;
 67 
 68     if (trace_sched_task_util_enabled())
 69         start_t = sched_clock();                //trace log
 70 
 71     /* Pre-select a set of candidate CPUs. */
 72     candidates = this_cpu_ptr(&energy_cpus);
 73     cpumask_clear(candidates);
 74 
 75     if (need_idle)
 76         sync = 0;
 77 
 78     if (sysctl_sched_sync_hint_enable && sync &&
 79                 bias_to_this_cpu(p, cpu, start_cpu)) {        //滿足3個調節:sync hint enable/flag:sync=1/bias to當前cpu
 80         best_energy_cpu = cpu;                                //當前執行的cpu
 81         fbt_env.fastpath = SYNC_WAKEUP;
 82         goto done;
 83     }
 84 
 85     if (is_many_wakeup(sibling_count_hint) && prev_cpu != cpu &&    //sibling_count_hint代表有多少個thread在當前event中喚醒
 86                 bias_to_this_cpu(p, prev_cpu, start_cpu)) {
 87         best_energy_cpu = prev_cpu;                            //選擇prev cpu
 88         fbt_env.fastpath = MANY_WAKEUP;
 89         goto done;
 90     }
 91 
 92     rcu_read_lock();
 93     pd = rcu_dereference(rd->pd);
 94     if (!pd)
 95         goto fail;
 96 
 97     /*
 98      * Energy-aware wake-up happens on the lowest sched_domain starting
 99      * from sd_asym_cpucapacity spanning over this_cpu and prev_cpu.
100      */
101     sd = rcu_dereference(*this_cpu_ptr(&sd_asym_cpucapacity));
102     while (sd && !cpumask_test_cpu(prev_cpu, sched_domain_span(sd)))
103         sd = sd->parent;
104     if (!sd)
105         goto fail;
106 
107     sync_entity_load_avg(&p->se);        //更新task所在sched_entity的PELT load
108     if (!task_util_est(p))
109         goto unlock;
110 
111     if (sched_feat(FIND_BEST_TARGET)) {        //檢查FIND_BEST_TARGET這個調度特性是否打開:目前是打開的
112         fbt_env.is_rtg = is_rtg;
113         fbt_env.placement_boost = placement_boost;
114         fbt_env.need_idle = need_idle;
115         fbt_env.start_cpu = start_cpu;
116         fbt_env.boosted = boosted;
117         fbt_env.strict_max = is_rtg &&
118             (task_boost == TASK_BOOST_STRICT_MAX);
119         fbt_env.skip_cpu = is_many_wakeup(sibling_count_hint) ?
120                    cpu : -1;
121 
122         find_best_target(NULL, candidates, p, &fbt_env);            //(1)核心函數,最終是將找到的target_cpu和backup_cpu都存放進了candidates中
123     } else {
124         select_cpu_candidates(sd, candidates, pd, p, prev_cpu);
125     }
126 
127     /* Bail out if no candidate was found. */
128     weight = cpumask_weight(candidates);    //判斷如果沒有找到target cpu和backup cpu時,直接goto unlock
129     if (!weight)
130         goto unlock;
131 
132     /* If there is only one sensible candidate, select it now. */
133     cpu = cpumask_first(candidates);
134     if (weight == 1 && ((schedtune_prefer_idle(p) && idle_cpu(cpu)) ||      //如果只找到了1個cpu,task是prefer_idle並且這個cpu也是idle的;或者cpu就是prev_cpu
135                 (cpu == prev_cpu))) {
136         best_energy_cpu = cpu;                              //那麼就選這個cpu為【best_energy_cpu】
137         goto unlock;
138     }
139 
140 #ifdef CONFIG_SCHED_WALT
141     if (p->state == TASK_WAKING)      //如果是新喚醒的task,獲取task_util
142         delta = task_util(p);
143 #endif
144     if (task_placement_boost_enabled(p) || need_idle || boosted ||      //滿足一下條件之一,那麼第一個candidate cpu就作為【best_energy_cpu】不再考慮計算energy
145         is_rtg || __cpu_overutilized(prev_cpu, delta) ||            //打開了sched_boost、need_idle(PF_WAKE_UP_IDLE)、開了schedtune boost、related_thread_group限制使用小核、prev_cpu+delta沒有overutil、
146         !task_fits_max(p, prev_cpu) || cpu_isolated(prev_cpu)) {       //p放在prev_cpu上會misfit、prev_cpu處於isolated
147         best_energy_cpu = cpu;
148         goto unlock;
149     }
150 
151     if (cpumask_test_cpu(prev_cpu, &p->cpus_allowed))              //根據prev_cpu是否在task p的cpuset範圍內
152         prev_energy = best_energy = compute_energy(p, prev_cpu, pd);     //(2)在範圍內,則計算p在prev_cpu上的energy
153     else
154         prev_energy = best_energy = ULONG_MAX;                  //不在範圍內,energy就設為最大,說明prev_cpu不考慮作為best_energy_cpu了
155 
156     /* Select the best candidate energy-wise. */          //通過比較energy,挑選出best_energy_cpu、best_energy
157     for_each_cpu(cpu, candidates) {
158         if (cpu == prev_cpu)      //過濾prev_cpu
159             continue;
160         cur_energy = compute_energy(p, cpu, pd);            //計算p遷移到candidate cpu上的energy
161         trace_sched_compute_energy(p, cpu, cur_energy, prev_energy,
162                        best_energy, best_energy_cpu);
163         if (cur_energy < best_energy) {
164             best_energy = cur_energy;
165             best_energy_cpu = cpu;
166         } else if (cur_energy == best_energy) {
167             if (select_cpu_same_energy(cpu, best_energy_cpu,    //當candidate cpu的energy與best_cpu一樣的話,怎麼選
168                         prev_cpu)) {
169                 best_energy = cur_energy;
170                 best_energy_cpu = cpu;
171             }
172         }
173     }
174 unlock:
175     rcu_read_unlock();
176 
177     /*
178      * Pick the prev CPU, if best energy CPU can't saves at least 6% of
179      * the energy used by prev_cpu.
180      */
181     if ((prev_energy != ULONG_MAX) && (best_energy_cpu != prev_cpu)  &&  //找到了非prev_cpu的best_energy_cpu、且省電下來的energy要大於在prev_energy上的6%,那麼best_energy_cpu則滿足條件;否則仍然使用prev_cpu
182         ((prev_energy - best_energy) <= prev_energy >> 4))          //這裏巧妙地使用了位移:右移1位代表÷2,所以prev_energy/2/2/2/2 = prev_energy*6%
183         best_energy_cpu = prev_cpu;
184 
185 done:
186 
187     trace_sched_task_util(p, cpumask_bits(candidates)[0], best_energy_cpu,
188             sync, need_idle, fbt_env.fastpath, placement_boost,
189             start_t, boosted, is_rtg, get_rtg_status(p), start_cpu);
190 
191     return best_energy_cpu;
192 
193 fail:
194     rcu_read_unlock();
195 eas_not_ready:
196     return -1;
197 }

 (1)find_best_target()

  1 static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
  2                     struct task_struct *p,
  3                     struct find_best_target_env *fbt_env)
  4 {
  5     unsigned long min_util = boosted_task_util(p);        //獲取p的boosted_task_util
  6     unsigned long target_capacity = ULONG_MAX;
  7     unsigned long min_wake_util = ULONG_MAX;
  8     unsigned long target_max_spare_cap = 0;
  9     unsigned long best_active_util = ULONG_MAX;
 10     unsigned long best_active_cuml_util = ULONG_MAX;
 11     unsigned long best_idle_cuml_util = ULONG_MAX;
 12     bool prefer_idle = schedtune_prefer_idle(p);    //獲取task prefer_idle配置
 13     bool boosted = fbt_env->boosted;
 14     /* Initialise with deepest possible cstate (INT_MAX) */
 15     int shallowest_idle_cstate = INT_MAX;
 16     struct sched_domain *start_sd;
 17     struct sched_group *sg;
 18     int best_active_cpu = -1;
 19     int best_idle_cpu = -1;
 20     int target_cpu = -1;
 21     int backup_cpu = -1;
 22     int i, start_cpu;
 23     long spare_wake_cap, most_spare_wake_cap = 0;
 24     int most_spare_cap_cpu = -1;
 25     int prev_cpu = task_cpu(p);
 26     bool next_group_higher_cap = false;
 27     int isolated_candidate = -1;
 28 
 29     /*
 30      * In most cases, target_capacity tracks capacity_orig of the most
 31      * energy efficient CPU candidate, thus requiring to minimise
 32      * target_capacity. For these cases target_capacity is already
 33      * initialized to ULONG_MAX.
 34      * However, for prefer_idle and boosted tasks we look for a high
 35      * performance CPU, thus requiring to maximise target_capacity. In this
 36      * case we initialise target_capacity to 0.
 37      */
 38     if (prefer_idle && boosted)
 39         target_capacity = 0;
 40 
 41     if (fbt_env->strict_max)
 42         most_spare_wake_cap = LONG_MIN;
 43 
 44     /* Find start CPU based on boost value */
 45     start_cpu = fbt_env->start_cpu;
 46     /* Find SD for the start CPU */
 47     start_sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, start_cpu));    //找到start cpu所在的sched domain,sd_asym_cpucapacity表示是非對稱cpu capacity級別,應該就是DIE level,所以domain是cpu0-7
 48     if (!start_sd)
 49         goto out;
 50 
 51     /* fast path for prev_cpu */
 52     if (((capacity_orig_of(prev_cpu) == capacity_orig_of(start_cpu)) ||        //prev cpu和start cpu的當前max_policy_freq下的capacity相等
 53         asym_cap_siblings(prev_cpu, start_cpu)) &&
 54         !cpu_isolated(prev_cpu) && cpu_online(prev_cpu) &&
 55         idle_cpu(prev_cpu)) {
 56 
 57         if (idle_get_state_idx(cpu_rq(prev_cpu)) <= 1) {    //prev cpu idle state的index <1,說明休眠不深
 58             target_cpu = prev_cpu;
 59 
 60             fbt_env->fastpath = PREV_CPU_FASTPATH;
 61             goto target;
 62         }
 63     }
 64 
 65     /* Scan CPUs in all SDs */
 66     sg = start_sd->groups;
 67     do {                            //do-while循環,針對start cpu的調度域中的所有調度組進行遍歷,由於domain是cpu0-7,那麼調度組就是2個大小cluster:cpu0-3,cpu4-7
 68         for_each_cpu_and(i, &p->cpus_allowed, sched_group_span(sg)) {    //尋找task允許的cpuset和調度組可用cpu範圍內
 69             unsigned long capacity_curr = capacity_curr_of(i);        //當前freq的cpu_capacity
 70             unsigned long capacity_orig = capacity_orig_of(i);        //當前max_policy_freq的cpu_capacity, >=capacity_curr
 71             unsigned long wake_util, new_util, new_util_cuml;
 72             long spare_cap;
 73             int idle_idx = INT_MAX;
 74 
 75             trace_sched_cpu_util(i);
 76 
 77             if (!cpu_online(i) || cpu_isolated(i))        //cpu處於非online,或者isolate狀態,則直接不考慮
 78                 continue;
 79 
 80             if (isolated_candidate == -1)
 81                 isolated_candidate = i;
 82 
 83             /*
 84              * This CPU is the target of an active migration that's
 85              * yet to complete. Avoid placing another task on it.
 86              * See check_for_migration()
 87              */
 88             if (is_reserved(i))        //已經有task要遷移到上面,但是還沒有遷移完成。所以這樣的cpu不考慮
 89                 continue;
 90 
 91             if (sched_cpu_high_irqload(i))    //高irq load的cpu不考慮。irq load可以參考之前WALT文章:https://www.cnblogs.com/lingjiajun/p/12317090.html
 92                 continue;
 93 
 94             if (fbt_env->skip_cpu == i)        //當前活動的cpu是否有很多event一起wakeup,如果有,那麼也不考慮該cpu
 95                 continue;
 96 
 97             /*
 98              * p's blocked utilization is still accounted for on prev_cpu
 99              * so prev_cpu will receive a negative bias due to the double
100              * accounting. However, the blocked utilization may be zero.
101              */
102             wake_util = cpu_util_without(i, p);      //計算沒有除了p以外的cpu_util(p不在該cpu rq的情況下,實際就是當前cpu_util)
103             new_util = wake_util + task_util_est(p);    //計算cpu_util + p的task_util(p的task_util就是walt統計的demand_scaled)
104             spare_wake_cap = capacity_orig - wake_util;  //剩餘的capacity = capacity_orig - p以外的cpu_util
105 
106             if (spare_wake_cap > most_spare_wake_cap) {
107                 most_spare_wake_cap = spare_wake_cap;  //在循環中,找到有剩餘capacity最多(最空閑)的cpu = i,並保存剩餘的capacity
108                 most_spare_cap_cpu = i;
109             }
110 
111             if (per_task_boost(cpu_rq(i)->curr) ==    //cpu【i】當前running_task的task_boost == TASK_BOOST_STRICT_MAX,那麼不適合作為tager_cpu
112                     TASK_BOOST_STRICT_MAX)
113                 continue;
114             /*
115              * Cumulative demand may already be accounting for the
116              * task. If so, add just the boost-utilization to
117              * the cumulative demand of the cpu.
118              */
119             if (task_in_cum_window_demand(cpu_rq(i), p))      //計算新的cpu【i】的cpu_util_cum = cpu_util_cum + p的boosted_task_util
120                 new_util_cuml = cpu_util_cum(i, 0) +        //特別地,如果p已經在cpu【i】的rq中,或者p的部分demand被統計在了walt中。那麼防止統計2次,所以要減去p的task_util(denamd_scaled)
121                         min_util - task_util(p);
122             else
123                 new_util_cuml = cpu_util_cum(i, 0) + min_util;
124 
125             /*
126              * Ensure minimum capacity to grant the required boost.
127              * The target CPU can be already at a capacity level higher
128              * than the one required to boost the task.
129              */
130             new_util = max(min_util, new_util);          //取 p的booted_task_util、加入p之後的cpu_util,之間的較大值
131             if (new_util > capacity_orig)              //與capacity_orig比較,大於capacity_orig的情況下,不適合作為target_cpu
132                 continue;
133 
134             /*
135              * Pre-compute the maximum possible capacity we expect
136              * to have available on this CPU once the task is
137              * enqueued here.
138              */
139             spare_cap = capacity_orig - new_util;        //預計算當p遷移到cpu【i】上后,剩餘的可能最大capacity
140 
141             if (idle_cpu(i))                     //判斷當前cpu【i】是否處於idle,並獲取idle index(idle的深度)
142                 idle_idx = idle_get_state_idx(cpu_rq(i));
143 
144 
145             /*
146              * Case A) Latency sensitive tasks
147              *
148              * Unconditionally favoring tasks that prefer idle CPU to
149              * improve latency.
150              *
151              * Looking for:
152              * - an idle CPU, whatever its idle_state is, since
153              *   the first CPUs we explore are more likely to be
154              *   reserved for latency sensitive tasks.
155              * - a non idle CPU where the task fits in its current
156              *   capacity and has the maximum spare capacity.
157              * - a non idle CPU with lower contention from other
158              *   tasks and running at the lowest possible OPP.
159              *
160              * The last two goals tries to favor a non idle CPU
161              * where the task can run as if it is "almost alone".
162              * A maximum spare capacity CPU is favoured since
163              * the task already fits into that CPU's capacity
164              * without waiting for an OPP chance.
165              *
166              * The following code path is the only one in the CPUs
167              * exploration loop which is always used by
168              * prefer_idle tasks. It exits the loop with wither a
169              * best_active_cpu or a target_cpu which should
170              * represent an optimal choice for latency sensitive
171              * tasks.
172              */
173             if (prefer_idle) {                        //對lantency有要求的task
174                 /*
175                  * Case A.1: IDLE CPU
176                  * Return the best IDLE CPU we find:
177                  * - for boosted tasks: the CPU with the highest
178                  * performance (i.e. biggest capacity_orig)
179                  * - for !boosted tasks: the most energy
180                  * efficient CPU (i.e. smallest capacity_orig)
181                  */
182                 if (idle_cpu(i)) {                    //如果cpu【i】是idle的
183                     if (boosted &&
184                         capacity_orig < target_capacity)      //對於boosted task,cpu需要選擇最大capacity_orig,不滿足要continue
185                         continue;
186                     if (!boosted &&
187                         capacity_orig > target_capacity)      //對於非boosted task,cpu選擇最小capacity_orig,不滿足要continue
188                         continue;
189                     /*
190                      * Minimise value of idle state: skip
191                      * deeper idle states and pick the
192                      * shallowest.
193                      */
194                     if (capacity_orig == target_capacity &&
195                         sysctl_sched_cstate_aware &&
196                         idle_idx >= shallowest_idle_cstate)    //包括下面的continue,都是為了挑選出處於idle最淺的cpu
197                         continue;
198 
199                     target_capacity = capacity_orig;
200                     shallowest_idle_cstate = idle_idx;
201                     best_idle_cpu = i;                //選出【prefer_idle】best_idle_cpu
202                     continue;
203                 }
204                 if (best_idle_cpu != -1)              //過濾上面已經找到best_idle_cpu的情況,不需要走下面流程了
205                     continue;
206 
207                 /*
208                  * Case A.2: Target ACTIVE CPU
209                  * Favor CPUs with max spare capacity.
210                  */
211                 if (capacity_curr > new_util &&
212                     spare_cap > target_max_spare_cap) {    //找到capacity_curr滿足包含進程p的cpu_util,並且找到空閑capacity最多的那個cpu
213                     target_max_spare_cap = spare_cap;
214                     target_cpu = i;                //選出【prefer_idle】target_cpu
215                     continue;
216                 }
217                 if (target_cpu != -1)              //如果cpu條件不滿足,則continue,繼續找target_cpu
218                     continue;
219 
220 
221                 /*
222                  * Case A.3: Backup ACTIVE CPU
223                  * Favor CPUs with:
224                  * - lower utilization due to other tasks
225                  * - lower utilization with the task in
226                  */
227                 if (wake_util > min_wake_util)          //找出除了p以外的cpu_util最小的cpu
228                     continue;
229 
230                 /*
231                  * If utilization is the same between CPUs,
232                  * break the ties with WALT's cumulative
233                  * demand
234                  */
235                 if (new_util == best_active_util &&
236                     new_util_cuml > best_active_cuml_util)  //如果包含p的cpu_util相等,那麼就挑選cpu_util_cum + p的boosted_task_util最小的那個cpu
237                     continue;
238                 min_wake_util = wake_util;
239                 best_active_util = new_util;
240                 best_active_cuml_util = new_util_cuml;
241                 best_active_cpu = i;                //選出【prefer_idle】best_active_cpu
242                 continue;
243             }
244 
245             /*
246              * Skip processing placement further if we are visiting
247              * cpus with lower capacity than start cpu
248              */
249             if (capacity_orig < capacity_orig_of(start_cpu))  //cpu【i】capacity_orig < 【start_cpu】capacity_orig的不考慮
250                 continue;
251 
252             /*
253              * Case B) Non latency sensitive tasks on IDLE CPUs.
254              *
255              * Find an optimal backup IDLE CPU for non latency
256              * sensitive tasks.
257              *
258              * Looking for:
259              * - minimizing the capacity_orig,
260              *   i.e. preferring LITTLE CPUs
261              * - favoring shallowest idle states
262              *   i.e. avoid to wakeup deep-idle CPUs
263              *
264              * The following code path is used by non latency
265              * sensitive tasks if IDLE CPUs are available. If at
266              * least one of such CPUs are available it sets the
267              * best_idle_cpu to the most suitable idle CPU to be
268              * selected.
269              *
270              * If idle CPUs are available, favour these CPUs to
271              * improve performances by spreading tasks.
272              * Indeed, the energy_diff() computed by the caller67jkkk
273              * will take care to ensure the minimization of energy
274              * consumptions without affecting performance.
275              */                               //對latency要求不高的task,並要求idle cpu作為target的情況
276             if (idle_cpu(i)) {                      //判斷cpu【i】是否idle
277                 /*
278                  * Prefer shallowest over deeper idle state cpu,
279                  * of same capacity cpus.
280                  */
281                 if (capacity_orig == target_capacity &&      //選出capacity相同情況下,idle最淺的cpu
282                     sysctl_sched_cstate_aware &&
283                     idle_idx > shallowest_idle_cstate)
284                     continue;
285 
286                 if (shallowest_idle_cstate == idle_idx &&
287                     target_capacity == capacity_orig &&
288                     (best_idle_cpu == prev_cpu ||
289                     (i != prev_cpu &&
290                     new_util_cuml > best_idle_cuml_util)))    //best_idle_cpu非prev_cpu,並且挑選cpu_util_cum + p的boosted_task_util最小的
291                     continue;
292 
293                 target_capacity = capacity_orig;
294                 shallowest_idle_cstate = idle_idx;
295                 best_idle_cuml_util = new_util_cuml;
296                 best_idle_cpu = i;                  //選出【normal-idle】best_idle_cpu
297                 continue;
298             }
299 
300             /*
301              * Consider only idle CPUs for active migration.
302              */
303             if (p->state == TASK_RUNNING)              //task p正在運行說明是misfit task,只考慮idle cpu作為target,不進行下面流程
304                 continue;
305 
306             /*
307              * Case C) Non latency sensitive tasks on ACTIVE CPUs.
308              *
309              * Pack tasks in the most energy efficient capacities.
310              *
311              * This task packing strategy prefers more energy
312              * efficient CPUs (i.e. pack on smaller maximum
313              * capacity CPUs) while also trying to spread tasks to
314              * run them all at the lower OPP.
315              *
316              * This assumes for example that it's more energy
317              * efficient to run two tasks on two CPUs at a lower
318              * OPP than packing both on a single CPU but running
319              * that CPU at an higher OPP.
320              *
321              * Thus, this case keep track of the CPU with the
322              * smallest maximum capacity and highest spare maximum
323              * capacity.
324              */                                  //對latency要求不高,並需要ACTIVE cpu作為target的情況
325 
326             /* Favor CPUs with maximum spare capacity */
327             if (spare_cap < target_max_spare_cap)        //找到遷移p之後,剩餘capacity最多的cpu
328                 continue;
329 
330             target_max_spare_cap = spare_cap;
331             target_capacity = capacity_orig;
332             target_cpu = i;                      //找出【normal-ACTIVe】的target_cpu
333         }      //到此就是一個調度組(cluster)內cpu的循環查找
334 
335         next_group_higher_cap = (capacity_orig_of(group_first_cpu(sg)) <
336             capacity_orig_of(group_first_cpu(sg->next)));      //嘗試查找下一個capacity更大的big cluster
337 
338         /*
339          * If we've found a cpu, but the boost is ON_ALL we continue
340          * visiting other clusters. If the boost is ON_BIG we visit
341          * next cluster if they are higher in capacity. If we are
342          * not in any kind of boost, we break.
343          *
344          * And always visit higher capacity group, if solo cpu group
345          * is not in idle.
346          */
347         if (!prefer_idle && !boosted &&                //上面找到cpu但是boost=ON_ALL,那麼還要查找其他cluster
348             ((target_cpu != -1 && (sg->group_weight > 1 ||     //上面找到cpu但是boost=ON_BIG,那麼還要在capacity更大的cluster中查找
349              !next_group_higher_cap)) ||                //上面找到了cpu,並且不在任何boost。那麼break
350              best_idle_cpu != -1) &&                  //如果上面group中,沒有cpu是idle,那麼always在capacity更大的cluster中查找
351             (fbt_env->placement_boost == SCHED_BOOST_NONE ||
352             !is_full_throttle_boost() ||
353             (fbt_env->placement_boost == SCHED_BOOST_ON_BIG &&
354                 !next_group_higher_cap)))                
355             break;
356 
357         /*
358          * if we are in prefer_idle and have found an idle cpu,
359          * break from searching more groups based on the stune.boost and
360          * group cpu capacity. For !prefer_idle && boosted case, don't
361          * iterate lower capacity CPUs unless the task can't be
362          * accommodated in the higher capacity CPUs.
363          */
364         if ((prefer_idle && best_idle_cpu != -1) ||            //如果設置了prefer_idle,並且找到了一個idle cpu;根據schedtune是否打開boost和是否有更大capacity的cluster進行判斷是否break
365             (boosted && (best_idle_cpu != -1 || target_cpu != -1 ||   //沒有prefer_idle,但是打開boost的情況,除非high capacity的cpu不能接受task,否則不用再遍歷low capacity的cpu
366              (fbt_env->strict_max && most_spare_cap_cpu != -1)))) {
367             if (boosted) {                           
368                 if (!next_group_higher_cap)                 
369                     break;
370             } else {
371                 if (next_group_higher_cap)
372                     break;
373             }
374         }
375 
376     } while (sg = sg->next, sg != start_sd->groups);
377 
378     adjust_cpus_for_packing(p, &target_cpu, &best_idle_cpu,      //計算將task放在target_cpu時,在考慮20%的余量,和sched_load_boost之後,看capacity是否滿足target_cpu當前freq的capacity
379                 shallowest_idle_cstate,                  //另外檢查rtg,看是否不考慮idle cpu
380                 fbt_env, boosted);
381 
382     /*
383      * For non latency sensitive tasks, cases B and C in the previous loop,
384      * we pick the best IDLE CPU only if we was not able to find a target
385      * ACTIVE CPU.                                    //latency要求不高的task選擇cpu優先級:ACTIVE cpu > idle cpu;沒有ACITVE,則選idle cpu
386      *
387      * Policies priorities:
388      *
389      * - prefer_idle tasks:                              //prefer_idle的task選擇cpu優先級:idle cpu > ACTIVE cpu(包含task之後又更多spare capacity) > ACTIVE cpu(更小cpu_util+boosted_task_util)
390      *
391      *   a) IDLE CPU available: best_idle_cpu
392      *   b) ACTIVE CPU where task fits and has the bigger maximum spare
393      *      capacity (i.e. target_cpu)
394      *   c) ACTIVE CPU with less contention due to other tasks
395      *      (i.e. best_active_cpu)
396      *
397      * - NON prefer_idle tasks:                            //非prefer_idle的task選擇cpu優先級:ACTIVE cpu > idle cpu
398      *
399      *   a) ACTIVE CPU: target_cpu
400      *   b) IDLE CPU: best_idle_cpu
401      */
402 
403     if (prefer_idle && (best_idle_cpu != -1)) {    //prefer_idle的task,直接選擇best_idle_cpu作為target
404         target_cpu = best_idle_cpu;
405         goto target;
406     }
407 
408     if (target_cpu == -1)              //假如target沒有找到,那麼重新找target:
409         target_cpu = prefer_idle
410             ? best_active_cpu            //1、prefer_idle的task選擇best_active_cpu;
411             : best_idle_cpu;            //2、而非prefer_idle的task選擇best_idle_cpu
412     else
413         backup_cpu = prefer_idle          //假如找到了target,那麼再選backup_cpu:
414         ? best_active_cpu              //1、prefer_idle的task選擇 best_active_cpu
415         : best_idle_cpu;               //2、非prefer_idle的task選擇 best_idle_cpu
416 
417     if (target_cpu == -1 && most_spare_cap_cpu != -1 &&
418         /* ensure we use active cpu for active migration */        //active migration(misfit task遷移)情況只選擇active cpu
419         !(p->state == TASK_RUNNING && !idle_cpu(most_spare_cap_cpu)))
420         target_cpu = most_spare_cap_cpu;
421 
422     if (target_cpu == -1 && isolated_candidate != -1 &&  //假如沒有找到target_cpu,prev_cpu又處於isolated,而task允許的所有cpu中有online並且unisolated的
423                     cpu_isolated(prev_cpu))         
424         target_cpu = isolated_candidate;            //那麼就選擇最後一個online並unisolated的cpu作為target
425 
426     if (backup_cpu >= 0)
427         cpumask_set_cpu(backup_cpu, cpus);          //將backup_cpu存放進cpus中
428     if (target_cpu >= 0) {
429 target:
430         cpumask_set_cpu(target_cpu, cpus);          //將找出的target cpu存放進cpus中
431     }
432 
433 out:
434     trace_sched_find_best_target(p, prefer_idle, min_util, start_cpu,
435                      best_idle_cpu, best_active_cpu,
436                      most_spare_cap_cpu,
437                      target_cpu, backup_cpu);
438 }

(2)計算energy

/*
 * compute_energy(): Estimates the energy that would be consumed if @p was
 * migrated to @dst_cpu. compute_energy() predicts what will be the utilization
 * landscape of the * CPUs after the task migration, and uses the Energy Model
 * to compute what would be the energy if we decided to actually migrate that
 * task.
 */
static long
compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
{
    long util, max_util, sum_util, energy = 0;
    int cpu;

    for (; pd; pd = pd->next) {
        max_util = sum_util = 0;
        /*
         * The capacity state of CPUs of the current rd can be driven by
         * CPUs of another rd if they belong to the same performance
         * domain. So, account for the utilization of these CPUs too
         * by masking pd with cpu_online_mask instead of the rd span.
         *
         * If an entire performance domain is outside of the current rd,
         * it will not appear in its pd list and will not be accounted
         * by compute_energy().
         */
        for_each_cpu_and(cpu, perf_domain_span(pd), cpu_online_mask) {    //在perf domain的cpu中找出online的
#ifdef CONFIG_SCHED_WALT
            util = cpu_util_next_walt(cpu, p, dst_cpu);    //計算遷移task p之後,每個cpu的util情況
#else
            util = cpu_util_next(cpu, p, dst_cpu);
            util += cpu_util_rt(cpu_rq(cpu));
            util = schedutil_energy_util(cpu, util);
#endif
            max_util = max(util, max_util);            //找到perf domain中cpu util最大的值(同perf domain,即cluster,最大的util決定了freq的設定)
            sum_util += util;                        //統計遷移之後,perf domain內的總util
        }

        energy += em_pd_energy(pd->em_pd, max_util, sum_util);    //計算perf domain的energy,並累計大小cluster的energy,就是整個系統energy
    }

    return energy;
}

 

獲取perf domain內的energy,在其中有2個重要的結構體:

/**
 * em_cap_state - Capacity state of a performance domain
 * @frequency:    The CPU frequency in KHz, for consistency with CPUFreq
 * @power:    The power consumed by 1 CPU at this level, in milli-watts
 * @cost:    The cost coefficient associated with this level, used during
 *        energy calculation. Equal to: power * max_frequency / frequency
 */
struct em_cap_state {
    unsigned long frequency;
    unsigned long power;
    unsigned long cost;
};

/**
 * em_perf_domain - Performance domain
 * @table:        List of capacity states, in ascending order
 * @nr_cap_states:    Number of capacity states
 * @cpus:        Cpumask covering the CPUs of the domain
 *
 * A "performance domain" represents a group of CPUs whose performance is
 * scaled together. All CPUs of a performance domain must have the same
 * micro-architecture. Performance domains often have a 1-to-1 mapping with
 * CPUFreq policies.
 */
struct em_perf_domain {
    struct em_cap_state *table;
    int nr_cap_states;
    unsigned long cpus[0];
};

 

em_pd_energy函數可以得到perf domain的energy。

/**
 * em_pd_energy() - Estimates the energy consumed by the CPUs of a perf. domain
 * @pd        : performance domain for which energy has to be estimated
 * @max_util    : highest utilization among CPUs of the domain
 * @sum_util    : sum of the utilization of all CPUs in the domain
 *
 * Return: the sum of the energy consumed by the CPUs of the domain assuming
 * a capacity state satisfying the max utilization of the domain.
 */
static inline unsigned long em_pd_energy(struct em_perf_domain *pd,
                unsigned long max_util, unsigned long sum_util)
{
    unsigned long freq, scale_cpu;
    struct em_cap_state *cs;
    int i, cpu;

    if (!sum_util)
        return 0;

    /*
     * In order to predict the capacity state, map the utilization of the
     * most utilized CPU of the performance domain to a requested frequency,
     * like schedutil.
     */
    cpu = cpumask_first(to_cpumask(pd->cpus));
    scale_cpu = arch_scale_cpu_capacity(NULL, cpu);            //獲取cpu的max_capacity
    cs = &pd->table[pd->nr_cap_states - 1];                    //獲取capacity state,是為了獲取最大頻點(因為cs的table是升序排列的,所以最後一個配置就是最大的頻點)
    freq = map_util_freq(max_util, cs->frequency, scale_cpu);    //利用上面獲取的最大頻點、max_capacity,根據當前的cpu util映射到當前的cpu freq

    /*
     * Find the lowest capacity state of the Energy Model above the
     * requested frequency.
     */
    for (i = 0; i < pd->nr_cap_states; i++) {    //通過循環找到能滿足當前cpu freq的最小的頻點,及其對應的capacity state
        cs = &pd->table[i];                        //同樣因為cs的table是升序排列的,所以遞增找到第一個滿足的,就是滿足條件的最小頻點
        if (cs->frequency >= freq)
            break;
    }

    /*
     * The capacity of a CPU in the domain at that capacity state (cs)
     * can be computed as:
     *
     *             cs->freq * scale_cpu
     *   cs->cap = --------------------                          (1)
     *                 cpu_max_freq
     *
     * So, ignoring the costs of idle states (which are not available in
     * the EM), the energy consumed by this CPU at that capacity state is
     * estimated as:
     *
     *             cs->power * cpu_util
     *   cpu_nrg = --------------------                          (2)
     *                   cs->cap
     *
     * since 'cpu_util / cs->cap' represents its percentage of busy time.
     *
     *   NOTE: Although the result of this computation actually is in
     *         units of power, it can be manipulated as an energy value
     *         over a scheduling period, since it is assumed to be
     *         constant during that interval.
     *
     * By injecting (1) in (2), 'cpu_nrg' can be re-expressed as a product
     * of two terms:
     *
     *             cs->power * cpu_max_freq   cpu_util
     *   cpu_nrg = ------------------------ * ---------          (3)
     *                    cs->freq            scale_cpu
     *
     * The first term is static, and is stored in the em_cap_state struct
     * as 'cs->cost'.
     *
     * Since all CPUs of the domain have the same micro-architecture, they
     * share the same 'cs->cost', and the same CPU capacity. Hence, the
     * total energy of the domain (which is the simple sum of the energy of
     * all of its CPUs) can be factorized as:
     *
     *            cs->cost * \Sum cpu_util
     *   pd_nrg = ------------------------                       (4)
     *                  scale_cpu
     */
    return cs->cost * sum_util / scale_cpu;        //通過上面的註釋以及公式,推導出energy計算公式,並計算出perf doamin的總energy
}

 

總結

1、find_best_target()函數主要是根據當前情況,找到task遷移的candidate cpu(target_cpu、backup cpu、prev_cpu)

具體邏輯:

prefer_idle:

best_idle_cpu:必須選擇idle狀態的cpu
—【task打開boost,選大核cpu】 && 【idle state最淺】
—【task沒有打開boost,選小核cpu】 && 【idle state最淺】

target_cpu:必選選擇ACTIVE狀態的cpu
—【當前freq的cpu_capacity > 遷移task后的cpu_util】 && 【遷移task之後,剩餘capacity最多的cpu】

best_active_cpu:必選選擇ACTIVE狀態的cpu
—【當前cpu_util更小的cpu】 && 【遷移task之後的cpu_util相等的話,選擇cpu_util_cum + boosted_task_util】

 

normal:

該cpu的capacity_orig > start_cpu的capacity_orig(只會往更大的cluster中尋找)

best_idle_cpu:必須選擇idle狀態的cpu
—【capacity相同情況下,idle最淺的cpu】 && 【選擇cpu_util_cum + boosted_task_util中最小的】 && 【不能是prev_cpu】

非misfit task遷移的情況下,還要選出target_cpu
target_cpu:必選選擇ACTIVE狀態的cpu
—【遷移task之後,剩餘capacity最多的cpu】】

 

2、在find_energy_efficient_cpu()後半段,計算task遷移到每個candidate cpu后的系統總energy。計算出的最小energy假如比prev_cpu的總energy少6%以上,那麼這個cpu就是best_energy_cpu。

 

後續:在energy model與energy計算,目前還未弄清楚如何聯繫起來,後續需要找到如何聯繫。

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

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

選擇SUV的N個理由,說中你了嗎?_如何寫文案

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

6%的人表示準備買SUV,這麼高的數據比例其實不驚人,確實在近幾年的汽車市場中,SUV持續火爆,自主品牌也厚積薄發,像哈弗H6,榮威RX5,吉利博越,寶駿560等等。那麼問題來了,廠家如此重本地研發SUV,加上越來越多消費者買SUV,究竟為的是什麼。

在某網站上曾看過一個數據調查,

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

其中有一個問題是“你會買一輛SUV么?”,在回答中有90.6%的人表示準備買SUV,這麼高的數據比例其實不驚人,確實在近幾年的汽車市場中,SUV持續火爆,自主品牌也厚積薄發,像哈弗H6,榮威RX5,吉利博越,寶駿560等等。那麼問題來了,廠家如此重本地研發SUV,加上越來越多消費者買SUV,究竟為的是什麼?

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

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。