My code works, I don’t know why.

國王的耳朵是驢耳朵

Ubuntu 12.04下面無線網路無法ifconfig Wlan0 Up的檢查

| Comments

錯誤訊息

1
2
$ifconfig wlan0 up
SIOCSIFFLAGS: Operation not possible due to RF-kill

解決方式

  • 列出RF的block狀態,如果是硬體關掉請自行打開RF開關
    • rfkill list all
1
2
3
4
5
6
7
$ rfkill list all
8: phy1: Wireless LAN
  Soft blocked: yes
  Hard blocked: yes
9: hci0: Bluetooth
  Soft blocked: yes
  Hard blocked: no
  • 從軟體上面打開WIFI
    • rfkill unblock wifi

Linux下面快速搜尋PDF的方式

| Comments

有時候手上一堆PDF檔,不知道要查的資料在那個檔案,可以用下面的指令找出

  • find -name "*.pdf" -exec pdfgrep {} \;
  • 注意pdfgrep需要額外安裝
    • sudo apt-get install pdfgrep

GNU: The C Preprocessor 導讀

| Comments

C語言的前置處理(CPP: C preprocessor)是個很有趣的題目,知道在對的時機使用他們絕對能夠對於開發軟體有巨大的幫助。以下是我閱讀GNU: The C Preprocessor的筆記。請注意這只是筆記,詳細資料請自行參考原本網頁。

目錄

測試環境

概論

  • Preprocesser: 輸入文字,產生更動過的文字x。產生出來文字會當作另外執行程式的輸入資料。 出處
  • CNU C有自訂專用的Preprocessor指令,如果程式有移植性考量,gcc可以加入-std=c90, -std=c99-std=c11參數檢查。全開就用-pedantic參數

編碼

  • Source character set
    • 為gcc內部CPP處理的字元編碼
    • gcc 讀入原始碼後會以UTF-8同構的字元編碼處理程式碼,CPP處理時的文字輸出(如gcc -E)也是使用Source character set
    • 可使用-finput-charset=參數指定source file 字元編碼
  • Execution character set
    • CPP處理結束後會將結果轉換成指定的編碼,預設仍然是UTF8
    • 後面看不懂,不想看

初始行為

  • Load檔案到記憶體內。GCC 支援不同Line end 格式(LF, CR LF, CR)
    • 標準C 最後一行沒有line end是未定義行為,GCC會跳出警告訊息
  • 處理trigraphs
    • 史前遺跡,早期有些電腦沒有C需要的字元而使用trigraphs代替。如??/ 代表 \
    • 需要gcc參數設定才會支援
  • 將\斷行的statemenet合併成一行
  • 把註解換成空白字元

取Token

  • 空白鍵為分隔空白的單位
  • 由左至右順序取token a+++++b -> a++ ++ +b而不是a++ + ++b
  • Preprocessor token分類
    • identifiers: 單純的C合法token 如keyword, 字母和數字的組合
    • preprocessing numbers: 一般來說就是數字
    • String literals: 兩個"中間包含的字串,包括#include "test.h"
    • Punctuators: @ $ ` 以外ASCII的標點符號
    • other: 直接pass到preprocessr output,一般來說C compiler會把other token打槍。
      • Other chars:
        • @
        • $
        • `
        • 不是NUL的control char
        • ASCII 0x7F–0xFF (因為要支援國際字元、未來會討論存廢)
      • NUL在註解中會被忽略,一般程式碼則視為空白
  • 基本上,preprocesser 輸出就是一個token
1
2
3
4
5
6
#define MY() ddd
int main(void)
{
    int i,MY()__;
    return
}

展開後就是

1
2
3
4
5
6
7
8
9
10
## 1 "b.c"
## 1 "<built-in>"
## 1 "<command-line>"
## 1 "b.c"

int main(void)
{
    int i,ddd __;
    return
}

