なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

GitHubはじめました。

Posted by arms22 on 2013年07月18日 0  0

GitHub-Logo
Octocat

GitHubはじめました。これまでArduinoのライブラリやスケッチはGoogle Codeを利用して管理していましたが、今後はGitHubを利用して管理することにしました。Google CodeのUIは一昔前のデザインのままでイケテナイし、Google Readerみたいにいつサービスが終了するかわからないからね。今のうちにデータを移しておこうかなと。

arms22 - GitHub
https://github.com/arms22

以下、導入時のメモ。


Gitインストール



次のページからdmgをダウンロードして、Gitのコマンドラインツールをインストールします。インストーラーと一緒に配布されているパス設定用のシェルも実行します。

Git - Downloads
http://git-scm.com/downloads

インストールが終わったらバージョンを確認します。
$ git version
git version 1.8.3.2
メールアドレスとニックネームを設定します。
$ git config --global user.name "Your Name Here"
$ git config --global user.email "your_email@example.com"
Gitコマンドの使い方は次のページで解説されています。

Git - Book(日本語)
http://git-scm.com/book/ja/

Mac用のGUIクライアントもあります。ただOS X 10.7 Lion以上でないと動かないみたい。

GitHub for Mac
http://mac.github.com/


GitHubのアカウント取得


GitHubに移動してアカウントを取得します。
http://github.com/


SSHキーの登録


新しい公開鍵を作成してGitHubに登録します。pbcopyコマンドで公開鍵をクリップボードにコピーしています。
$ cd ~/.ssh
$ ls
$ ssh-keygen -t rsa -C "your_email@example.com"
$ pbcopy < ~/.ssh/id_rsa.pub
GitHubの設定ページに移動し公開鍵を登録します。クリップボードの内容をテキストボックスに貼付けて、適当な名前を付けます。
https://github.com/settings/ssh


リモートリポジトリの作成

 
GitHubのページでリポジトリを作成します。リポジトリの名前(ユニークな名前)と概要を記載して作成します。有料アカウントなら非公開リポジトリも作れます。
https://github.com/new


ローカルリポジトリの作成


GitHubで管理したいプロジェクトのディレクトリに移動します。
cd WattMeter
ディレクトリ直下にREADMEファイルをおくのが習わしです。
touch README.md
ローカルリポジトリを初期化し、ディレクトリ直下のすべてのファイルを追加します。そして最初のコミットを行います。この時点ではまだリモートリポジトリにファイルは追加されていません。
$ git init
$ git add .
$ git commit -m "first commit"
リモートリポジトリのURLをローカルリポジトリに追加し、リモートリポジトリに変更内容をプッシュします。
$ git remote add origin git@github.com:arms22/WattMeter.git
$ git push -u origin master
GitHubのリポジトリのページに移動すると先ほどプッシュした内容が反映されているのがわかると思います。

https://github.com/arms22/WattMeter

すでにGitで管理しているプロジェクトがある場合は、リモートリポジトリの追加とプッシュのみ行えばよいでしょう。
git remote add origin git@github.com:arms22/WattMeter.git
git push -u origin master



参考URL


そもそもGitHubとは一体何か?
http://jp.techcrunch.com/2012/07/15/20120714what-exactly-is-github-anyway/

はじめてのgithub
http://blog.katsuma.tv/2009/02/first_github.html

MacでGithubにレポジトリを作ってアップロードするまでをまとめる
http://d.hatena.ne.jp/goryugo/20081026/1225007428

ナウなヤングのためのgithub入門講座 -基本機能からdotfiles管理まで-
http://d.hatena.ne.jp/shim0mura/20111212/1323660740


入門git
入門git
posted with amazlet at 13.07.18
Travis Swicegood
オーム社
売り上げランキング: 44,280



C言語でコルーチン(co-routine)(4)

Posted by arms22 on 2008年04月12日 0  0

C言語でコルーチンを実装してみる、その4。今回でコルーチンの連載(?)は最後です。最後にコルーチンを使った協調型スレッドライブラリを実装します。さっそくサンプルコードから見ていきましょう。

