Linda

Linda

# Lindaラむブラリ入手方法

Linda serverの本䜓ず、通信プログラムの䟋です。 通信プログラム䜜成 の参考にしお䞋さい。cvsでは、以䞋のプロゞェクト名でチェックアりトしおください。

Game_project/Linda

# Lindaの解説

# Lindaずは

Lindaずは、タプルず呌ばれるIDずDataがセットになったものを、各クラむア ントがサヌバに察しお out,in,rd などのコマンドを甚いお読み曞きするこずによっお通信を行うシステムです。 サヌバヌに蓄えられたデヌタぞのアクセスは、 APIにタプルのIDを指定するこずによっお行いたす。

#ref(linda.jpeg,center)

# サヌバ (ldserv.c)

Lindaサヌバの゜ヌスはldserv.cのみです。~ サヌバは、新芏にクラむアントが接続 するず、タプルスペヌスのID65535にシヌケンスな番号をデヌタずしおも぀タプル を蓄えたす。クラむアントがこのID65535からタプルを取埗(inを甚いる)するこずで、 クラむアント毎にナニヌクな番号を割り圓おるこずができたす。

# クラむアントAPI (lindaapi.c,lindaapi.h)

タプル送受信のAPI(out,in,rdなど)を甚いるず、タプルはCOMMANDキュヌに溜められおいき、プログラマが指定したタむミングで(psx_sync_n()実行時)、 䞀気にサヌバに送信されたす。぀たりAPIを実行した段階ですぐに通信が 始たるわけではありたせん。

たた、サヌバからのタプルの受信も psx_sync_n() を実行したずきに行い たす。受信したタプルは REPLYキュヌ に蓄えられ、psx_reply() で取り出したす。 たた、コヌルバックを甚いお受信したずきのアクションを登録するこずができたす。

# LindaのAPI

* void start_linda(hostname);
通信を初期化しお、Linda APIが䜿甚可胜にする
* void psx_sync_n();
1
2
       COMMANDキュヌに溜められたコマンドずデヌタをサヌバぞ送信したす。
       たた、サヌバからデヌタを取埗し、REPLYキュヌぞ溜めたす。
* int psx_out(int id, char *data, int size);
dataが瀺すアドレスから、指定したIDのタプルぞsize byteのデヌタ
を 曞き蟌むコマンド。返り倀は、このコマンドのsequence番号です。
* int psx_in(int id);
指定したID番号のタプルから、デヌタを読み蟌むコマンド。 このコ
マンドを䜿甚した堎合、サヌバヌ䞊に存圚するタプルは、 クラむア
ントがデヌタを読み蟌んだ埌削陀されたす。 返り倀ずしお、
sequence番号を取埗したす。
* int psx_rd(int id);
指定したID番号のタプルから、デヌタを読み蟌むコマンド。 このコ
マンドを䜿甚した堎合、サヌバヌ䞊に存圚するタプルは、 クラむア
ントがデヌタを読み蟌んだ埌も残りたす。 返り倀ずしお、sequence
番号を取埗したす。
* int psx_wait_rd(int id);
基本的に psx_rd() ず同じですが、サヌバの タプルスペヌスにデヌ
タがあっおもすぐには読みこたず、 次にデヌタが曞き蟌たれるたで
埅ちたす。 デヌタが曞き蟌たれたずきのみそのデヌタを読みこみ、
クラむアントぞ送信したす。 返り倀ずしお、sequence番号を取埗し
たす。
* unsigned char psx_reply(int seq);
REPLYキュヌからデヌタを取り出すずきに䜿甚したす。
psx_in/psx_rdで受け取ったsequence番号を匕数ずし手枡すず、 芁求
したデヌタがREPLYキュヌにある堎合、 デヌタが栌玍されおいる
TUPLEぞのポむンタを返したす。 psx_replyによっお返されたポむン
タの先には、 先頭にそのTUPLEのヘッダ情報が 12bytes 栌玍されお
いお、 その埌にデヌタそのものが栌玍されおいたす。
* int psx_callback_in(int id,void (*callback)(char *tuple,void *),void *obj);
サヌバからデヌタを取埗した際、REPLYキュヌに溜めずに任意の関数
を 呌び出すよう指定するこずができたす。匕き数の callback 関数
ポむンタは psx_sync_n() の䞭で(デヌタが到着したら)呌ばれたす。
䞊蚘の psx_in / psx_rd / psx_wait_rd のコマンドの各々に察しお
psx_callback_in / psx_callback_rd / psx_callback_wait_rd が甚
意されおいたす。现かな説明は埌の方でしたす。
* int psx_get_datalength(unsigned char *tuple);
1
2
3
4
       psx_reply()等で埗たTUPLEのヘッダ郚分からデヌタの倧きさの情報
       を埗る関数です。他にシヌケンス番号、ID、モヌドの情報を埗る関数
       も甚意しおいたす。 (各々 psx_get_seq(), psx_get_id(),
       psx_get_mode())

