All articles in c-language

libsafeを使ってみる

libsafeはCの標準関数のうち,よくバッファオーバーフローを起こすものを差し替えてバッファサイズをチェックする処理をしてくれるらしいので試してみた.libsafeって何だ?インストール試してみる libsafeって何だ? libsafeはベル研がLinux向けに開発した,バッファオーバフロー対策用のライブラリらしい. 詳細はこの辺に書いてあるが,とにかくCの標準ライブラリがバッファのオーバーフローチェックをしてないからダメなんじゃないか,だったらそういうライブラリを作って差し替えようとか,そういう感じらしい. インストール 試してみる 適当にlibsafeがチェックする関数を呼び出すサンプルを作成してみる.

マウス

ncursesではマウスの操作を検知できるらしい.ただしSVr4以前とか4.4BSD以前ではできないようだ.マウスイベントバグマウスイベントの検知座標クリックの検知サンプル マウスイベント バグ man mouseのBUGSによるとxtermでマウスイベントを検知するためには,以下の条件が必要らしい.cbreakモードになっている(wmousemaskでマウスイベント検知をONにする場合).キーパッドが有効(なんかマウスイベントをファンクションキーとして扱ってしまうらしい).terminfoでkmousの値が”\E[M”になっている必要がある.環境変数$TERMが”xterm”を含むかterminfoでkmousが定義されている.なんか移植性が心配な雰囲気だ. マウスイベントの検知 座標 特に指定しなければ,マウスイベントはmousemaskで指定したボタンが押されたとか離されたということしか検知しない.マウスイベントを検知したとき,マウスの座標をしりたければmousemaskでREPORT_MOUSE_POSITIONを渡す.例えばボタン1の押下を検知し,その座標を知りたいときはmousemask(BUTTON1_PRESSED | REPORT_MOUSE_POSITION, NULL);とする.また,stdscrでの座標からスクリーンでの座標に変換するにはbool mouse_trafo(int* pY, int* pX, bool to_screen);を使用する.このへんはslk_…関数に関係があるらしい(man slk参照). クリックの検知 マウスのクリックやダブルクリックはmousemask関数の第一引数にBUTTON1_PRESSEDやBUTTON1_RELEASEDを指定して実装出来そうだが,BUTTON1_CLICKEDやBUTTON1_DOUBLE_CLICKED等を指定するだけで検知することができる.で,ボタン押下とボタン離しでボタンクリックやダブルクリックを実装するときをイメージすると,ボタンが押されてから何秒以内にボタンを離せばクリックとするのかを指定する必要がある気がして来る.これを指定するのが,int … More マウス

リソース情報の取得と設定

プログラムを実行する際のリソース情報(とくにリソースの制限)を取得する必要がある場合がある.limits.hプライオリティの取得と設定リソース使用量リソースの制限とその設定 limits.h プライオリティの取得と設定 リソース使用量 リソースの制限とその設定 リソースの制限にはソフト制限とハード制限がある. ソフト制限 超えるべきでない値.超えるとライブラリ関数がエラーを返すことがある. ハード制限 この制限を超えるとシステムがプロセスにシグナルを送りそのプロセスを殺そうとする ソフト制限はハード制限を超えない範囲で設定できる,ということである.さらに,ハード制限は引き下げることが可能である.また,root権限がある場合だけはハード制限を引きあげることができる.リソースの制限はrlimit構造体で取得できる.以下,/usr/include/bits/resource.hより

terminfo

terminfoを使用すると出力場所とかをイイ感じにできるかもしれない.terminfoとはterminfoのデータclearカーソル移動 terminfoとは かつてのUNIXシステムではいろんな端末があって,それらの制御方法は標準化されていなかった.そこで,統一されたインタフェースでプログラムからの要求を受け取り,保持している各端末の制御方法に関するデータを参照して処理するパッケージとしてterminfoが登場した.terminfoはcursesと組み合わせて使用するが,両者の境界はなんだかあいまいらしい. terminfoのデータ 私のシステムではterminfoのデータが入っているterminfoファイルは/usr/share/terminfo/に沢山あった.これらはterminfoファイル名の頭文字ごとにディレクトリに分けられ,それぞれのterminfoファイルはticというコマンドでコンパイルされたもの(バイナリファイル)らしい.terminfoファイル内の各データは以下の3種類に分けられる.ブール型該当する機能をサポートするか否か.数値型サイズを表す.文字列型端末機能にアクセスするためのキーとか,キーボード入力をどんな文字列に変換してプログラムに渡すかを定義.端末を制御するコーディングの流れは大体以下のようになる.setuptermで現在の端末に対応するTERMINAL構造体を取得tigetflag,tigetnum,tigetstrで現在の端末の状態を取得エスケープシーケンスを生成putp,tputsでエスケープシーケンスを端末に送るエスケープシーケンスの生成についてちょっと書いておく.まず,どんな文字列型のデータがあるかは,man 5 terminfoに一覧がある(やたら多い).ここにある「Capname」をキーにしてtigetstrを呼び出すとその機能に対応したエスケープシーケンスが得られる.で,そこで得られるエスケープシーケンスの中にはそのままでは使用できないものがある.「カーソルを何行目の何列目に移動しろ」などという命令に対応するエスケープシーケンスは,数が膨大になるのを防ぐために,「何行目」とか「何列目」というのをパラメータ化している.このような場合,tparmを使用して取得したエスケープシーケンスのパラメータに具体的な値をいれるというステップが入る. clear サンプルとしてclearコマンドを作成する.man clearによるとclearコマンド自体,tputをclear引数とともに呼んでいるらしい. terminfoを使用するときは,コンパイル時にコンパイルオプションが必要である.私のシステムでは以下でコンパイルできた.gcc -Wall -o my_clear my_clear.c -lncurses-lncursesがないと怒られる.システムによっては-Iでncurses.hの場所を教える必要があるかもしれない(私のシステムでは/usr/include/ncurses.hがあった).コンパイル後実行するとclearコマンドと同様の結果が得られた. カーソル移動 もう一つの例としてカーソル移動のサンプルを作成してみた. このサンプルはviみたくhjklでカーソルを移動する.文字は入力できない.あとqを入力すると終了する.

socket関数とプロトコル

まずsocket関数とプロトコルとアドレスについて記述しておく.socket関数ドメインとタイプとプロトコルアドレスの表現よく使うSocket socket関数 同一マシンのプロセス間だけでなく,別マシンのプロセスとも通信したりするには,Socketを使用する.で,そのためにsocketシステムコールを使用する.int socket(int domain, int type, int protocol);この関数の呼び出しが成功するとソケットへのディスクリプタを返す.これはファイルディスクリプタと同様に扱える.引数にprotocolというのがある.これを見ると,TCP/IPだのUDPだのを指定するのかと思うのは私だけだろうか.実際はちょっと違う.例えばTCP/IPで通信したければ,socketを以下のように呼び出す.socket_df = socket(AF_INET, SOCK_STREAM, 0);雰囲気を掴めたところで(こんなんで掴めるのか?)パラメータを一つずつ見ていく. ドメインとタイプとプロトコル アドレスの表現 socket関数でプロトコルを指定できた.では,アドレスはどうだろうか.アドレスはドメインによって独自のアドレス形式があるらしい.例えば,PF_INETではアドレスを以下の構造体で指定する(man ipより).struct sockaddr_in {sa_family_t sin_family; … More socket関数とプロトコル

ロックとmutex

スレッドの同期には,pthread_joinによる合流の他に,ロックという方法がある.mutexって何だ?mutexの属性と初期化mutexのロックとアンロックサンプル mutexって何だ? mutexはmutual exclusionの略らしい. ということは,mutexは「ミューテクス」とかそんな感じの読みのような気がするが,正しい読みはよくわからない(※). とにかく,pthreadでは,mutexをロックすることによって,スレッド間の同期を行うことができる.mutex = バイナリセマフォということで,よいと思う. つまり,あるスレッドでロックしたmutexに対し,別のスレッドがロックしようとしたら,最初のスレッドがそのmutexを開放するまで後のスレッドは待たされる. 上図で,破線で囲まれた部分の処理が,同期が保証される領域で,クリティカルセクションという. 具体的にはクリティカルセクションでは,複数のスレッドで参照,更新するデータに対する処理を行う. クリティカルセクションで参照するデータは,別のスレッドによって更新途中になっている不完全なデータを参照したり更新したりしてしまう心配がない. 性能の観点からすると,クリティカルセクションは短い程よい.※ 私はどういうわけか,「ムテフ」とか「マテフ」と読んでしまうが,これは,まぁ,間違ってるんだろうな. mutexの属性と初期化 mutexはまず初期化する必要がある.int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex-attr_t *mutexattr);pthread_mutex_initはmutexattarで指定した属性をもつmutexを作成する. … More ロックとmutex

メッセージキュー

メッセージキューはパイプとより扱いが簡単でちょっと嬉しい.メッセージキューに関する関数サンプル メッセージキューに関する関数 メッセージキューに関する関数として,以下がある.int msgget(key_t key, int msgflg);指定したkeyのメッセージキュー識別子を取得.msgflgにはパーミッションやオプションなどを指定する.これにIPC_CREATを指定すると,指定したkeyのメッセージキューがない場合は作成してくれる.int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);メッセージの送信.ssize_t msgrcv(int msqid, struct msgbuf … More メッセージキュー

zlibを使ってみる

自作のアプリケーションでデータを圧縮解凍したいと思うことがたまにある.zlibを使用すると簡単にzip圧縮と解凍ができるようなので試してみた.zlib.h圧縮エラーメッセージの取得解凍コンパイルと実行 zlib.h zlibにはいろいろな関数がたくさんあって,その詳細はzipの仕様がわかっていないとなかなかつらそうだったりもする. で,zlib.hを眺めていると,詳細な操作を行う関数の他に,簡単に使用したい人のための関数も用意されているようなので,今回はそれらを使用してみる. zlibの各関数にはmanがないようだが,zlib.hには詳細なドキュメントがコメントされているので,困ったらそれを読むとよい. 圧縮 データをzip形式圧縮してファイル出力するサンプルを以下に示す. 簡易APIを使用すると,通常のファイル出力と同様,オープン,書き出し,クローズの三段階の手順となる.ファイルのオープンファイルのオープンはfopenに似ている.ZEXTERN gzFile ZEXPORTgzopen OF((const char *path, const char *mode));pathが出力ファイルパス,modeはfopenのモード+圧縮モードである. fopenのモードは”rb”か”wb”で,圧縮モードは圧縮レベル [圧縮方式]である. 圧縮レベルは0 : … More zlibを使ってみる

cursesの基本的な関数

cursesの多くの関数のうち,基本的なものを紹介する.cursesの基本的な関数カーソルの移動文字出力文字の削除画面のクリアサンプルサンプル2 cursesの基本的な関数 cursesには沢山の関数がある.ここではそのうちの以下の機能を使ってみる.カーソルの移動文字出力文字の削除画面のクリア カーソルの移動 カーソルの移動にはint move(int y, int x);を使用する.左上が0,0となる.そして縦にy,横にxが増加していく.また,ウィンドウが複数になると,ウィンドウを指定してそのウィンドウのカーソルを移動させることができる.int wmove(WINDOW *win, int y, int x);複数のウィンドウの扱いについては別項に記述する. 文字出力 文字を出力する関数はいろいろある.最も基本的なものとして以下がある.int printw(char *fmt [, … More cursesの基本的な関数

スレッドのデタッチとjoin

2007-02-05T22:50+09:00 matsuスレッドのデタッチと合流について調べてみた.スレッドの終了とjoinデタッチサンプル スレッドの終了とjoin スレッドは終了してもリソース(スレッドディスクリプタとスタック)が保持される. このリソースは,他のスレッドが開放するまで保持され続ける. この開放処理が include int pthread_join(pthread_t th,void **thread_return);である. 返り値は0なら成功,それ以外の場合にはエラーコードが格納されている. 引数は以下.thスレッド識別子. join対象のスレッドをpthread_createした際に取得したもの.thread_returnjoin対象のスレッドのイニシャル関数の返り値(void *)の格納領域のポインタ.この関数を呼び出した時点で,対象のスレッドが終了していないければ,そのスレッドが終了するのを待ってからリソースは開放される. プロセスでforkした後のwaitをイメージすれば近いだろうか. だから,この関数はその名の通り,スレッドの合流と解した方が,その挙動を解しやすいかもしれない. デタッチ スレッドが終了したら,別のスレッドでその終了したスレッドのリソースを開放しなければならない. だが,プログラムによっては,このリソース開放処理を記述する適切な箇所が見当たらなかったり,プログラム構造に制約を課してしまう場合がある. … More スレッドのデタッチとjoin