simotin13's message

simotin13といいます。記事の内容でご質問やご意見がありましたらお気軽にコメントしてください\^o^/

TranscendのJDM820を買ってMacBookProのSSDを交換した

普段使っているMacBookPro(Late 2013)でS.M.A.R.Tエラーが出ていたため、タイトルの通り
MacBookProで使えるSSDであるJDM820を買ってSSDを交換してみました。

SSDの交換から復旧して使えるようになるまで比較的簡単でしたのでまとめておきたいと思います。

購入のきっかけ・S.M.A.R.Tエラーについて

ここ数か月前からSSDがS.M.A.R.Tエラーが発生する状態になっておりました。

Mac OS で S.M.A.R.Tエラーが発生するとOSの更新ができなくなります。
実はこのJDM820を購入する前にVMWare Fusionを購入していたのですが、OSのバージョンが古いためインストールができませんでした。しかもOSを更新しようとするとS.M.A.R.Tエラーで更新を拒絶されるというどつもにはまった状態でした。

抜け出すには、SSDを更新するしか手はありません。
ということで、この商品を購入することにしました。

商品内容

SSD本体。高いですが240GBでは少し心もとないのと、長く使うものだからということで思い切って480GBの商品を買いました。痛い出費ですがまぁ必要なものだし元は取れるはず・・・
※私が使っているのはMacBookPro late2013(latina)です。SSDは使っているMacBookによって異なるのでご注意を。

f:id:simotin13:20180113134949j:plain



交換するときに必要なドライバーも付属しています。
f:id:simotin13:20180114135812j:plain

SSDの交換の際には、

  1. TimeMachineによるバックアップ作業
  2. SSDの交換作業
  3. OS再インストール・データ復旧

TimeMachineによるバックアップ作業

交換前にデータのバックアップを取っておきます。
TimeMachineでのバックアップはデータ容量によると思いますが、私の場合5分程度で完了しました。

SSDの交換作業

交換作業にあたって、こちらの記事を参考にさせて頂きました。

www.machinist.work
参考にさせて頂き、ありがとうございます。

交換の作業自体はそれほど難しいものではありません。
ネジを外して、元々ついているSSDを外し、購入した新しいSSDに差し替えるだけです。

まずは商品に付属のドライバを使ってMacBookProの裏面にあるネジを外して、SSDを交換します。

カバーを外してみると・・・

なんということでしょう。

f:id:simotin13:20180113135747j:plain

埃まみれになって 時間(とき)の経つのも忘れた

4年程使ってますが、中はこんなに汚くなっているんですね・・・

一歩間違うと閲覧注意のグロ画像になるところでした。ホコリじゃなくてゴキブリの卵とか死体とかが入っていなかったのでよしとしましょう。

ということで交換の前に綺麗に掃除しました。

基板だけでなくカバーの方もかなり汚れていました。交換に関わらず掃除は定期的にした方がよいかもしれません。
f:id:simotin13:20180113140658j:plain

さて、交換作業ですが、この部分がSSDになります。
f:id:simotin13:20180113140445j:plain

左側にネジがついていて、写真はネジを外した状態です。
右側がコネクタになっているので優しく引き抜いて、新しいSSDを差し込み、再びネジを締めます。

後はカバーをもと通りに付け直して交換作業は完了です。時間にして5分程でしょうか。

OS再インストール

交換したSSDはまっさらな状態ですので、当然いままで使っていたMacOSは起動しません。
復旧するには、

  1. インストールDVDから復旧
  2. TimeMachineから復旧
  3. ネットワークリカバリから復旧

という選択肢があるそうですが、ネットワークリカバリからの復旧が簡単そうでしたので試してみました。

手順

ネットワークリカバリのためにはインターネットに接続している必要があります。

まずは、Option+ Command + R キーを押しながらMacBook Proを起動します。
交換前に使用していたWiFiの設定が残っているためか、勝手にネットに接続してくれたようでした。

起動すると、しばらく何かのダウンロードに時間がかかりますが、ダウンロード後はOS Xのユーティリティの画面が表示されます。

ディスクユーティリティで交換したSSDをフォーマットした後、OS Xのインストールを選択すると、OSのインストールが可能です。※OSのイメージはネットから取得しているようです。(私が試した時はOS X MAVERICKSがインストールされました)

無事インストールができればOSのアップデートやデータの復旧などをすればSSDの交換前と同じように使えます。
この間、Option+ Command + R キーを押して起動したから、40分~50分程度でしょうか。

感想

復旧作業は思っていたより簡単だったので大満足です。

SSDフラッシュメモリを長く使うためには

フラッシュメモリはコントローラがウェアラベリングを担当してくれるそうです。
ウェアラベリングは特定のブロックへの書き込みを集中させないように書き込み先を分散する技術になりますが、使用済みの領域が多いとそもそも分散させる先がなくなってしまいます。
このため、一般にSSD等のフラッシュメモリは容量をある程度余裕がある状態で使うと長く使えると言われています。※同じ人に仕事を割り当て続けると疲弊して最後は仕事ができなくなりますがそんなイメージでしょうか・・・負荷を分散できるような余裕があるっていうのは大事なことですね。