Preprossessor 語法概要

  • 包含指令(directives)和巨集(macros)
  • 提供
    • include檔案
    • 巨集展開
    • 條件式編譯
    • 行號控制:目前不是很懂,看起來是可以告訴compiler編譯intermediate時該statement是從哪個檔案的那一行過來的
    • compile時可以吐error或warning
  • 除了gcc內建的directives外,directives以#開頭,前後都可以有空白

  • 回目錄

Header Files

  • Header file就是檔案,該檔案包含下面的元件,讓不同原始碼檔案共用。
    • C declarations
    • 巨集
  • 原始碼檔案透過#include去取用這些Header Files的資料
  • #include效果和複製header file到原始碼檔案一樣。你可以用gcc -E 原始碼檔名看到header file被放入。之所以這樣做就是讓使用者省去複製和多次修改相同介面的時間。

#include語法

  • #include <file>
    • 使用系統內建的標頭檔。標頭檔除了放在預設的目錄外,還可以在GCC下使用-I參數指定標頭檔路徑
  • #include "file"
    • 自己原始碼專用的標頭檔。GCC搜尋順序
      • 同一份原始檔的目錄
      • -iquote指定的目錄
      • -I指定的目錄

標頭擋路徑

  • echo | gcc -v -x c -E -可以列出gcc 搜尋標頭檔目錄
  • gcc搜尋標頭檔順序是
    • 系統預設路徑
    • -I參數,一個以上-I路徑則由左至右開始搜尋
  • 可以使用-nostdinc讓gcc不去搜尋系統標準的include path

避免因為多重#include重複定義

  • 狀況說明
    • 原始碼檔案中include “file1”和”file2”
    • “file2”也有include “file1”
    • 最後變成原始碼檔案中放了兩份file1的內容,一方面多餘另一方面也會發生重複定義的情況
  • 建議方式: Include guard
Include guard example
1
2
3
4
5
6
#ifndef MY_HEADER_H
#define MY_HEADER_H

#define MY_VAR (1)

#endif /* MY_HEADER_H */

Computed Includes

  • 用來節省太多條件式#include如
條件式include
1
2
3
4
5
#ifdef LINUX
    #include <linux_plat.h>
#else
    #include <windows_plat.h>
#endif
  • 使用方式
C檔案
1
#include MY_DEF_H
Makefile
1
CFLAGS=-DMY_DEF_H="<linux_plat.h>"

System Headers

  • GCC會忽略掉系統標頭檔的Warning,如果其他一般標頭檔想要有相同的處理方式,可以使用-isystem 路徑讓GCC將該目錄下的標頭檔視為系統標頭導

  • 回目錄

巨集

  • Marco分成
    • 擬函數巨集: #define foo(): 重點是(),()前面不得有空格
      • 定義完後可以直接當作function使用,所以可以玩callback = foo;這樣的描述
    • 資料相關巨集

擬函數巨集

  • 擬函數巨集可以吃參數,以,分開。所以MAC(buf[x = 1, u + 1])這樣的程式碼會被拆成兩個參數,請使用MAC((buf[x = 1, u + 1]))
  • 擬函數巨集的參數可以空白,多個參數請用,隔開。
擬函數巨集參數空白範例
1
2
3
4
5
6
#define MY_MAC(x,y) my_mac(x,y)
...
MY_MAC(,);
MY_MAC(a,b);
MY_MAC(a,);
MY_MAC(,b);
  • 擬函數巨集定義的描述如果有使用"並且和參數相同,最後並不會被替換。
    • FOO(X) _bar(x, "x"); -> FOO(bar) _bar(bar, "x");

字串轉換

1
#define ENCLOSE_QUOTE(VAR) #VAR
  • ENCLOSE_QUOTE(test); -> "test"
1
2
3
#define PLAY 0
#define ENCLOSE_QUOTE(VAR) #VAR
#define TO_STR(VAR) ENCLOSE_QUOTE(VAR)
  • ENCLOSE_QUOTE(PLAY); -> "PLAY"
  • TO_STR(PLAY) -> ENCLOSE_QUOTE(0) -> "0"
    • 利用擬函數巨集展開參數的特性

合體

