ネットワーク・プログラミング ソケットプログラミングと共有メモリ
全体の位置づけ オペレーションシステム(Linux) ソケットプログラミング プロセス カーネルとシステムコール プロセス間通信 スレッド クライアントーサーバ 非同期I/Oとマルチタスク
1.1 プロトコル TCP/IP通信 パケット プロトコル TCP/IP通信 ネットワーク層(IP) トランスポート層(TCP又はUDP) 1.1 プロトコル パケット TCP/IP通信における情報伝送の単位。 プロトコル 情報を交換する手順やパケットの内容について定めた決まりごと。TCP/IPはプロトコルである。 TCP/IP通信 アプリケーションプログラムがソケットを介してUDP又はTCPサービスを利用する通信。 ネットワーク層(IP) パケットを宛先(宛先IPアドレスを持つコンピュータ)に届ける。 パケットは個別に処理される。 ベストエフォートサービス(パケットの紛失や到着順の逆転が起きる)。 トランスポート層(TCP又はUDP) 宛先アプリケーションにデータを届ける。 ポート番号を使って、アプリケーションを識別する。 TCPは紛失パケットを再送する。 UDP は紛失パケットを再送しない。 アプリケーション (AP) アプリケーション (AP) ソケット ソケット UDP TCP TCP UDP IP 通信 チャネル IP IP 通信 チャネル コンピュータ ルータ コンピュータ TCP/IP通信
1.2 アドレスとソケット IPアドレス ポート番号 クライアント/サーバ ソケット IP IP クライアント サーバ ソケット TCP 1.2 アドレスとソケット IPアドレス コンピュータの通信用のアドレス。 IPアドレスは32ビット(IPv4)。 ドット10進表記法(例: 10.1.2.3)。 ポート番号 アプリケーションを識別する番号。 符号無しの16ビット2進数(1~65,535)。 クライアント/サーバ サーバがクライアントにサービスを提供する。 クライアントは予めサーバのIPアドレスとポート番号を(DNSを使って)知っている。 よく利用されるポート番号は予約されている。 ソケット TCP/IP通信を行うためのAPI(アプリケーションインタフェース)。 データの送受信は(ファイルI/Oと同様に)ソケットへの書込/読出により行う。 ストリームソケット(TCPを使用)とデータグラムソケット(UDPを使用)の2種類ある。 FTP FTP 5000 20 TCP TCP 10.1.2.3 10.1.2.5 IP IP クライアント サーバ AP AP AP ソケット 1 2 65535 1 2 65535 UDP TCP ソケットがポートにバインド IP
2. 共有メモリ プロセス A プロセス B 共有メモリ カーネル shmget(); shmget(); shmat(); 2. 共有メモリ プロセスAとBは、 同じ鍵を持っている プロセス A プロセス B プロセスA shmget(); shmat(); write(); プロセスB shmget(); shmat(); read(); プロセス間通信 パイプライン シグナル カーネル 共有メモリ 共有メモリ セマフォ ソケット カーネル
2.1 共有メモリ概要 共有メモリを利用する手順 (例)カット&ペースト mcut mpaste shmid 共有メモリの 利用状況 2.1 共有メモリ概要 共有メモリの 利用状況 共有メモリを利用する手順 共有メモリ識別子を獲得(shmget)。メモリ上に共有メモリ領域が確保される。 共有メモリにアタッチ(shmat)。利用できる共有メモリの先頭アドレスが返される。 共有メモリにデータを書込む/読込む。 共有メモリをデタッチ(shmdt)。利用を終える。 (shmctl, ipcrmコマンドを使って)共有メモリ領域を開放する。 (例)カット&ペースト mcut 標準入力からのデータを共有メモリに入れる。 mpaste 共有メモリからのデータを取出し標準出力へ出力する。 [oida@rpc261 soft2]$ ipcs -m ------ シェアードメモリセグメント -------- キー shmid 所有者 権限 バイト nattch 状態 [oida@rpc261 soft2]$ w | ./mcut 0x61018088 360453 oida 666 4096 0 [oida@rpc261 soft2]$ ./mpaste 12:04pm up 1:38, 2 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT oida pts/0 pupa 11:33am 1:41 0.03s 0.03s -bash oida pts/1 pupa 11:43am 0.00s 0.05s 0.01s w [oida@rpc261 soft2]$ ipcrm shm 360453 リソースを削除しました [oida@rpc261 soft2]$ 利用者情報をカット 利用者情報をペースト shmid
アクセス権の指定方法は、ファイルと同じrwx。 つまり、read,write,execute 2.2 共有メモリのシステムコール1 shmget 共有メモリを割当て、識別子を得る インクルードファイル #include <sys/ipc.h> #include <sys/shm.h> 書式 int shmget(key_t key, int size, int shmflg); 戻値 成功時 共有メモリ識別子 失敗時 -1 key: 共有メモリを使うプロセス共通のキー size: 確保する共有メモリのサイズ(バイト) shmflg: IPC_CREAT: 新規作成(同じキーで割当てられていれば、既にある 共有メモリを使う) IPC_EXCL: 同じキー値で既に割当てられていれば、エラーを返す アクセス権: ファイルの許可ビットと同じ 例: IPC_CREAT|0666 新規作成、全ての人が読書可能 IPC_CREAT|IPC_EXCL|0666 割当てられていない新しいメモリ アクセス権の指定方法は、ファイルと同じrwx。 つまり、read,write,execute
shmat 共有メモリをプロセスにアタッチ 2.3 共有メモリのシステムコール2 shmat 共有メモリをプロセスにアタッチ shmdt 共有メモリをデアタッチ インクルードファイル #include <sys/types.h> #include <sys/shm.h> 書式 void *shmat(int shmid, const void *shmaddr, int shmflg); 戻値 成功時 アタッチされた共有メモリの開始アドレス 失敗時 -1 int shmid: 共有メモリ識別子(shmgetの戻値) const void *shmaddr: アタッチするアドレス(共有メモリの先頭 からのオフセット) shmflg: 共有メモリの操作モード(SHM_RDONLYは、読取り モード、それ以外は、読書きモード) インクルードファイル #include <sys/types.h> #include <sys/shm.h> 書式 int shmdt(const void *shmaddr); 戻値 成功時 0 失敗時 -1 shmctl 共有メモリを制御する インクルードファイル #include <sys/ipc.h> #include <sys/shm.h> 書式 int shmctl(int shmid, int cmd, struct shmid_ds *buf); 戻値 成功時 0 失敗時 -1 cmd: IPC_STAT 共有メモリの状態を得る IPC_SET 共有メモリの状態を変更 IPC_RMID 共有メモリを削除 共有メモリ プロセス shmat 戻値
2.4 クリップボード(カット&ペースト) mcut.c mpaste.c 共有メモリの先頭アドレスを得る 2.4 クリップボード(カット&ペースト) 追加して下さい #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <stdlib.h> #include <string.h> mcut.c mpaste.c int main() { char *head; char in_data[4096], *in_ptr; char *pos; int i, in_tmp, shmid; key_t shmkey; shmkey=ftok("mcut",'a'); shmid=shmget(shmkey,sizeof(in_data),IPC_CREAT|0666); head=pos=shmat(shmid,0,0); in_ptr=in_data; for (i=0; i<sizeof(in_data)-1; i++) { if ((in_tmp=getchar())==EOF) { break; } *in_ptr=in_tmp; in_ptr++; *in_ptr=(char)NULL; strncpy(pos,in_ptr,sizeof(in_data)); shmdt(head); return EXIT_SUCCESS; #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *head; char out_data[4096], *out_ptr; char *pos; int shmid; key_t shmkey; shmkey=ftok("mcut",'a'); shmid=shmget(shmkey,sizeof(out_data),IPC_CREAT|0666); head=pos=shmat(shmid,0,0); out_ptr=out_data; strncpy(out_ptr,pos,sizeof(out_data)); printf("%s",out_data); fflush(stdout); return EXIT_SUCCESS; } (存在する)ファイルの 名前と任意の1文字からキーを作る 共有メモリの先頭アドレスを得る ファイル名はmcut.cで使った名前と同じでなければならない 標準入力からの文字をin_dataへ 共有メモリの先頭アドレスを得る 警告がでれば(char)NULL→’\0’ 共有メモリに書込む 共有メモリから読み出す 共有メモリの利用を止める
宿題7 mcut hw7 mpaste w 共有 メモリ 宿題:(mcut.c,mpaste.cを参考にして)mcutによって共有メモリに書き込まれたデータを全て大文字に変換後、共有メモリに再度書き込むプログラム(hw7.c)。関数toupper()を使用する。全て大文字になっていることをmpasteで確認すること。 表紙に氏名と学籍番号を書く 本文にプログラムを書く プログラムの実行結果を書く 実施した内容を説明する文章を書く レポートの締切は次の週の水曜日18:00 w write 共有 メモリ read toupper write read hw6.c print [oida@rpc261 soft2]$ w 7:43pm up 7:51, 2 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT oida pts/0 pupa 12:34pm 10:53 0.05s 0.05s -bash oida pts/1 pupa 7:25pm 0.00s 0.08s 0.01s w [oida@rpc261 soft2]$ gcc -o hw7 hw7.c [oida@rpc261 soft2]$ w | ./mcut [oida@rpc261 soft2]$ ./hw7 [oida@rpc261 soft2]$ ./mpaste 7:43PM UP 7:52, 2 USERS, LOAD AVERAGE: 0.00, 0.00, 0.00 OIDA PTS/0 PUPA 12:34PM 10:32 0.05S 0.05S -BASH OIDA PTS/1 PUPA 7:25PM 0.00S 0.07S 0.00S W [oida@rpc261 soft2]$ ipcrm shm 360453 リソースを削除しました [oida@rpc261 soft2]$ ヒント toupper()関数の使い方 全て大文字にする for (i=0; i<strlen(out_data); i++) out_data[i] = toupper(out_data[i]); 使い終わった共有メモリは削除する shmid