int thread1_count=0;
int thread1_func(coroutine_t coro)
{
co_begin(coro);
while(1){
thread1_count++;
co_yield();
}
co_end;
}

int thread2_count=0;
int thread2_func(coroutine_t coro)
{
co_begin(coro);
while(1){
thread2_count++;
co_yield();
}
co_end;
}

int thread3_count=0;
int thread3_func(coroutine_t coro)
{
co_begin(coro);
while(1){
thread3_count++;
co_yield();
}
co_end;
}

int main(int argc, char *argv[])
{
struct cothread_scheduler schdlr;
cothread_t thread1;
cothread_t thread2;
cothread_t thread3;
int thread1_stack[32];
int thread2_stack[32];
int thread3_stack[32];

/* 協調型スレッド作成 */
thread1 = cothread_create(thread1_func,(co_addrword_t)1,
thread1_stack,sizeof(thread1_stack));
thread2 = cothread_create(thread2_func,(co_addrword_t)2,
thread2_stack,sizeof(thread2_stack));
thread3 = cothread_create(thread3_func,(co_addrword_t)3,
thread3_stack,sizeof(thread3_stack));

/* スケジューラ作成 */
cothread_scheduler_init(&schdlr);

/* スレッドアタッチ */
cothread_scheduler_attach(&schdlr,thread1);
cothread_scheduler_attach(&schdlr,thread2);
cothread_scheduler_attach(&schdlr,thread3);

/* 実行 */
cothread_scheduler_run(&schdlr);
printf("thread1_count %d, thread2_count %d, thread3_count %d?n",
thread1_count,thread2_count,thread3_count);
cothread_scheduler_run(&schdlr);
printf("thread1_count %d, thread2_count %d, thread3_count %d?n",
thread1_count,thread2_count,thread3_count);
cothread_scheduler_run(&schdlr);
printf("thread1_count %d, thread2_count %d, thread3_count %d?n",
thread1_count,thread2_count,thread3_count);
}
実行結果は次のとおり。
% a.exe
thread1_count 1, thread2_count 1, thread3_count 1
thread1_count 2, thread2_count 2, thread3_count 2
thread1_count 3, thread2_count 3, thread3_count 3
コルーチン関数の書き方は何も変わっていない。コルーチンの作成関数が協調型スレッドの作成関数に置き換わっているのがわかる。順番に見ていこう。
  • cothread_create()
    協調型スレッドの作成関数だ。内部でco_create関数を呼び出す。引数はco_create関数と同じだ。第1引数にコルーチン関数のアドレスを渡す。戻り値としてcothread_t型にキャストしたスタックのアドレスを返す。
  • cothread_scheduler_init()
    スレッドスケジューラの初期化関数だ。スケジューラの初期化を行う。今回実装したスケジューラはアタッチされたスレッドを順番に実行するラウンドロビン方式を採用している。
  • cothread_scheduler_attach()
    スケジューラにスレッドをアタッチする関数だ。
  • cothread_scheduler_run()
    アタッチされたスレッドを1つ1つ実行する。すべてのスレッドを1度実行した後、処理を呼び出し元に返す。

協調型スレッドを含むコルーチンライブラリの全ソースコードはこちら。
http://xfind.hp.infoseek.co.jp/electric/coroutine/coroutine_20080410.zip

C言語でコルーチン(co-routine)(3)

Posted by arms22 on 2008年04月11日 0  0

C言語でコルーチンを実装してみる、その3。
前回でローカル変数の問題、状態を制御できない問題は解決した。今回はコルーチンで値を返す処理を追加した。例によって、まずはサンプルコードから。

int num_gen(coroutine_t coro)
{
co_begin_rettype(coro,int);
co_local_valiables{
int number;
};
co_local.number = 0;
while(1){
co_yield_ret(co_local.number++);
}
co_end;
}

int main(int argc, char *argv[])
{
coroutine_t gen1;
coroutine_t gen2;
int stack1[128];
int stack2[128];
int i;

gen1 = co_create(num_gen,0,stack1,sizeof(stack1));
gen2 = co_create(num_gen,0,stack2,sizeof(stack2));

for(i=0;i<10;i++){
co_call(gen1);
co_call(gen2);
printf("gen1 result %d,gen2 result %d\n",
co_get_retval(gen1,int),
co_get_retval(gen2,int));
}
}
実行結果は次の通り。
% a.exe
gen1 result 0,gen2 result 0
gen1 result 1,gen2 result 1
gen1 result 2,gen2 result 2
gen1 result 3,gen2 result 3
gen1 result 4,gen2 result 4
gen1 result 5,gen2 result 5
gen1 result 6,gen2 result 6
gen1 result 7,gen2 result 7
gen1 result 8,gen2 result 8
gen1 result 9,gen2 result 9
num_gen関数はint型の値を、呼び出し毎に1ずつ増やして返す関数だ。今回追加したマクロはco_begin_rettype,co_yield_ret,co_get_retvalだ。順番に見ていこう。
  • co_begin_rettype(coro,int);
    コルーチンの開始と戻り値の型を決める。戻り値のサイズ分、スタックに空きを作る。
  • co_yield_ret(co_local.number++);
    スタックに戻り値を積んで、処理を中断し呼び出しもとに戻る。
  • co_get_retval(gen1,int)
    コルーチンの戻り値を型を指定して取り出す。
気になる(?)実装は次の通り。
#define co_begin_rettype(coro,type) \
type *__return_addr = (type*)((coro)+1); \
co_stack_t __stack_addr = (co_stack_t)(((int)(__return_addr+1)+3)&~3); \
switch((coro)->resume){ \
case CO_INITIALALIZE:;

#define co_yield_ret(value) \
do{ \
*__return_addr=value; \
return(__LINE__); \
case __LINE__:; \
}while(0)

#define co_get_retval(coro,type) \
(*((type*)((coro)+1)))
ローカル変数で使うスタックのアライメントを4バイトに調節している。

C言語でコルーチン(co-routine)(2)

Posted by arms22 on 2008年04月10日 0  0

C言語でコルーチンを実装してみる、その2。
前回のコルーチンマクロではローカル変数が使えない、外部から状態を制御できないという問題があった。今回はそれらの問題を解決してみる。まずはサンプルコードを見てほしい。

int hoge(co_routine_t coro){
co_begin(coro);
co_local_valiables{
int a;
int b;
};
co_local.a = 0;
co_local.b = 0;
printf("arg 0x%x\n",(int)co_get_addrword(coro));
while(1){
printf("a=%d b=%d\n",co_local.a++,co_local.b++);
co_yield();
}
co_end;
}

main{
co_routine_t coro;
int stack[32];
coro = co_create(hoge,0xaa,stack,sizeof(stack));
co_call(coro);
co_call(coro);
co_call(coro);
co_call(coro);
}
実行結果は次のとおり。
% a.exe
arg=0xaa
a=0 b=0
a=1 b=1
a=2 b=2
a=3 b=3
前回のコルーチンマクロから変わった所は、コルーチンの関数定義、co_beginマクロに引数を追加、co_local_variables/co_localマクロの追加、co_create/co_call関数の追加ぐらいだろうか。順番に見ていこう。
  • int hoge(co_routine_t coro)
    今回の実装ではコルーチン関数はco_routine_t型の引数とint型の値を返す必要がある。なもんで、呼び出す度に戻り値が変わる関数を作りたい場合には使えない。
  • co_begin,co_end
    毎度おなじみの"おまじない"。
  • co_local_valiables
    ローカル変数の宣言をここで行う。これらの変数はコルーチンが呼び出されている間は消えることはない。ローカル変数へのアクセスはco_localマクロを経由して行う。co_localは単純にスタックのアドレスをローカル変数用の構造体にキャストしているだけ。
  • co_yield()
    このマクロが呼ばれた時点でコルーチンは処理を中断し、関数を抜ける。次に呼ばれた時は、このマクロの次の行から処理が再開される。
  • coro = co_create(hoge,0xaa,stack,sizeof(stack))
    co_create関数を使ってコルーチンを作成する。第1引数にコルーチン関数のポインタ、第2引数にコルーチン関数に渡す引数、第3引数にスタックのアドレス、第4引数にスタックのサイズを渡す。スタックのサイズは最低、sizeof(関数ポインタ)+sizeof(コルーチン関数に渡す引数)+sizeof(int)分必要。作成に成功したらスタックのアドレスがco_routine_t型にキャストされて返される。失敗した場合は0が返る。
  • co_call(coro)
    コルーチン呼び出す。コルーチンでco_yieldマクロが呼ばれたら処理が返ってくる。
ソースコードは長いので続きに載せておくよ。

そうそう、マクロでちまちまやるのは嫌だという人にはPCL(Portable Coroutine Library)というポータブルなコルーチンライブラリがあるよ。PCLはcontext save/restoreでコルーチンを実現しているよ。setjmp、longjmpを駆使するみたい。

Portable Coroutine Library
http://www.xmailserver.org/libpcl.html

C言語でコルーチン(co-routine)

Posted by arms22 on 2008年04月07日 0  0

C言語でコルーチンを実装してみる。

コルーチン(co-routine)とはプログラミングの構造の一種。サブルーチンがエントリーからリターンまでを一つの処理単位とするのに対し、コルーチンはいったん処理を中断した後、続きから処理を再開できる。接頭辞co-は協調を意味するが、複数のコルーチンが中断/継続により協調動作を行う。

組み込みシステムではよく、複数の処理を同時に行う必要がある。そのような場合、コルーチンが使えれば、処理の記述が楽に行える。switch-caseあるいは関数テーブルなどを駆使すれば、実現することは可能だが、見通しがわるくなる。

コルーチンをサポートする言語にはModula-2、Simula、Icon、Lua、C#がある。マルチスレッドで原理的には同じことができるため、現在はそちらが使われるケースが多い。

組み込みシステムにおいても上記のことは言えるが、小規模なシステムの場合、リソースの制約上、処理1つ1つにタスクを割り当てることができず、1つのタスクで複数の処理を実行するケースも存在する。

今回、紹介するコルーチンはswitch-caseを巧みに利用して実現されている。次のコードは呼び出すごとに"Hello World"がテキトーになっていくHelloWorld関数だ。
void helloworld(void){
co_begin;

printf("hello world!!\n");
co_yield();

printf("hi world!\n");
co_yield();

printf("hi again.\n");
co_yield();

printf("hi\n");
co_yield();

printf(":)\n");
co_end;
}
main(){
helloworld();
helloworld();
helloworld();
helloworld();
helloworld();
}
実行結果は次の通り。
hello world!!
hi world!
hi again.
hi
:)
見慣れないキーワードが三つ。それぞれ簡単に説明すると、
  • co_begin
    コルーチンの開始
  • co_yield()
    処理の中断
  • co_end
    コルーチンの終了
co_begin,co_endはおまじないと思ってくれ。co_yieldについて説明しよう。
co_yieldは呼び出した時点で処理を中断し関数を抜けるんだ。次にこの関数が呼ばれた時、最後にco_yieldを呼び出したところから処理が再開される。
さて、気になるco_begin,co_yield(),co_endの実装を見てみよう。

#define co_begin              \
static int __state = 0; \
switch(__state){ \
case 0:

#define co_yield() \
do { \
__state = __LINE__; \
return; \
case __LINE__: \
break; \
} while(0);

#define co_end \
__state = __LINE__; \
}
うーん。なかなか良く出来たコードだ。switch-caseを巧みに利用しているのがわかる。もちろんこのマクロは完璧ではない。ローカル変数は使えないし、外部から状態を制御できない。PICなんかだと、1度動作を開始させた後、処理を止める必要がない場合が多いので、今回のマクロで十分かもしれない。

次回は、このコルーチンマクロをもう少し使い易く、ローカル変数を使えるようにしてみる。

コルーチン - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3

このカテゴリーに該当する記事はありません。