echo -e "#define MYDEF(PARAM1, PARAM2) PARAM1##PARAM2 \n\n MYDEF(xxx, yyy)" | gcc -E -x c -

Variadic Macros: 兩種方式,不能一個巨集同時使用

  • C99語法:#define my_printf(...) printf("myprintf: " __VA_ARGS__)
  • GNU語法:#define my_printf(arg...) printf("myprintf: " args)
  • 可以在varidic marco中明確指定參數
    • #define my_printf(format, ...) fprintf(stderr, format, __VA_ARGS__)
      • 缺點: 使用my_printf("test");會GG,因為被轉成fprintf(stderr, "test",);
      • 解法: #define my_printf(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
        • GNU會把, 硬食掉

GNU C支援的predefined Macros (節錄)

標準Macro: 可以望文生義就不解釋了

  • __FILE__
  • __LINE__
  • __func__
    • GCC也有一樣功能的__FUNCTION__
  • __DATE__
  • __TIME__
  • __STDC__:顯示目前是否使用Standard C編譯程式碼
  • __STDC_VERSION__:Standard C版本
  • __cplusplus:是否為C++編譯環境
  • __OBJC__:是否為object C編譯環境
  • __ASSEMBLER__:是否在組合語言環境

GNU Marco

  • __COUNTER__:回傳一個從0開始的數字,每次呼叫一次加一
  • GCC版本
    • __VERSION__
    • 細部版號
      • __GNUC__
      • __GNUC_MINOR__
      • __GNUC_PATCHLEVEL__
  • __GNUG__:是否是用GNU C++
  • __INCLUDE_LEVEL__:標頭檔被引用的深度,從0開始算。如a->b->c,c就是2
  • __ELF__:輸出格式是否為elf
  • __TIMESTAMP__

系統內建Macro

  • 和平台有關,使用下面指令查詢:echo "" | gcc -x c -E -dM -
  • C標準規範使用__包夾或是_+大寫為系統內建Macro,其name space保留。

Undefine/Redefine

Undefine/Redefine範例
1
2
3
4
#define FOO BAR
...
#undef FOO
#define FOO BAR2

密技和怪招

Misnesting

  • 間接呼叫
間接呼叫範例
1
2
3
4
#define MY_PRT(X) printf(x)
#define P_TEST(M) M("test")
...
P_TEST(MY_PRT);
  • 不對稱的括號
不對稱的括號範例
1
2
3
#define TEST(x) func1(x, "test"
...
test(my_param));
  • 硬食分號
test.c
1
2
3
4
5
6
#define MY_TEST(x) { printf("test\n"); }
...
    if (bit)
      MY_TEST(bit);
    else
      printf("else\n");

編譯會錯誤,原因是因為分號會讓gcc判斷if statement已經結束

錯誤訊息
1
2
3
4
cc     test.c   -o test
test.c: In function ‘main’:
test.c:23:5: error: ‘else’ without a previous ‘if’
make: *** [test] Error 1
  • 解法: do {...} while (0)
test.c
1
2
3
4
5
6
#define MY_TEST(x) do { printf("test\n"); } while(0)
...
    if (bit)
      MY_TEST(bit);
    else
      printf("else\n");

  • 除非明確了解巨集內容,否則避免直接傳函數進去巨集。MY_TEST(func(xy,xx), 10));

    • 原因是巨集內也許會呼叫參數好幾次,如果傳進去的函數執行成本很高,就會發生悲劇。
  • 回目錄

Preprocessor Output

  • 可以使用gcc -E 檔案或是cpp 檔案觀察CPP的展開,和CPP相關格式請參考這邊
  • 回目錄

gcc和CPP相關的參數

  • 大部分選項和參數可以以空白隔開(-I /usr/include)或是直接連在一起(-I/usr/include)

節錄

  • -D 文字: 定義文字巨集為1
    • 測試echo "TEST" | gcc -E -xc -DTEST -
  • -D 文字=文字:定義文字巨集
    • 測試echo "TEST" | gcc -E -xc -DTEST=CPP -
  • -U: undefine 巨集,如果參數同時有-U-D的話優先先出現的先做
  • -I dir:指定搜尋header file目錄
    • dir=開頭,gcc會取代成sysroot路徑,參考--sysroot-isysroot
  • -M:列出要檔案要吃的source code和header files
    • 測試:
-M範例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ gcc -M b.c
b.o: b.c /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdint.h \
 /usr/include/stdint.h /usr/include/features.h \
 /usr/include/x86_64-linux-gnu/bits/predefs.h \
 /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/stdio.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \
 /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h b.h
  • -MM:列出要檔案要吃的source code和非系統的header files
範例
1
2
$ gcc -MM b.c
b.o: b.c b.h
  • -MF file:配合-M, -MM時將結果寫入file
  • -MG: -M, -MMparse到header file不存在會跳錯誤,而加上-MG後會假裝他們存在,照樣吐出結果。
-MG範例
1
2
3
4
5
6
$ mv b.h a
$ gcc   -MM b.c
b.c:3:15: fatal error: b.h: No such file or directory
compilation terminated.
$ gcc -MG  -MM b.c
b.o: b.c b.h
  • -MP: 順便把depend的target加入
-MP範例
1
2
3
4
$ gcc -MP -MM b.c
b.o: b.c b.h

b.h:
  • -MT :指定target
-MT範例
1
2
$ gcc -MT test -MM b.c
test: b.c b.h
  • -MD: 直接編譯,同時把會吃的檔案和header files放在*.d檔
-MD範例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ rm a.out
$ gcc -MD b.c
$ ls a.out
a.out
$ cat b.d
b.o: b.c /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdint.h \
 /usr/include/stdint.h /usr/include/features.h \
 /usr/include/x86_64-linux-gnu/bits/predefs.h \
 /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/stdio.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \
 /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h b.h
  • -MMD: 直接編譯,同時把會吃的檔案和非系統header files放在*.d檔
-MMD範例
1
2
3
4
5
6
$ rm a.out
$ gcc -MMD b.c
$ ls a.out
a.out
$ cat b.d
b.o: b.c b.h
  • -dM: 列出編譯時所有的巨集,不列出展開巨集的結果, 通常配合-E
  • -dD: 列出編譯時不包含predefine的巨集以及展開巨集的結果, 通常配合-E
  • -dN: 和-dD的差別是巨集只列出名稱不列出要展開的內容, 通常配合-E
    • #define foo bar -dD輸出 #define foo bar-dN結果 #define foo
  • -dI:不顯是巨集,而是顯示#include的指令
  • -C: 保留註解,不包含巨集展開的部份註解
  • -CC: 保留註解,包含巨集展開的部份註解
  • -H:列出編譯時會參考的header files

  • 回目錄

參考資料

b.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdint.h>
#include <stdio.h>
#include "b.h"


#define foo  (bit,lfsr) /* XXX */
#define bar(x) lose(x)
#define lose(x) (1 + (x))

#if aaa
#define ddd ddds
#endif

int main(void)
{
    uint16_t lfsr = time(0);
    unsigned bit;
    unsigned period = 0;
    int c= 644;

    printf("%s\n", __BASE_FILE__);
    printf("%s\n", __VERSION__);
    if (bit)
        MY_TEST(bit);
    else
        MY_TEST(bit);
        printf("%d\n", (lfsr,bit,c));
        printf("%d\n", (bit, lfsr));

#line 10
printf("test:%d, %s\n", __LINE__, __FILE__);

#if 0
    lfsr = typeof(bit) 10;
#endif

    bar(foo);
printf("test:%d, %s\n", __LINE__, __FILE__);

    return 0;
}
b.h
1
#define MY_TEST(x) do { printf("test\n"); } while(0)

FreeRTOS 筆記

| Comments

出處:The Architecture of Open Source Applications (Volume 2): FreeRTOS

目錄

簡介

  • FreeRTOS是基於GPLv2授權的開源自由RTOS
  • 支援多種平台架構

架構

  • FreeRTOS元件有三個
    • Tasks:使用者行撰寫含有優先權的C語言程式碼,為RTOS執行的單位
    • Communication:提供Tasks和中斷之間溝通的管道
    • 硬體包裝層:提供介面分隔操作實際硬體和RTOS行為
  • 軟體階層
    • User task和ISR
    • 硬體抽象化後的程式碼
    • 硬體相關程式碼
      • 放置於: FreeRTOS/Source/portable/平台
        • port.c/ portmacro.h
    • 硬體
  • FreeRTOS/Demo/[平台]/FreeRTOSConfig.h存放硬體相關設定如Clock和stack size等
  • FreeRTOS透過巨集來將硬體無關的程式碼對應到硬體相關的實作

Task Scheduling

  • FreeRTOS使用陣列list來管理task Prority
    • static xList pxReadyTasksLists[ configMAX_PRIORITIES ];
  • 每次tick中斷起來就叫一次vTaskSwitchContext()
  • vTaskSwitchContext()
    • 根據優先權從ready list由高到低挑出一個list
      • 如果高優先權已經沒有task,再從下一個優先權list挑
    • 從該list中挑出上一次跑過的task下一個task
    • 開始執行task

Tasks

  • TCB: Task control block,為FreeRTOS的重要資料結構,提供
    • Stack資訊
    • List資訊
    • Event資訊
    • 優先權
  • Task狀態:每一個狀態就是對應到一個task list
    • Running
    • Ready
    • Suspend
    • Block

Create Task流程

  • 產生並設定TCB
  • 設定stack及硬體context switch 會用到的暫存器
  • Disable 中斷避免有人更動TCB資訊
  • 把TCB加入List中、系統初始化還會Init list
    • Ready list
    • Suspend list
    • Kill list
    • Delay list
  • 處理完list後enable中斷

Lists

  • FreeRTOS list使用doule 環狀link
  • list node會指向一個TCB
  • list 依xItemValue順序排列
  • list 會指向container,該container提供
    • list node個數
    • 起始node
    • 結束node
    • 指到目前系統處理的node

[Ubuntu 16.04] 安裝完系統後新增工具整理

| Comments

安裝完作業系統後還需要裝一些平常使用的工具,順手整理一下

目錄

懶人包

  • 第一次更新
1
sudo apt update && sudo apt install aptitude && sudo aptitude upgrade -y --full-resolve
  • 更新
1
sudo apt update && sudo aptitude upgrade -y --full-resolve && sudo apt autoremove
  • 全部來
1
sudo apt install -y aptitude build-essential bison flex automake libtool intltool  libncurses5-dev git-svn tig meld cscope vim-gtk fonts-inconsolata geany joe doxygen-gui exuberant-ctags manpages-dev manpages-posix-dev minicom tree terminator ttf-mscorefonts-installer ack-grep pandoc gnome-system-tools ghex mc dict wireshark mtr pdfgrep sshfs fail2ban rkhunter bc libssl-dev cmake gdb libatk-adaptor libgail-common
  • 從Server安裝後再裝Mate,安裝完記得關掉/etc/network/interfaces
1
sudo apt install -y lightdm mate-desktop-environment language-selector-gnome hime lightdm-gtk-greeter
  • 從Server安裝後再裝LxQT,安裝完記得關掉/etc/network/interfaces
1
sudo apt install -y lightdm lxqt language-selector-gnome hime lightdm-gtk-greeter
  • 安裝Hardware Enhance 相關套件
1
sudo apt install -y linux-image-generic-hwe-16.04 xserver-xorg-hwe-16.04 
  • 單一選擇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
sudo apt-get install build-essential
sudo apt-get install bison 
sudo apt-get install flex
sudo apt-get install automake
sudo apt-get install libtool
sudo apt-get install intltool
sudo apt-get install libncurses5-dev
sudo apt-get install bc
sudo apt-get install libssl-dev
sudo apt-get install gdb

sudo apt-get install git-svn
sudo apt-get install tig
sudo apt-get install meld
sudo apt-get install cscope
sudo apt-get install vim-gtk
sudo apt-get install fonts-inconsolata
sudo apt-get install geany
sudo apt-get install joe
sudo apt-get install doxygen-gui
sudo apt-get install exuberant-ctags
sudo apt-get install manpages-dev
sudo apt-get install manpages-posix-dev
sudo apt-get install minicom

sudo apt-get install tree
sudo apt-get install terminator
sudo apt-get install ttf-mscorefonts-installer 
sudo apt-get install ack-grep
sudo apt-get install pandoc
sudo apt-get install gnome-system-tools
sudo apt-get install ghex
sudo apt-get install mc
sudo apt-get install dict
sudo apt-get install wireshark
sudo apt-get install mtr
sudo apt-get install pdfgrep
sudo apt-get install sshfs
sduo apt-get install aptitude

sudo apt-get install fail2ban
sudo apt-get install rkhunter

sudo apt-get install libatk-adaptor
sudo apt-get install libgail-common

工具分類及簡單說明

系統程式開發套件 (不解釋)

  • build-essential
  • bison
  • flex
  • automake
  • libtools
  • intltool
  • libncurses5-dev
  • libssl-dev
  • bc
  • cmake
  • gdb

程式開發輔助工具

  • git-svn
    • git, svn, git-svn三個願望一次滿足
  • tig
    • 文字介面的git管理工具
  • meld
    • GUI介面的檔案比較工具
  • cscope
    • 追蹤程式碼工具,可以查詢函數被誰呼叫,宣告等功能。請配合vim服用
  • exuberant-ctags
    • 追蹤程式碼工具,可以切入函數呼叫等功能。請配合vim服用
  • vim-gtk
    • vim和gvim兩個願望一次滿足
  • fonts-inconsolata
    • 給開發程式時的GUI編輯器使用,因為不希望因為粗體斜體等效果干擾字元對齊
  • geany
    • 簡單好用的GUI編輯
  • joe
    • 文字介面的WordStar式介面編輯器
  • doxygen-gui
    • 文件產生器和他的Front UI
  • ghex
    • GUI 16進位檔案檢視工具
  • manpages-dev
    • 更多男人
  • manpages-posix-dev
    • POSIX男人,查phread用
  • minicom
    • Serial port終端機工具

一般工具

  • tree
    • 文字介面使用樹狀結構顯示檔案
  • terminator
    • 增強版gnome-terminal,可以同一個畫面任意新增分割的終端
  • ttf-mscorefonts-installer
    • 主要是要Wingdings字型,有一堆有趣的向量ICON可以用
  • ack-grep
    • 學長推荐的加強版grep,還不熟
  • pandoc
    • 吃markdown語法產生其他文件如pdf
  • gnome-system-tools
    • 需要GUI使用者管理所以安裝
  • mc
    • 文字介面的norton commander介面式檔案管理工具,除了複製搬移外、還可以解壓縮檔案
  • dict
    • 文字介面查英文單字用
  • wireshark
    • 分析封包的工具
  • mtr
    • 加強版的ping + tracert工具
  • pdfgrep
    • grep pdf檔案的工具
  • sshfs
    • 可以透過ssh mount遠端的帳號
  • aptitude
    • 另外一種套件操作方式aptitude upgrade --full-resolve -y我常用
  • libatk-adaptor libgail-common
    • gvim不會出現下面錯誤訊息
1
2
Gtk-Message: Failed to load module "gail"
Gtk-Message: Failed to load module "atk-bridge"

資安工具

  • rkhunter
    • 掃rootkit 的工具
  • fail2ban
    • 自動ban掉固定時間內重複嘗試連線ssh等的工具,中文簡介

學習: Markdown語法簡介

| Comments

對於技術文件寫作來說,能夠省去複雜語法和繁複操作,同時又能方便的寫出好的架構和論述很重要。因此我需要

  • 直接在本文中加入簡單的Tag語法省去滑鼠操作時間
  • 明顯地文章段落顯示方式
  • 方便的支援巢狀條列語法
  • 美觀地顯示程式語言代碼

為了做出好的文件,了解並學習Markdown語法是必經的路程。就讓我邊查資料現學現賣吧。