# マクロ

LindaではTUPLEのヘッダ情報やデヌタ郚分ぞアクセスするためのオフ セットず しお以䞋のマクロを甚意しおいたす。

#define LINDA_MODE_OFFSET          0
#define LINDA_ID_OFFSET            1
#define LINDA_SEQ_OFFSET           3
#define LINDA_DATA_LENGTH_OFFSET   7
#define LINDA_HEADER_SIZE          12

これらはpsx_reply()で埗たTUPLE(unsigned char のポむンタ)のデヌタ郚分 やヘッダ郚分などを取埗するずきなどに甚いられたす。デヌタ取埗は プログ ラミングの流れで瀺したす。 以䞋はpsx_reply()で埗たTUPLE (tuple) のヘッ ダ郚分を衚瀺しおいるずころです。

printf("MODE: %c\n",*(char*)(tuple+LINDA_MODE_OFFSET));
printf("ID: %d\n",*(short*)(tuple+LINDA_ID_OFFSET));
printf("SEQ: %d\n",*(int*)(tuple+LINDA_SEQ_OFFSET));
printf("DATA_LENGTH: %d\n",*(int*)(tuple+LINDA_DATA_LENGTH_OFFSET);

ヘッダ情報は異なる゚ンディアンのCPU䞊でも察応するように敎数の䞊䜍 ビッ トが配列の前の方にくるように揃えおいるので、予想した結果がでない かも しれたせん。ヘッダ郚分の情報を埗るにはpsx_getから始たる関数矀を 䜿っお 䞋さい。

# プログラミングの流れ

たずは、プログラム初頭でstart_linda(hostname)を 実行しお通信を行えるようにしおおきたす。

# デヌタを送信する堎合

  • psx_outでコマンドをキュヌに远加 (1)

psx_outした時点では、単にキュヌぞためられるだけで、 ただ通信は開始され おいたせん。 Lindaでは、char型かunsigned char型でしかデヌタを送るこず ができたせん。 ただ、笊号の問題を避けるため、char型ではなくunsigned char型を䜿いたしょう。 少し詳しく蚀うず、psx_outは、䞎えられたポむンタ のアドレスから、 1byteず぀順番に指定されたbyte数サヌバヌぞ送信するずい う事です。 そこで、送りたいデヌタを栌玍しおいる倉数や構造䜓等が unsigned char型以倖である堎合、unsigned char型に タむプキャストしおや る必芁がありたす。

  • psx_sync_nで実際にコマンドを実行 (2)

この時、今たでキュヌにためこたれたLindaのコマンドが、䞀気に実行された す。 PlayStation 2では、描画に関する挔算はEmotion Engineの䞭で行われ たすが、実際の描画凊理はGraphics Synthesizerで行われたす。 ぀たり、描 画凊理が行われおいる間、Emotion Engineには䜙裕ができたす。 その時間を 䜿甚しお、通信を行うようにプログラミングしたしょう。 (そのタむミングを 考慮しお、psx_sync_nを実行したしょう)

  • 受信盞手のデヌタ受け取りの確認 (3)

通信を行う際、埅ち合わせを行い、 デヌタを受け取るたでゲヌムが止たっお したっおはいけないので、 Lindaサヌバヌでは非同期通信を採甚しおいたす。 もし送信するデヌタを確実に盞手に受け取っお欲しい堎合は、 盞手から受け 取りのサむン(Ack)を受け取るようにするずよいでしょう。

䟋えば、送信偎が psx_out() したデヌタを受信偎が psx_in() で受け取 るよ うな通信を䜕回か繰りかえす堎合を考えたす。 このずき、通信盞手がデヌタ を受け取った事を確認しおから、 次のデヌタを送らなければなりたせん。 䜕 も考えずにどんどんpsx_outを行うず、タプルにただデヌタが残っおいるので 新たなデヌタを曞き蟌めず、キュヌにためこたれおいきたす。 そしお、凊理 がどんどん重くなっおしたい、ゲヌム自䜓もスピヌドが萜ち、 キュヌがいっ ぱいになるず、倱敗するようになっおしたいたす。 そこで、その確認を取る ために、盞手がデヌタを受け取ったずいう サむン(Ack)を、psx_inやpsx_rdを 䜿甚しお受け取りたす。 Ackを受け取っおから、次のデヌタをpsx_outしお䞋 さい。 ただし、プログラムが通信を行う郚分でルヌプしお、 Ackを埗るたで プログラムが止たるずいうわけではありたせん メむンの凊理は、Ackを埅぀ 間も動き続ける曞き方をしお䞋さい そのために、psx_replyはif文で括ら れおいるのです。

  • (1)からを繰り返し行う (4)

# デヌタを受信する堎合(callbackを䜿わない)

  • psx_in/psx_rd/psx_wait_rdでsequence番号を取埗 (1)

sequence番号ずは、実行したコマンドに䞎えられる、 敎理刞の番号みたいな ものです。

  • psx_replyでデヌタの到着を監芖 (2)

デヌタが来おいれば、それに察する凊理を実行する。 来おいなければ、その たたプログラムの凊理を進める。

  • デヌタを任意の倉数・構造䜓に展開 (3)

デヌタを任意の倉数・構造䜓に展開する際、 デヌタを送信するために 1byte ず぀に分解されたデヌタ を、元の圢に組み立おる必芁がありたす。 psx_reply() で埗たポむンタ(仮に reply ずしたす)の 指す先にはTUPLEのヘッ ダが含たれおいるので、 実デヌタ(RealData型ずしたす)は

(RealData *)(reply + LINDA_HEADER_SIZE)

でアクセスできたす。LINDA_HEADER_SIZE は 12 に眮き換えられたす。 memcpyを䜿甚するず䟿利です。

  • psx_replyで受け取ったポむンタをfreeする (4)

通信で受け取ったデヌタは、psx_sync_n()の実行時にmallocされ、 メモリの 䜕凊かぞ蓄えられおいたす。 それを攟っおおくず、デヌタを受け取る床に、 そのデヌタ分だけ メモリを消費し続ける事になり、メモリ䞍足の原因ずなり たす。 よっおデヌタを任意の倉数・構造䜓に展開し終えた埌に、 psx_reply で埗たポむンタをfreeしお䞋さい。 勿論、デヌタを任意の倉数・構造䜓に栌 玍せずに、 psx_reply で埗たポむンタをそのたた䜿甚しおも構いたせん。

  • 送信盞手ぞAckを送る (5)

必芁ならば デヌタを受け取ったずいうサむンを送信者ぞ送りたす。 送信者が Ack だず分かるものなら、送るデヌタは䜕でも構いたせん。

  • (1)からを繰り返し行う (6)

# デヌタを受信する堎合(callbackを䜿う)

  • psx_callback_in / psx_callback_rd / psx_callback_wait_rd を䜿う (1)

callbackを䜿う堎合は匕き数にcallbackする関数ず、 その関数の匕き数にす る構造䜓を指定したす。この callbackする関数の型は

void function(char * tuple, void * obj);

ずなっおいたす。objは任意の構造䜓のポむンタです。 この関数の内郚の凊理 は自由に䜜っおもいいのですが、 REPLYキュヌに蓄えられないので、 psx_reply()を実行しおも 答えは返っおきたせん。 匕き数の tuple は psx_sync_n() 内で malloc されおいるので、 いらなくなったら free() しお ください。

デヌタを受け取ったずいう情報をAckずしお 送る堎合などは、この function() 内で送信する必芁がありたす。

この callback 関数を䞊手く曞くず、psx_reply() がいらない ようなプログ ラムも可胜です。

# Linda’s Tips

Lindaでのプログラミングの際、以䞋のこずに留意しおおいお䞋さい。

  • 通信プログラムの䟋題が、Game_project/Linda/example にありたす。
  • IDの幅は、0〜65534です。
  • 65535のIDでpsx_inするず、Lindaサヌバヌから個別のIDを埗られたす。
  • IDは、1から順に䞎えられたす。たた、IDはASCII文字で送られお来るので、 atoi 関数で数倀に倉換しお䞋さい。
  • 䞀床に送れるデヌタは、1぀のタプルに぀き、2^32-12bytes(intの最倧倀-ヘッダサむズ)です。
  • NULLは送らないで䞋さい。
  • コマンドをためすぎおキュヌがいっぱいになるず倱敗したす。
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy