2018年4月6日 星期五

EZLink SSD 安全抹除 secure rease

EZLink SSD 安全抹除 secure rease

廠商已經倒了,找了一下有挖到他的原廠軟體,在這邊備份一下
切記不要使用 USB連接,以及有可能需要使用 IDE 模式 (我還沒抹除過先找來放)

創建SSD 安全抹除 secure erase

創建 SSD 安全抹除 secure erase

前篇寫了金字噸的,這篇補上創建的
https://charlottehong.blogspot.tw/2018/04/ssd-secure-erase.html
建議使用官方提供的專屬軟體不要使用通用的安全抹除

安全抹除

需要有第二個作業系統,如果有第二台電腦直接拆去第二台比較快;如果沒有的話看有沒有第二顆硬碟,可以直接從尾部切割一些空間安裝一個系統來執行。
切割方式可以對著開始按右鍵,然後開啟 磁碟管理(k) 對著你的第二顆硬碟的分割區按右鍵壓縮,壓縮出足夠的空間。
然後就正常安裝win10即可,這邊安裝完畢要注意先不要開接著看下面

使用IDE模式開啟

記得新安裝好的 Win10 要到BIOS內設置為 IDE 模式啟動,因為那個軟體只支援IDE模式下安全抹除。
如果是已經安裝好的系統從這裡教學 AHCI轉IDE,不用重灌系統
https://charlottehong.blogspot.tw/2018/02/win10-sysprep.html
記得抹除完畢之後還會轉回來 AHCI 模式,這樣對硬碟壽命、效能都比較好。轉回來的方法跟轉過來方法是一樣的。
覺得超級雷…SATA 要開 AHCI 比較好,要轉 IDE 模式還頗麻煩,之後抹除完畢還要轉回來。
然後就開啟 SSD Scope 軟體按抹除吧~

2018年4月1日 星期日

金士頓 SSD 固態硬碟 速度變超慢,如何安全抹除(Secure Erase)

金士頓 SSD 固態硬碟 速度變超慢,如何安全抹除(Secure Erase)

軟體(可在AHCI模式抹除):
安全抹除最大差別在於沒有真的去寫一次0,所以一下子幾秒就好了不會增加無謂損耗
,類似於直接在韌體上消除標記的概念。

安全抹除

條件
  • 必須 AHCI模式下運行
  • 更新韌體到最新
更新韌體(至少按一次)
開始抹除
開始抹除之後會要求你輸入序號的末四碼,就是圖中我塗掉的地方最後4碼

完整格式化

完整格式化會造成多於的浪費讀寫,以及他並不能真的清除所有地方
SSD讀寫有幾個不一樣的地方
  1. 主動尋找0的地方先寫(避開重複寫同一個地方)
  2. 磁軌是模擬出來的,實際上寫的位置是韌體的算法決定的
先上一篇比較有爭議的文章
http://www.coolaler.com/threads/ssd.261697/
這一篇底下有蠻多人反對的,客觀來看如果考慮到[2],你對硬碟完整格式化,也就是對全部填0,會發生的事情就是,在軟體上你認為是從磁軌0寫到最後一軌,實際上在硬體也就是SSD內根本就不存在磁軌0,他就是幫你找一塊他覺得好的地方寫上。
文中的說法是會自動使用FF填滿整顆,但是問題是填滿的時候應該不是塞檔案而是從磁軌0填充FF到最後一軌(我是沒有實際照著做,但是從軟體的語意上看起來是這樣,這邊就假設是),或者是說沒辦法在我的電腦見到磁碟空間已滿,所以這與直接格式化會是一樣的意思。
如果不是的話,那這樣不對,因為根據 [1] 還是整顆都髒的,接著根據[2]到時候填0也沒辦法填整顆。
結果就是浪費不少讀寫次數沒有把全部歸零,歸零多少[50%、80%甚至30%] 就是看運氣了,但是有一點是確定,變慢的硬碟這樣做過之後速度會變快
因為本來是整顆硬碟都不存在0,才要花時間找,現在是有部分是0所以測速變快了。
不過因為付出的代價還蠻大的,而且效率也不是很高,客觀來看不建議這樣做。
考量到 Secure Erase 多數情況是要下載原廠的軟體來做,如果原廠倒了….等等的情況未必能拿到軟體,那還是只能犧牲讀寫次數,做一次完整格式化來換一點點效能了~
不過在這一點我是覺得沒有什麼特別情況或是必要性等等,也沒差拉就算給你安全抹除也只是短暫快一陣子~很快會寫滿整顆了
安全抹除的指令根據主控不同設計不同,指令會不一樣;有通用的安全抹除軟體,慎用~可能會導致硬碟被鎖住不能用。
https://www.ptt.cc/bbs/PC_Shopping/M.1495986776.A.CF8.html


HDDERASE 抹除

這個軟體其實非常老舊了我並不認為他是,安全抹除,實際上爬文也有發現用這個方法安全抹除需要一點時間,顯然不是抹除。
不過他與前一章節提到的直接格式化最大不同在於,他需要再 IDE模式下才能工作,SSD的技術是建立在AHCI上的,不知道是不是因為這樣能夠干擾SSD的最佳化,進而真的從頭遍歷一遍。(這我不確定只是猜測~)


完整抹除

基於SSD是依據算法找存點,還有他是有一塊緩衝+備用區的,要完整消除資料很困難。
能刪除比較多的做法就是,填滿整顆固態硬碟,至少可以保證除了隱藏的工作區、備用區之外的地方都被刪除了,最後再做一次安全抹除,消除填滿的垃圾資料。


其他廠牌安全抹除

創建

限制
  • 不能使用USB連接
  • 只能使用IDE模式抹除

2018年3月28日 星期三

Win10 關機黑畫面很久才關閉 或是 開機進桌面前會黑屏一段時間

Win10 關機黑畫面很久才關閉 或是 開機進桌面前會黑屏一段時間

懶人包

  1. 確定網卡已經安裝廠商提供驅動,而不是Win10自動安裝
  2. 確實安裝主機板晶片驅動程式,尤其是英特爾的IME一定要
  3. 到 控制台->電源->關閉快速啟動 (見下面第一張圖)
下面是相關知識說明,上面做完即可解決問題可以不用看
另外這個現象我在2018的Win10還沒沒發生過,有可能是bug被修好了,也有可能是升級Win10版本導致的,有季度大更新建議重灌比較穩~


快速啟動

關機黑畫面比較常發生,是快速啟動導致的。但是正常情況下的快速啟動是不至於卡到的,大概就是延遲個幾秒就關閉了,不曉得是原因導致卡住了,如果卡太久就把它關閉了吧。
快速啟動會再關機的時候把一些硬件資訊或是開機的東西寫入硬碟,下次開機直接讀來用就不用重新讀取了。
快速啟動條件比較嚴苛要
  1. 系統支援並打開
  2. 主機板支援並打開
  3. 顯示卡支援(會更快)

系統支援並打開

到電源選項開啟即可,關機卡太久也是從這裡關閉就好

主機板支援並打開

到主機板裡面打開 fastboot+Ultra Fast ,兩個可能在同一選項。
Ultra Fast 會關掉一堆咚咚的檢測,比如說鍵盤…,所以才會有人說 WIN10的筆電不能進BIOS之類的問題。(解決辦法就是按住SIFT再按重開機就會跳出安全模式選項,選項中有一項是進BIOS的)
我的華碩Z97板子並沒有Ultra Fast,不過他可以手動選擇那些東西不檢測,結果是差不多意思的,手動把全部關了都不檢測;Ultra Fast是主機板廠商幫你設置好,廠商直接特化的會更快一些。
另外硬盤必須是GPT的格式,使用EFI啟動才能Ultra Fast,如果你的硬盤是MBR可以參考站內的文章,使用微軟內建的工具轉換,一下子就好了。
https://charlottehong.blogspot.tw/2017/11/windows-mbr-gptefi.html

顯示卡支援

顯示卡支援才能打開 Ultra Fast ,具體可以查詢一下,不過現在已經2018了市面上的卡都支援了,除非是舊卡否則不用特別查都會有。

快速啟動失敗

有沒有成功可以由幾個地方觀察(下面要同時成立)
  1. 開機是主機板廠商LOGO+轉圈圈而不是win10
  2. 這個轉圈圈只會一次轉個幾圈直接進桌面
快速啟動硬件都支援也都打開了,也有可能會失敗,失敗的原因不清楚,不過這就是造成標題所導致的情況的主因。
這邊以我的主機板華碩,具體可以看到開機的時候會有幾秒顯示 del可以進BIOS,會看到這個畫面就是快速啟動失敗了…,正常應該是直接ASUS轉一圈進桌面。
還有另一種失敗情況,一開機 ASUS轉圈,然後閃一下 ASUS再一次轉圈。
失敗都是有徵兆的,上一次關機會關超久,卡在黑畫面

如何修復快速啟動

如果失敗的話嘗試看看
  • 關閉快速啟動,正常關機再開機,然後再打開快速啟動
  • 清理一下你的C曹的至少保留足夠的空間
都不行就直接關了吧,SSD最多不會差超過10秒
都弄不好可以試試在開始搜尋復原,然後選擇保留資料。這個就相當於重灌,不過會幫你留著資料,原本設置是什麼就還好什麼完整保留,只重灌系統部分。
之前有一次大改版年度更新之後,我的快速啟動就修好了XD 回推這個方法可以試試看。
不過為了避免意外發生記得還是要先備份資料。

2018年3月21日 星期三

C C++ 隨機亂數 如何每次執行程式都不一樣

C C++ 隨機亂數 如何每次執行程式都不一樣

一開始時做亂數的時候最常遇到的問題就是怎麼每一次執行的亂數都一樣,大概是幾個原因造成的,沒有給時間種子或者是把時間種子放到for裡面一起跑了。
下面是做好的範例版本,初始化的方法是用 static 避開,static 初始化的那一行只會執行一次,然後這個變數會一直留著不會被刪除(解構)直到程序結束才跟著解構。

範例代碼

預設函式都是不包含最大值的,使用的時候可以自己手動在乎叫的時候+1,或是從函式裡面把 --max 中的 -- 移除即可。
純C的版本
/*****************************************************************
Name : 
Date : 2018/03/21
By   : CharlotteHonG
Final: 2018/03/21
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int rand_int(int min, int max){
    static int init=0;
    if(init == 0){ srand((unsigned)time(NULL)), rand(), ++init; }
    return (int)((rand() / (RAND_MAX+1.0)) * (--max - min + 1.0) + min);
}

int main(int argc, char const *argv[]){
    for(unsigned i = 0; i < 10; ++i) {
        printf("%d, ", rand_int(0, 10));
    } printf("\n");

    return 0;
}
再來是C++的版本
C++版本中
VS2017 使用的預設引擎是 mt19937
GCC 有查到使用的預設引擎是 minstd_rand0 (這個會導致第一個亂數永遠一樣)
/*****************************************************************
Name : 
Date : 2018/03/21
By   : CharlotteHonG
Final: 2018/03/21
*****************************************************************/
#include <iostream>
#include <random>
#include <ctime>
using namespace std;

template<typename T>
int randNum(int min, int max) {
    static std::mt19937 generator(time(NULL));
    std::uniform_int_distribution<T> distribution(min, --max);
    return distribution(generator);
}

int main(int argc, char const *argv[]){
    for(unsigned i = 0; i < 10; ++i) {
        cout << randNum<int>(1, 10) << ", ";
    } cout << endl;
    return 0;
}

為何亂數的第一個永遠都一樣

引用至:https://goo.gl/WJDCR7 留言中提到以下內容
我查到的是 default_random_engine 是使用 minstd_rand0引擎,使用的是linear_congruential_engine
算法大致為 xi+1 = (16807xi + 0) mod 2147483647.
那個如果是用time(NULL)
我們假設目前time是137486376xxxx(x我不知道是多少不過沒差)
要生成數字為0 - 168070000經過測試第一筆亂數為
136956956xxxx * 16807 / 16807000 = 136956956
這時time為
第二次跑程式時測是為生成 0-168070000
137490578xxxx * 16807 / 16807000
由於生成的數字太小,time的前幾位數並沒有改變所以導致
第一個數字都會一樣
而事實上,當你生成的亂數max等於100000時
第一次的第一個數 : 77018
//間隔約3秒
第二次的第一個數 : 77021
可以發現只有各位數在改變
而雖然microsoft 的定義是typedef mt19937 default_random_engine;但本質上用的引擎仍為mt19937,使用的是梅森算法(別問我是甚麼),所以不會有這問題
細節還是問其他懂的人吧
我以前用亂數時也發生過這問題所以我通常會用time(clock())

2018年3月19日 星期一

為什麼 char* str 在 printf 的時候 str 與 *str 會印出一樣的內容

為什麼 char* str 在 printf 的時候 str 與 *str 會印出一樣的內容

    char str[][1] = {{1}};
    printf("%p\n",  str);   // is address
    printf("%p\n",  *str);  // is address
    printf("%d\n", (int)    *(char*)str); // is 1

第一行

返回的就是一個陣列的地址這個應該不是個大問題,只是這中間編譯器自己默默做了一次隱式轉換
str 是一個 char(*)[1] 型態 自動轉換成 (char**)型態 他們之間並不完全等價,前者是陣列後者是指針。
這裡實際輸入函式的型態是 (cahr**)

第二行

這個是因為陣列轉換後的指針正好會是第一個值的關係,所以derefrence之後之後還是同一個地址
這裡實際輸入函式的型態是 (cahr*), 由 (char**) dereferance 而來。

第三行

這裡多一個語法上不安全的型別轉換,從 (char**) 轉換到 (char*)
(這個例子使用上是安全的)。
轉換成指針之後再 derefernnce 獲得記憶體內容,最後再轉成整數印出。
因為放置的內容 1 所以就是 1 了,如果內容是 1 對照一下表會是 49
    char str[][1] = {{1}};
    printf("%p\n",  str);   // is address
    printf("%p\n",  *str);  // is address
    printf("%d\n", (int)    *(char*)str); // is 1

2018年3月17日 星期六

C++ 計時器,計時函式跑的時間

C++ 計時器,計時函式跑的時間

簡單寫了一個比較易用的函式
/*****************************************************************
Name : Timer.hpp
Date : 2017/12/19
By   : CharlotteHonG
Final: 2017/12/19
*****************************************************************/
#pragma once
#include <string>
#include <ctime>

class Timer {
public:
    Timer(std::string name=""): name(name){
        startTime = clock();
    }
    operator double() {
        return time;
    }
public:
    void start() {
        startTime = clock();
        flag=0;
    }
    void end() {
        finalTime = clock();
        time = (double)(finalTime - startTime)/CLOCKS_PER_SEC;
    }
    void print(std::string name="") {
        if (flag==0) {
            flag = 1;
            end();
        }
        if(name=="") {
            name=this->name;
        }
        if(priSta) {
            std::cout << "#" << name << ", " << " time = " << time << "s" << std::endl;
        }
    }
private:
    std::string name;
    clock_t startTime;
    clock_t finalTime;
    double time;
    bool flag = 0;
public:
    bool priSta = 1;
};
直接引用即可,使用方法大致如下
Timer t;
t.start();
YourFun();
t.print("YourFun");
如果有一整頁的計時器一個一個刪除很麻煩可以使用
t.priSta=0;
可以關閉計時,就不用砍掉全部了