目錄

參考資料

語法說明

注意!有些效果可以透過不同語法達成。 本文只列出我感興趣的語法,並沒有列出完整的語法。

標題

## 主標題
### 次要標題
#### 更次要標題,最多到6個#

主標題

次要標題

更次要標題,最多到6個

Bullet List

- 第一層List
    - 第二層List,和第一層隔4個空白字元或是tab
        - 第三層List,和第二層隔4個空白字元或是tab
  • 第一層List
    • 第二層List,和第一層隔4個空白字元或是tab
      • 第三層List,和第二層隔4個空白字元或是tab

數字 List

1. 第一層List
    1. 第二層List,和第一層隔4個空白字元或是tab
        1. 第三層List,和第二層隔4個空白字元或是tab
  1. 第一層List
    1. 第二層List,和第一層隔4個空白字元或是tab
      1. 第三層List,和第二層隔4個空白字元或是tab

撒尿牛丸 List

1. 第一層List
    - 第二層List,和第一層隔4個空白字元或是tab
        1. 第三層List,和第二層隔4個空白字元或是tab
  1. 第一層List
    • 第二層List,和第一層隔4個空白字元或是tab
      1. 第三層List,和第二層隔4個空白字元或是tab

分隔線

***

字型

*斜體字,字和星號中間不能空白*

斜體字,字和星號中間不能空白

**粗體字,字和星號中間不能空白**

粗體字,字和星號中間不能空白

連結

