□メッセージキューの使い方(CとPHPでプロセス間通信)

0 comments

Posted on 20th 10月 2011 by admin in MEMO

C言語で作ったプロセス同士はもちろん、C言語で作ったプロセスとPHPで作ったスクリプト間でもメッセージキューであれこれやり取りしたい。手順としては、とりあえずC言語側でもPHPでも同じ。

 http://www.fireproject.jp/feature/c-language/ipc/message-queue.html

より、メッセージキューの実験

semmainで作ったセマフォをsemotherでロック、すると別のsemotherを起動すると先に起動したsemotherが終わるまで後からのは待つ

cat > sendque.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

// バッファサイズBUFSIZは8192バイトもあるのでもったいないから1024にする。
#define BUFFSIZE 1024

/* メッセージキューで送受信するメッセージ
   msgsnd,msgrcvの*msgpにはこの構造体へのポインタをいれる */
struct msgbuf{
  /* メッセージの先頭はかならずlong int型でなければならない */
  long int type;
  char data[BUFFSIZE];
};

int main(int argc, char *argv[])
{
  /* メッセージキューのID */
  int msqid;
  /* メッセージ */
  struct msgbuf message;

  /* パラメータチェック */
  if(argc != 3){
    fprintf(stderr,"Usage: %s type string\n",argv[0]);
    exit(EXIT_FAILURE);
  }else{
    /* messageのtypeは正でなければならない */
    if((message.type = atol(argv[1])) <= 0){
      fprintf(stderr,"type value is invalid\n");
      exit(EXIT_FAILURE);
    }
    strncpy(message.data,argv[2],BUFFSIZE);
  }

  printf("BUFFSIZEEは%0dバイトです\n",BUFFSIZE);

  /* メッセージキューの作成,取得 */
  errno = 0;
  if((msqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1){
    perror("msgget failure");
    exit(EXIT_FAILURE);
  }

  /* メッセージを送信 */
  errno = 0;
  if(msgsnd(msqid, &message, BUFFSIZE, 0) == -1){
    perror("msgsnd failure");
    exit(EXIT_FAILURE);
  }

  exit(EXIT_SUCCESS);
}

gcc -O2 sendque.c -o sendque

cat > rcvque.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

// バッファサイズBUFSIZは8192バイトもあるのでもったいないから1024にする。
#define BUFFSIZE 1024

/* メッセージキューで送受信するメッセージ
   msgsnd,msgrcvの*msgpにはこの構造体へのポインタをいれる */
struct msgbuf{
  /* メッセージの先頭はかならずlong int型でなければならない */
  long int type;
  char data[BUFFSIZE];
};

int main(int argc, char *argv[])
{
  /* メッセージキューのID */
  int msqid;
  /* メッセージ */
  struct msgbuf message;
  long int read_type;

  /* パラメータチェック */
  if(argc != 2){
    fprintf(stderr,"Usage: %s type\n",argv[0]);
    exit(EXIT_FAILURE);
  }else{
    /* 受信タイプの設定 */
    read_type = atol(argv[1]);
  }

  /* メッセージキューの作成,取得 */
  errno = 0;
  if((msqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1){
    perror("msgget failure");
    exit(EXIT_FAILURE);
  }

  while(1){
    /* メッセージの受信 */
    errno = 0;
    if(msgrcv(msqid, &message, BUFFSIZE, read_type, 0) == -1){
      perror("msgrcv failure");
      break;
    }else{
      fprintf(stdout,"received message:\t%s\n",message.data);
    }
    /* "exit"を受信すると終了する */
    if(strcmp(message.data, "exit") == 0){
      break;
    }
  }

  /* メッセージキューの削除 */
  errno = 0;
  if(msgctl(msqid, IPC_RMID, NULL) == -1){
    perror("msgctl failure");
    exit(EXIT_FAILURE);
  }

  exit(EXIT_SUCCESS);
}

gcc -O2 rcvque.c -o rcvque

できたら、

./sendque 111 aaaaa
./sendque 333 ccccc
./sendque 222 bbbbb
./sendque 444 ddddd
./sendque 555 exit

と送ってみて、別プロセスで

./rcvque 333

とかすると該当するtype(ID)のメッセージを取ってこれる

これをPHPで受けるとすると、上記のサンプルソースではキューのキーが「1111」なので、以下のようなスクリプトで存在を確認できる。

<?php

$QKEY = 1111;

if (msg_queue_exists($QKEY))
{
    print $QKEY."はあります\n";
}
else
{
    print $QKEY."がありません!?\n";
}
?>

このキューに実際にアクセスするには msg_get_queue() で一度リソースを取得する必要がある。

<?php

$QKEY = 1111;
$QUEUE = msg_get_queue($QKEY, 0666);

if (msg_queue_exists($QKEY))
{
//    var_dump(msg_stat_queue($QUEUE));
    // キューの先頭からの
    if (msg_receive($QUEUE, 0, $MSGTYPE, 4096, $MSGDATA, FALSE, MSG_IPC_NOWAIT | MSG_NOERROR, $ERRCODE) == TRUE)
    {
        print "TYPE:".$MSGTYPE." MSG:".$MSGDATA."\n";
    }
    else
    {
        if ($ERRCODE & MSG_NOERROR)
        {
            print "キューにデータがありませんでした!?\n";
        }
        else
        {
            print "キューから取得できませんでした!?\n";
        }
    }
}
else
{
    print "キューがありません!?\n";
}
?>

□Emacsでお気に入りのインデント

0 comments

Posted on 18th 10月 2011 by admin in MEMO

http://search.luky.org/vine-users.6/msg08634.html

これこれ!!まさにこれですよー。

( setq c-mode-hook
‘( lambda ()
( c-set-style “stroustrup” )
(setq indent-tabs-mode nil)
( setq c-basic-offset 4 )
))

スペースにしたかったのでこうしてみました。

http://q.hatena.ne.jp/1189586222

void main()
{
    if ()
    {
        hogehoge = 0;
    }
}

こういうインデントにしたかったのですよっ!! ヽ(´ー`)ノ

 

 

□VineLinuxでArduino(IDE)を動かす

0 comments

Posted on 13th 10月 2011 by admin in MEMO

□VineLinuxでArduino(IDE)を動かす

参考:http://trac.switch-science.com/wiki/AVR-GCC

VineLinux6でArduinoをいじりたくてソフトをインストールした時のメモ。

基本rootでやったほうが楽

・Javaのインストール

Synapticで「java-x.x.x-openjdk」をインストール。

・gmp-develのインストール

Synapticで「gmp-devel」をインストール。

・mpfr-develのインストール

Synapticで「mpfr-devel」をインストール。

・mpcのインストール

mpcはパッケージがないので

cd /usr/src/package/
wget http://www.multiprecision.org/mpc/download/mpc-0.9.tar.gz
cd /usr/src/
tar xvzf ./package/mpc-0.9.tar.gz
cd ./mpc-0.9
./configure --prefix=/usr
make
make install

・binutilのインストール

AVR用にカスタマイズしてインストールする。

http://www.freebsd.org/cgi/cvsweb.cgi/ports/devel/avr-binutils/files/patch-newdevices

にある最新パッチが当てられるbinutilsを落としてくるのがよい。

cd /usr/src/package/
wget http://ftp.gnu.org/gnu/binutils/binutils-2.20.1.tar.bz2
cd /usr/src/
tar xvjf ./package/binutils-2.20.1.tar.bz2
cd ./binutils-2.20.1
wget "http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/ports/devel/avr-binutils/files/patch-newdevices?rev=1.16;content-type=text%2Fplain" -O
binutils.patch
patch -p0 < binutils.patch
mkdir ./build
cd ./build
../configure --prefix=/usr/local/avr --target=avr --disable-nls
make
make install

※makeinfoの場所は問題ない。:-)

・avr-gccのインストール

4.6.xだとmake時にエラー、4.5.xでもダメらしい。
なので、特段対応チップ云々で困らないなら4.4.xで作る事をお薦め。

cd /usr/src/package
wget ftp://ftp.dti.ad.jp/pub/lang/gcc/releases/gcc-4.4.6/gcc-4.4.6.tar.bz2
cd /usr/src/
tar xvjf ./package/gcc-4.4.6.tar.bz2
cd ./gcc-4.4.6
mkdir ./build
cd ./build
../configure --prefix=/usr/local/avr --target=avr \
--enable-languages=c,c++ \
--disable-nls --disable-libssp --with-dwarf2 \
--with-gmp --with-mpfr --with-mpc

エラーがなければ

make
make install

・AVRライブラリのインストール

cd /usr/src/package
wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-1.7.1.tar.bz2
cd /usr/src/
tar xvjf ./package/avr-libc-1.7.1.tar.bz2
cd ./avr-libc-1.7.1
mkdir ./build
cd ./build
PATH=$PATH:/usr/local/avr/bin
export PATH
../configure --prefix=/usr/local/avr \
--build=`../config.guess` --host=avr

エラーがなければ

make
make install

※PATHを通すのがポイント

・ArduinoのIDEをインストール

AVRライブラリまでインストールできたら、一般ユーザなりに戻って
IDEをダウンロードしてきて展開。

http://arduino.cc/

からDownloadをクリックしてLinuxの32bitないしは64bitのどちらかを
クリックすると、Fxがダウンロードして書庫マネージャで開きますか?
と聞いてくるのでOKとして、そのまま自分のホームディレクトリで展開
すると、

./arduino-xxxx/

というフォルダが出来ているので、その中にある arduino を実行すれば
OK、なはず。エラーになったらPATHの設定をすること。

.bash_profileで

addpath /usr/local/avr/bin

とかすればOK。

…パッケージの作り方わすれてるなー、また講習会してほしいかも。:-)

さて、電子工作♪電子工作♪

 

□LinuxでUstream(ffmpeg使って高解像度配信!?)

0 comments

Posted on 28th 9月 2011 by admin in MEMO

実家のライブカメラが壊れたので、AxisとかPanasonicのネットワークカメラをあれこれ物色したけど、どうにも高いというか、また壊れたらなーと思って、今回はLinuxでUSBのWebCam使ってUstreamが出来ないかな、と調べてみた。

最近のLinuxならUSBウェブカムは大抵UVC対応なので、プスッと挿して最初から入っているビューアー(レコーダー)ソフトを使うと何の句もなく見ることが出来る。で、見れるのは/dev/video0とかにカメラが繋がっているからで、FlashについてもLinuxにちゃんとインストールできれば、最低解像度でさっくりUstreamが出来ちゃったりするんだけど、どう見てもこれってQCamレベルの画質(160×120)。

ビューアー(レコーダー)ソフトでは1280×720とか、カメラがサポートしている解像度で見れるので、それでやって欲しいんですけど…FireFoxとかでブラウザからやろうとすると無理みたい。

で、高解像度にするならFME…といいたいところだけど、Linux用のなんてでていない。

でていないけど、データとしては高解像度になっているので、これをUstream側にポイッとできればいいわけで、みんなあれこれがんばっています。

ちょっと前だとv4l2loopbackとかでループバックさせた上でWebcamstudioを使うとかがあったけど、でもJavaを入れたりとか面倒なのと、当然Javaなので重い。他にもデスクトップ配信をするためのツールが幾つかあったりするけど、こちとらWebCamの映像をそのままUstreamで中継したいのでちょっと違う。

で、2011年02月あたりに日経なんたらで、ffmpegを使ってFMEの代わりとし、高解像度で中継する、と言う記事が出たらしい。でもこれには落ちがあって、いろいろがんばっても二~三分(百数十秒)するとffmpegが止まるという。確かに試してみるとそれくらいで止まって、ご丁寧なことにコマンドプロンプトに戻る。
これはいただけない、なんでこんなの記事にした!?さすが日経なんたら。

いろいろ調べてみると、ffmpegは2010年06月あたりにlibrtmpを経由してrtmpプロトコルに対応するようになったらしい。rtmpプロトコルって何ぞや、と言うとFMEとかとUstream送出用クライアントとの間でやりとりするリアルタイムメッセージプロトコルというものらしい。

でもこれって時間と言うよりデータ量で止まってしまっているんじゃないかと思う。だいたい5MBちょい(6MB行かない)流すとぷつっと止まる。で、rtmpと5MBで検索するとこんなサイトが引っかかったりするので、なんか問題解決に少し近づいてきた感があるんですけどどうでしょう?

ま、もう少しがんばってみます。
HDなUSBカメラ(Microsoftとかロジクールのとか)で見てみると、すげーきれいにUstreamできるんで、何とかしたい。

2011.09.28 追記1

librtmpのmanは見たほうがいいね。Vine6のffmpegはPentium-M(1.3GHz…つまりThinkPad X31)にインストールするのにえらい時間がかかったけど、librtmpにも対応しているみたいだったし。と言うわけでリンクおいときます。

2011.09.28 追記2

家に帰ってきてから早速あることを試してみた。一度/dev/video0からflvフォーマットで5MBを超えるファイルが作れるかということから。これはあっさりと10MBが余裕で作れた。つづいて、作った10MBのファイルをflvのままrtmpで出力すると…4MBでffmpegが止まる。これはつまりffmpegがどうのというわけではなくて、librtmpがアレなのか、ffmpegがlibrtmpをうまく使えていないということか。ますますソースを見ないといけなくなりそうな感じだな…

2011.09.29 追記3

その後もあちこちウロウロしたり、GoogleChrome先生の力を借りながらあちこちの海外サイトを見ても、やっぱりffmpegではUstremがうまく出来ないらしい。

こんなサイトがあったので、自分も思うところがあってwiresharkを入れて見てみたけど、自分の場合には動きがちょっと違った。というか、ブラウザでUstreamで配信開始しなくても、単にffmpegでだらだら送信するだけでもやっぱりこけるのでなんだかよく判らない。まぁこのサイトの人もjustin.tvを薦めているみたいだし、確かにこれでもやりたかったことはできそうなので、Ustreamはあきらめてjustin.tvで長時間ストリーミングを試すことにする。

ちなみにffmpegが落ちても再びストリーミングを開始するようなシェルスクリプトにしたので、ストリーミングそのものはマシンかカメラでもハングしない限りは延々と続く…と思うんだけどどうでしょう?

2011.10.05 追記4

上記からjustin.tvにだらだらと長時間ストリーミングしているんですが、なんかしらのタイミングで中継が途切れたとしても、無限ループなスクリプトにしたので、見た感じずーっと中継しているように見えます。(過去の中継記録とかみると、10時間とか86時間くらい中継した形跡もある)

これでいいんじゃね?という気になってます。が、justin.tvのサイトを見てみると、時々いい解像度で中継している人がいるんだけど、これってH.264でストリーミングしているのかなぁ?X31だとそこまではちょっと非力なんじゃないかと思って試していないけど、気が向いたら試してみるかな?

2011.10.31 追記5

このサイトも収まっているサーバーにWEBCAMつなげようとしたら、Vine5.xでffmpegパッケージとかが古かったのでrtmpに対応していなかった。なのであらためて本家からffmpegの最新版(0.8.5)を取ってきてインストールしてみる。もともとVineはself-buildでffmpegを入れるので、残りの必要なライブラリ(librtmpとdevel)を入れて、もともとのパッケージのffmpegで表示される./configureオプションの最初の方だけ(笑)をコピーしてmakeしてみる。果たして!?

2011.11.02 追記6

気分的にはまだ11.01なんだけど、一応これを書いている時点では02日ってことで。
本シリーズ、衝撃の完結となりました。詳しくは「□LinuxでUstream(ffmpegで高解像度配信!!完結編)」をご覧ください。

 

□PHPでTwitter

0 comments

Posted on 31st 8月 2011 by admin in MEMO

PHPでツイートするのは超簡単。

ツイートするまでにアクセストークンとシークレットキーを取得するのが
ちょっと手間だけど、それはぐぐればやり方はでてくるのでここではパス。

Twitterにアプリを登録して「Access token」と「Access token secret」
を取得できたら、WEBサーバーにOAuthをインストール。

yum -y install pcre-devel
pecl install OAuth

はいったら、PHPの拡張モジュールとして登録して

cat >  /etc/php.d/oauth.ini

; Enable OAuth extension module
extension=oauth.so

で、あとは

<?
// タイムゾーンをシステムのそれに設定
date_default_timezone_set(@date_default_timezone_get());

$consumer_key    = ‘コンシューマキー’;
$consumer_secret = ‘コンシューマシークレットキー’;

$access_token = ‘アクセストークン’;
$access_secret = ‘アクセスシークレットキー’;

// 同じ内容のツイートは弾かれるらしいので、テストの場合には常に内容を変える!!
$tweet = date(“H:i:s”).”のツイートテストです。”;
$oauth = new OAuth($consumer_key, $consumer_secret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($access_token, $access_secret);
$oauth->fetch(“https://twitter.com/statuses/update.xml”,array(‘status’ => $tweet), OAUTH_HTTP_METHOD_POST);
?>

のようにしてツイートしてみればよい。

参考
http://blog.flatlabs.net/20100612_134307/
http://d.hatena.ne.jp/imaiworks/20100506/1273138592