私の場合はVMWareをよく使っていたので常に容量は不足がちでした。(あとDropboxで大容量をローカルに同期したりとか・・・)

恐らくこの状態が長く続いた為に、S.M.A.R.Tエラーに陥ったのではないかと思います。

今回買ったJDM820は高かったので、できるだけ長く使えるよう容量は常に意識しながら使いたいと思います。

LLVMのビルドについてまとめてみる

f:id:simotin13:20180105144554p:plain

2018年早々、LLVMのビルドで消耗しておりました。
なんとなくlibToolingを使ってみようとしたらソースのビルドが必要そうな感じだったので始めたのですが、LLVMには複数のプロジェクトがあり、各プロジェクトの役割とかいまいちピンと来ておらず、ビルドにあたっていろいろドキュメント読んだりする必要がありました。

ドキュメントを熟読せずに始めるといろいろと躓くようなので、LLVMのビルドに関する情報をまとめておきたいと思います。

といってもまだまとめ切れていない点が多いので恐らく後から次々と追記・訂正することになりそうな気がします。

目次

  • 目次
  • 必読ページ達
  • LLVM System GettingStarted
    • 読めよ、絶対読めよ。
    • 開発環境のC++のツールチェインについて
  • ツール・プロジェクトについて
    • compiler-rt
    • lld
    • LLDB
  • 結論
    • 注意事項
      • LLVMのビルドは結構ディスク容量食います。
      • LLVMのビルドはすごく時間かかります。
      • LLVMのビルドではすごくメモリ使います。
      • リンクがかえってこない!?
    • やること
      • clangをインストール
      • LLVMのソースの取得と展開
      • コマンド実行例
    • cmakeコマンドのオプションについて
      • オプションの解説
  • 参考書籍
  • 感想
    • libLTO.so というお化けライブラリ
    • C++の現在と未来
  • まとめ
続きを読む

LLVMをビルドするときのリンクエラー対応

llvmをビルドしようとしてリンクエラーでこけました。
VMWare上のLinux Mint上でビルドしているのですが、ググってみるとどうもシステムのメモリ容量が小さいから起きているようでした。
※だいぶ前にLLVMをビルドしようとしたときにもはまったきがするので備忘録として書いておきたいと思います。


$make
.... (略) ....
[ 90%] Built target not
[ 90%] Built target yaml-bench
[ 90%] Built target LTO_exports
[ 90%] Linking CXX shared library ../../lib/libLTO.so
collect2: fatal error: ld terminated with signal 9 [強制終了]
compilation terminated.
tools/lto/CMakeFiles/LTO.dir/build.make:279: ターゲット 'lib/libLTO.so.5.0.1' のレシピで失敗しました
make[2]: *** [lib/libLTO.so.5.0.1] エラー 1
make[2]: *** ファイル 'lib/libLTO.so.5.0.1' を削除します
CMakeFiles/Makefile2:14041: ターゲット 'tools/lto/CMakeFiles/LTO.dir/all' のレシピで失敗しました
make[1]: *** [tools/lto/CMakeFiles/LTO.dir/all] エラー 2
Makefile:149: ターゲット 'all' のレシピで失敗しました
make: *** [all] エラー 2

仮想マシンのメモリ割り当ては2GBになっていたので4GBにしてみたところ無事最後までビルドできました。

■参考にさせて頂いた記事
stackoverflow.com

LLVMのビルドはコンパイル時間も割とかかりましたが、ビルドにも時間がかかります。

C言語でbrainfuckを実装してみた

なんだかすごく今更ですが、気分的になんとなく実装してみました。

仕様把握

そもそもbrainfuckの仕様がよく把握できていないのでwikipedia等いくつかのサイトを参考にさせて頂きました。

Brainfuck - Wikipedia
Brainf*ck

Hello Worldなどいくつかサンプルコードを動かしてみましたが一応動いてそうです。

書いてみたコード

#include <stdlib.h>
#include <stdio.h>

#define CODE_LEN_MAX            (1024)
#define DATA_LEN_MAX            (30000)
#define STACK_LEN_MAX           (32)

static unsigned char code[CODE_LEN_MAX]        = {0};
static unsigned char buf[DATA_LEN_MAX]         = {0};
static unsigned char stackframe[STACK_LEN_MAX] = {0};

int main(int argc, char **argv)
{
    int c;
    int ip = 0;
    int sp = 0;
    int ptr = 0;
    int clen = 0;
    FILE *fp;

    if (argc < 2)
    {
        fprintf(stderr, "Input Code File path.");
        exit(-1);
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        fprintf(stderr, "Source file open failed\n");
        exit(-1);
    }

    while(1)
    {
        c = fgetc(fp);
        if (c == EOF)
        {
            break;
        }

        if (CODE_LEN_MAX < clen)
        {
            fprintf(stderr, "Code Size too large\n");
            exit(-1);
        }
        if (c == '\n')
        {
            continue;
        }
        if (c == '\r')
        {
            continue;
        }
        if (c == ' ')
        {
            continue;
        }

        code[clen++] = c;
    }

    #if 0
    fprintf(stdout, "Program loaded, size:[%d] byte\n", clen);
    #endif

    ip = 0;
    while(1)
    {
        switch(code[ip])
        {
        case '>':
            ptr++;
            ip++;
            break;
        case '<':
            ptr--;
            ip++;
            break;
        case '+':
            buf[ptr]++;
            ip++;
            break;
        case '-':
            buf[ptr]--;
            ip++;
            break;
        case '.':
            printf("%c", buf[ptr]);
            ip++;
            break;
        case ',':
            buf[ptr] = getchar();
            ip++;
            break;
        case '[':
            stackframe[sp++] = ip;
            if (buf[ptr] == 0)
            {
                while(1)
                {
                    ip++;
                    if (code[ip] == ']')
                    {
                    	sp--;
                        ip++;
                        break;
                    }
                }
            }
            else
            {
                ip++;
            }
            break;
        case ']':
            if (buf[ptr] != 0)
            {
                ip = stackframe[sp-1];
                ip++;
            }
            else
            {
            	sp--;
                ip++;
            }
            break;
        default:
            fprintf(stderr, "err:%X, ip:%d, size:%d\n", code[ip], ip, clen);
            exit(-1);
            break;
        }

        if (clen <= ip)
        {
            break;
        }
    }
    exit(0);
}

感想

"[","]"の条件分岐とループのところはちょっと面倒というか仕様理解も含めて時間がかかりました。
いまだに正しい仕様がなんなのかいまいち分かっていないのですが、"[","]"はネストに対応してあげるのが正しい実装のようです。
でもバグがあってちゃんと動かないコードとか出てきたりするかもしれません。

brainfuckを実装するのは楽しいのですが、brainfuck自体のコードは難読でデバッグがやり辛く面倒なので結局自分でコードは書きたいとは正直思いませんでした。
なので実装のバグとりも十分できていない気がします。

brainfuckはコードを書かないから、Lisp処理系でもちょっと書いてみたいと思い、調子に乗ってとりあえず電卓レベルの実装を書いてみました。

mcommit.hatenadiary.com

Lispの電卓機能を実装してみる

冬休みということで少し時間があるのでいろいろ勉強しているのですが、なんとなくLisp処理系を書いてみたくなったのでRubyで実装してみたいと思います。

Lisp処理系の実装というとshemeの仕様を理解して実装するのが一般的らしいのですが、冬休みで時間も限られているのでとりあえずLisp風の入力に対する電卓レベルの機能をRubyで書いてみました。
※そもそもLispの機能自体をよく知らないのでどこまで真面目にかけるか分かりませんが気が向いたら続けて書いてみたいと思います。

このレベルだとまだ比較的短いです。せっかくなのでブログにも挙げておきたいと思います。

書いてみたコード

gist.github.com

補足・解説

LispLisp Processing の通り、リスト構造を使って処理するのが特徴ですが、処理系を実装しようとしてみるとその特徴がよく分かります。

最初C言語で書こうとしていましたが、そもそもList構造のコードを書くのも面倒だなということでとりあえずRubyで書いてみました。

普通の電卓コードは結構前にC言語でかいた事がありますが、電卓を書く際のこつとして、中間記法を後置記法に変換するのがポイントになります。

mcommit.hatenadiary.com

例えば、 1 + 2 であれば、 1 2 + という順番に変換して、スタックをうまく使うとカッコつきの演算がかなり素直に実装できます。

Lispの場合は四則演算の計算する場合、中間記法ではなく前置記法になります。上記の 1 + 2 はLispでは(+ 1 2)と書きます。
また、(1 + 2) * 3 のような式は(* (+ 1 2) 3) のような書き方になります。

後置記法はスタックで処理するのに適していますが、前置記法はリスト構造で前から順番に処理するのに適していることが実際に(電卓レベルですが)処理系を実装してみるとよく分かりました。

こうして四則演算の入力に対する処理系を書いてみると、

では人間はどうして中間記法を使うんだろうか?

という疑問が湧いてきます。

もしかしたら脳内の構造はスタックでもリストでもない構造になっているじゃないかなと思いました。

感想

文字列の解析部のコードがかなりRubyらしくないというかダサい感じになりました。もう少し綺麗にできそうなオーラが漂っています。※異常系の処理も書いていません。

手抜きしたところと、Rubyらしさを活かしてもっと手抜き出来るところもあるのでコードとしては微妙ですがあとでC言語に書き直したいということもあるのであまり手抜きしすぎるとC言語に直す時に「あれっ!?ここどうしよっかな・・・」みたいなことになりそうな気がします。

Lispの実装についてよく知らないので、gaucheのドキュメントとか読んでみたらスタックマシンを使って実装しているそうでした。
Lispの処理系というのは真面目に作る場合やはりVMから作る必要があるんだろうか・・・
VMを作るといってもRubyを使えばスタックマシンの実装はそんなには難しくはない(書くコード量は多くはない)だろうけど、なんというか気合と時間はそれなりに必要になりそうで多分時間が足りなくなる気がする。