[本站](http://wen00072.github.io)

本站

Code

  • 因為要顯示程式碼,所以不會Markdown的語法
    • 方式
      1. 行首以tab或8個空白開始
      2. 使用成對的`把程式碼包起來

 - 這個bullit 效果沒有出來  - 這個bullit 效果沒有出來

 ̀我是程式碼 ̀ 我是程式碼

引用

> 第一層引用
>> 第二層引用

第一層引用

第二層引用

段落用斷行

行尾沒有空白字元
第二行

行尾沒有空白字元 第二行

行尾加上兩個以上空白字元  
第二行

行尾加上兩個以上空白字元
第二行

如何做出目錄

  1. 在文件中嵌入HTML的anchor tag
  2. 同樣的文件中指定連結
1
2
<a name="test"></a>
[連連看](#test)

連連看

GitHub Flavored Markdown

刪除線

~~打我啊笨蛋,~和句子中間一樣不能有空白~~

打我啊笨蛋,~和句子中間一樣不能有空白

Fenced code blocks

GitHub Flavored Markdown語法

使用

```
把程式包起來

1
2
3
4
5
6
7
8
 ```
 #include <stdio.h>
 int main(void)
 { 
  printf("Hello World\n");
  return 0;
 }
 ```
1
2
3
4
5
6
 #include <stdio.h>
 int main(void)
 { 
  printf("Hello World\n");
  return 0;
 }

Octopress的語法

Octopress的語法讓使用者提供

  • 指定語言Highlight
  • 標題
  • URL
  • URL文字說明
1
2
3
4
5
6
7
8
 ```c 標題 http://wen00072.github.io URL文字說明
 #include <stdio.h>
 int main(void)
 { 
  printf("Hello World\n");
  return 0;
 }
 ```
標題URL文字說明
1
2
3
4
5
6
 #include <stdio.h>
 int main(void)
 {
  printf("Hello World\n");
  return 0;
 }

Shell Script: 番茄式時間管理法

| Comments

這是從The clean coder中文版看到的時間方式,本來想要找看看Ubuntun上面有沒有現成軟體可以用。後來看到有人使用Shell Script去弄一個。手癢也來做一個自己的版本。

番茄式時間管理法簡介

  • Francesco Cirillo 在1980年代末提出來的時間管理方式

運作原則

  1. 設定計時器二十五分鐘,這段時間內專心做事
  2. 二十五分鐘時間到休息五分鐘
  3. 1 和 2 總共重覆四次後休息長一點的時間

測試環境

  • Ubuntu 12.04
  • bash

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/bin/bash
## Inspired by http://navaneeth.github.io/blog/2010/12/19/simple-egg-timer-on-linux-for-pomodoro-technique/
## info: http://en.wikipedia.org/wiki/Pomodoro_Technique

## Function
function start_timer_minutes() ## Unit is minute
{
    time_elapse_minutes=0
    expire_period_minutes=$1

    while [ $time_elapse_minutes -lt $expire_period_minutes ] ; do
       sleep 60
       time_elapse_minutes=$(($time_elapse_minutes + 1))
       echo "$time_elapse_minutes minute(s) elapse of $expire_period_minutes minutes at iteration $((pomodori+1)).";
    done
}

## Check options
if [ $## -eq 2 ] ; then
    work_period_minutes=$1
    break_period_minutes=$2
elif [ $## -eq 0 ] ; then
    work_period_minutes=25
    break_period_minutes=5
else
    echo $0 expire_period_minutes break_period_minutes
    exit
fi

## Info variables
alert_title="Pomodoro"
start_message="Pomodoro started. You have $work_period_minutes minutes left"
end_message="Pomodoro ended. Take a short break for $break_period_minutes minutes."
max_pomodori=4

## pomodori, 4 iterations
pomodori=0
while [ $pomodori -lt $max_pomodori ] ; do
    ## Work time
    notify-send -u critical -i appointment -t 600 "$alert_title" "$start_message at iteration $((pomodori+1))"
    start_timer_minutes "$work_period_minutes"

    ## Rest time
    if [ $pomodori -lt $((max_pomodori - 1)) ] ; then
      notify-send -u critical -i appointment -t 600 "$alert_title" "$end_message"
      start_timer_minutes "$break_period_minutes"
    fi

    pomodori=$((pomodori + 1))
done

notify-send -u critical -i appointment -t 600 "$alert_title" "Time's up.. Take a longer rest."
echo "Time's up.. Take a longer rest."

參考資料

筆記: [OpenStack] GIT Commit Good Practice

| Comments

出處:[OpenStack] GIT Commit Good Practice

  • 大部份的程式碼是被閱讀的次數遠大於更動的次數,因此可讀性很重要。

如何結構化地切割變動?

  • 原則:每次的commit應該只包含一個邏輯上的變動

commit時該避免的事

  • commit的部份把空白字元更動(如空白從8個換成4個、TAB換成空白字元)和程式變動混在一起
  • 把和commit宣稱要改新功能無關的程式碼一起commit進去
  • 一次commit 大量的程式碼

關於Commit訊息

  • 不要假設審查者會瞭解該commit原本要處理的問題,所以不要忘記留下關於你要修掉的問題的描述和資訊,省去審查者自行查找的時間
  • 由於git的特性,審查者不一定只在電腦可以連上網路時審查您的commit。因此請將在commit留下足夠的訊息而不是要求別人去連到某個外部連結去參考資料
  • 不要自以為程式碼明顯易懂就在commit訊息偷懶省略資料。提供問題描述、解決方式和更動會比較週全
  • 請描述更動程式碼的理由和目的
  • 如果您的commit訊息需要長篇大論的說明時,也許是個好時機去分拆commit成更細小的commit
  • 如果很不幸地必須要commit大量的程式碼,請務必在commit 訊息中提供資訊讓審查者便於審查這大堆頭的程式碼
  • commit訊息的第1行非常重要。可以用在email的標題、log viewer的提示等。請想辦法在一行的長度讓閱讀log的人瞭解你commit了什麼資訊
  • 如果程式碼有已知錯誤、Todos、或是limitation也記得一併寫在commit訊息中

OpenStack 使用的commit 訊息格式

  • 第1行簡略描述該commit更動的內容,字數小於50字元,結尾不得有句點
  • 第2行單純為跳行符號
  • 第3行以後開始詳細描述更動的範圍,長度不得超過72字元
    • 描述問題狀況
    • 對應問題的更動描述,以及更動的理由說明
    • 提供更動後的結果範例
    • Limitation,改善空間等
  • 軟體管理用的辨別ID如Change-id等