| 2001/09 ALL | |
| Last Modified : | 09/26 02:22 |
| Total Access : | |
| Today Access : | |
| Your Access : | COOKIE_TIMES: deprecated in static mode. |
こっちで編集してしまった。 まいっか。
PIPS780の2.0はプリンタ制御ツールが入った。 しかし、逆にGUIが起動するなどプリンタサーバとしては 使いにくくなっている。filter780はほとんどコメントアウト しなくちゃいけないもんね。ああ両方入れられたらいいのに。
日曜日にスキャナーGT-7700Uを12800円で買った。USB機器は初めてなので ドキドキしたがその使い方の簡単さに脱帽。
スキャナー用にメモリも1GBにした。swapは128MBしかないのに。。
はじめLinuxで896MBしか認識しないのでびっくり。
BIOSまでいちどフラッシュしてしまったよ
(CMOSなんとかのジャンパはずして電源を入れる)。
なんのことはないdebianのkernel-image-2.4.9はHIGHMEM無効にしてるのね。
やってみると、おおLinuxでは4Gと64Gがすでにあるのか。
というわけでHIGHMEM4GBで再構築、ついでにプロセッサータイプを686からK7にする。
でもスキャナーで1200dpiでA4全部取り込んでも1Gは食うのか。。。
ここしばらくFreeWnnをkinput2で使っているがなんとも使いにくい。 とくに良く使うASCIIまじり文は書いてからASCIIに変換できないのがいたい。 はじめにqを押せばASCII入力になるが、そうじゃなく書いてから変換したいんだよね。
ノートにプリインストールされているWindows98SEを
なんとかつかえるようにしてみた。
まずセキュリティパッチをWindows Updateからいれる。
ついでに
Windows Media Player
も7.1にアップデートする。
そして
IE6
をインストールする。
Windowsスピードアップ術
を参考にディスク使用とタスクスイッチを最適化。
さらに無駄なデスクトップアイコンを削除し4つまで減らす。
それから以下のアプリケーションをインストール。
あと
WindowBlinds
も試してみるがあまり使わないだろう。
これに
Iria
と
RarUty
と
ホットゾヌ
(
monazilla
)なんか入れたらまさに厨房仕様だな。
cygwin
が使えるのはいいんだけど、Linuxでよく使うコマンドがいくつか
ないのでそれをインストールしてみた。
まずは
lv
をインストールした。
普通にコンパイルはうまくいくがデフォルトのアウトプットがSJISでない
のでそれを変える。src/conf.cの中のDEFAULT_OUTPUT_CODING_SYSTEM定義
をISO_2022_JPからSHIFT_JISに変更すればOK。
w3m
をインストール。基本的にconfigureスクリプトに対話で答えればOK
(出力の文字コードではShift_JISを選ぶ)。
ちなみにXMakefileのINCLUDESに-I/usr/include/opensslを
追加すればMonstar設定でもコンパイルできる。
インストールディレクトリはXXMakefileにある(デフォルトは/usr/localになっている)。
けっこうすんなりいけたのでなんか
sylpheed
を入れたくなったな(やっぱりだめだった)。
玄人志向
の安いキャプチャカードBT878A-PCIを買った。
サウンドはモノラルだけど値段が安いのでまあOK。
空けてみると中味はPV951だった。
これって中の見えないバルク品だよな。
Linuxで十分使えてます。
zapping
最高。終了は遅いけど。
ほんとはDVDつきのCD-Rドライブを買いたかったけど、
まだまだ下がりそうなので待つことに。
リコーRW9200が1万円くらいになれば即買いか。
念願の
ハッカー・プログラミング大全
を買った。
ていねいに書かれていて読みやすい。
昨日、坂村健教授がセキュリティについて講義をしたけど
eTRON
というものを考えているらしい。
専用ハードウェアとそのためのネットワークシステム
を作るようだ。これはなりすましや
盗聴ができないようなものでもあるらしい。
新しい部屋に引っ越して2週間がすぎ気づいたが、前にくらべて湿度が低い。 千葉にいたときは60%は必ずあったのだが、いまの東京の部屋は40%くらいだ。 これは旭川の家くらいの量かなあ。本には優しいかも。
読み込み
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>
int show_file(char* filename);
int main(int argc, char* argv[])
{
int i;
if (argc <= 1) {
printf("usage: %s file1 file2 ...\n", argv[0]);
exit(0);
}
for (i = 1; i < argc; i++) {
int ret;
ret = show_file(argv[i]);
if (ret < 0) {
perror(argv[i]);
}
}
return 0;
}
int show_file(char* filename)
{
FILE* out = stdout;
int fd;
off_t offset = 0;
struct stat fs;
char* fp;
fd = open(filename, O_RDONLY);
if (fd < 0) {
return -1;
}
fstat(fd, &fs);
fp = mmap(NULL, fs.st_size, PROT_READ, MAP_SHARED, fd, offset);
if ((int) fp < 0) {
close(fd);
return -1;
}
fwrite(fp, sizeof(char), fs.st_size, out);
munmap(fp, fs.st_size);
close(fd);
return 0;
}
書き込み
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
int write_file(char* filename, char* data);
int main(int argc, char* argv[])
{
int ret;
if (argc != 3) {
printf("usage: %s file text", argv[0]);
exit(0);
}
ret = write_file(argv[1], argv[2]);
if (ret < 0) {
perror(argv[1]);
}
return ret;
}
int write_file(char* filename, char* data)
{
int fd;
off_t offset = 0;
size_t size;
char* fp;
int ret;
size = strlen(data);
fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
return -1;
}
ret = ftruncate(fd, size);
if (ret < 0) {
close(fd);
return -1;
}
fp = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if ((int) fp < 0) {
close(fd);
return -1;
}
memcpy(fp, data, size);
ret = msync(fp, size, 0);
munmap(fp, size);
close(fd);
if (ret < 0) {
return -1;
}
return 0;
}
mmapでファイルに書き込むときはあらかじめ書き込めるだけの ファイルの領域をとる必要がある。
サーバ
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "define.h"
void process_connection(int cfd, int counter) ;
int server_open(int port, int backlog);
int main(int argc, char* argv[]) {
int sfd;
int connect_count = 3;
int i;
sfd = server_open(PORT, connect_count);
if (sfd < 0) {
perror("server");
exit(1);
}
for (i = 0; i < connect_count; i++) {
int cfd;
struct sockaddr_in caddr;
int len;
len = sizeof(caddr);
cfd = accept(sfd, (struct sockaddr*) &caddr, &len);
if (cfd < 0) {
perror("client");
continue;
}
process_connection(cfd, i);
shutdown(cfd, SHUT_RDWR);
close(cfd);
}
close(sfd);
return 0;
}
void process_connection(int cfd, int counter)
{
char buf[BUFSIZE];
int ret;
ret = read(cfd, buf, BUFSIZE);
buf[0] = '0' + counter;
puts(buf);
write(cfd, buf, BUFSIZE);
}
int server_open(int port, int backlog)
{
int sfd;
int optval;
struct sockaddr_in saddr;
int ret;
sfd = socket(PF_INET, SOCK_STREAM, 0);
if (sfd < 0) {
return sfd;
}
optval = 1;
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
memset((char*) &saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sfd, (struct sockaddr*) &saddr, sizeof(saddr));
if (ret < 0) {
close(sfd);
return ret;
}
ret = listen(sfd, backlog);
if (ret < 0) {
close(sfd);
return ret;
}
return sfd;
}
listenのbacklogは待ち受けする数。setsockoptのSO_REUSEADDRを1にすることは
連続してこのプログラムを実行するのに必要な処理です。shutdownはストリームを
閉じるものです(man 2 shutdown)。
クライアント
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include "define.h"
int connect_server(char* host, int port) ;
void process_connection(int cfd);
int main(int argc, char* argv[]) {
int cfd;
cfd = connect_server(HOST, PORT);
if (cfd < 0) {
perror("connect");
exit(1);
}
process_connection(cfd);
shutdown(cfd, SHUT_RDWR);
close(cfd);
return 0;
}
void process_connection(int cfd)
{
char buf[BUFSIZE];
strcpy(buf, "X is counter");
write(cfd, buf, BUFSIZE);
read(cfd, buf, BUFSIZE);
puts(buf);
}
int connect_server(char* host, int port)
{
int cfd;
struct sockaddr_in caddr;
struct hostent* hp;
int ret;
cfd = socket(PF_INET, SOCK_STREAM, 0);
if (cfd < 0) {
return -1;
}
memset((char*) &caddr, 0, sizeof(struct sockaddr_in));
caddr.sin_family = AF_INET;
caddr.sin_port = htons(port);
hp = gethostbyname(host);
memcpy(&caddr.sin_addr.s_addr, *hp->h_addr_list, hp->h_length);
ret = connect(cfd, (struct sockaddr*) &caddr, sizeof(caddr));
if (ret < 0) {
close(cfd);
return ret;
}
return cfd;
}
クライアントはbindではなくconnectを使って接続します。
bindが自分のアドレスを指定するのに対し、connectは相手のアドレスを指定します。
共通ヘッダ
#define PORT 9977 #define HOST "localhost" #define BUFSIZE 1024
PORTやHOSTは引数で設定することができるようにするべきだろう。
データ渡しっぱなしでスレッド立ち上げ。 gccのオプションでは-lpthreadが必要。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define THREAD_MAX (100)
typedef struct {
int var;
} DetachObject;
void* run(void* arg);
DetachObject* newDetachObject(int i);
void destoryDetachObject(DetachObject* obj);
int main(int argc, char* argv[])
{
int i;
for (i = 0; i < THREAD_MAX; i++) {
pthread_t thread;
pthread_attr_t attr;
DetachObject* obj;
obj = newDetachObject(i);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, &run, obj);
}
puts("main exit");
return 0;
}
DetachObject* newDetachObject(int i)
{
DetachObject* obj;
obj = malloc(sizeof(DetachObject));
obj->var = i;
return obj;
}
void destoryDetachObject(DetachObject* obj)
{
free(obj);
}
void* run(void* arg)
{
DetachObject* obj = arg;
printf("thread %d: count=%d\n", (int) pthread_self(), obj->var);
destoryDetachObject(obj);
return NULL;
}
「スレッドに渡すオブジェクト」と「スレッドで実行する関数」を定義 するというのが基本。DETACHはjoinしない(戻り値を使わない)スレッドに使う。
mutexによる排他ロックを使った共有データの変更。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define THREAD_MAX (100)
typedef struct {
int var;
pthread_mutex_t mutex;
} SharedObject;
void* run(void* arg);
SharedObject* newSharedObject(void);
void destorySharedObject(SharedObject* obj);
int main(int argc, char* argv[])
{
SharedObject* obj;
pthread_t threads[THREAD_MAX];
int i;
obj = newSharedObject();
for (i = 0; i < THREAD_MAX; i++) {
pthread_create(&(threads[i]), NULL, &run, obj);
}
for (i = 0; i < THREAD_MAX; i++) {
int ret;
pthread_join(threads[i], (void**) &ret);
printf("result %dth: id=%d result=%d\n", i, (int) threads[i], ret);
}
destorySharedObject(obj);
puts("main exit");
return 0;
}
SharedObject* newSharedObject(void)
{
SharedObject* obj;
obj = malloc(sizeof(SharedObject));
obj->var = 0;
pthread_mutex_init(&(obj->mutex), NULL);
return obj;
}
void destorySharedObject(SharedObject* obj)
{
pthread_mutex_destroy(&(obj->mutex));
free(obj);
}
void* run(void* arg)
{
SharedObject* obj = arg;
int val;
int ret;
ret = pthread_mutex_lock(&(obj->mutex));
if (ret != 0) {
return (void*) -1;
}
obj->var++;
val = obj->var;
printf("thread %d: val=%d\n", (int) pthread_self(), obj->var);
ret = pthread_mutex_unlock(&(obj->mutex));
if (ret != 0) {
return (void*) -1;
}
return (void*) val;
}
排他する単位ごとにmutexを使う。 排他する領域はなるべくちいさくするのがいい。
waitと通知。タイムアウトを指定する場合は pthread_cond_timedwaitを、 複数スレッドのwaitに対し通知する場合は pthread_cond_broadcastを使えばいい。
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int wait_count;
int counter;
pthread_mutex_t mutex;
pthread_cond_t cond;
} NotifyObject;
void* run_wait(void* arg);
void* run_notify(void* arg);
NotifyObject* newNotifyObject(int wait_count);
void destoryNotifyObject(NotifyObject* obj);
int main(int argc, char* argv[])
{
NotifyObject* obj;
pthread_t wait_thread;
int i;
obj = newNotifyObject(100);
pthread_create(&wait_thread, NULL, &run_wait, obj);
sleep(1);
for (i = 0; i < obj->wait_count; i++) {
pthread_t notify_thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(¬ify_thread, &attr, &run_notify, obj);
}
pthread_join(wait_thread, NULL);
destoryNotifyObject(obj);
puts("main exit");
return 0;
}
NotifyObject* newNotifyObject(int wait_count)
{
NotifyObject* obj;
obj = malloc(sizeof(NotifyObject));
obj->wait_count = wait_count;
obj->counter = 0;
pthread_mutex_init(&(obj->mutex), NULL);
pthread_cond_init(&(obj->cond), NULL);
return obj;
}
void destoryNotifyObject(NotifyObject* obj)
{
pthread_mutex_destroy(&(obj->mutex));
pthread_cond_destroy(&(obj->cond));
free(obj);
}
void* run_wait(void* arg)
{
NotifyObject* obj = arg;
int i;
int ret;
ret = pthread_mutex_lock(&(obj->mutex));
if (ret != 0) {
return (void*) -1;
}
for (i = 0; i < obj->wait_count; i++) {
while (obj->counter == 0) {
ret = pthread_cond_wait(&(obj->cond), &(obj->mutex));
if (ret != 0) {
pthread_mutex_unlock(&(obj->mutex));
return (void*) -1;
}
}
obj->counter--;
puts("consume");
}
pthread_mutex_unlock(&(obj->mutex));
return NULL;
}
void* run_notify(void* arg)
{
NotifyObject* obj = arg;
int ret;
ret = pthread_mutex_lock(&(obj->mutex));
if (ret != 0) {
return (void*) -1;
}
obj->counter++;
puts("supply");
pthread_cond_signal(&(obj->cond));
pthread_mutex_unlock(&(obj->mutex));
return NULL;
}
共有オブジェクトがリソース待ちをするプログラム。
つまりrun_waitはcounterが0になるまでへらし、run_notifyは
counterを1増やす。
注意点はwaitするとき、通知するときは同じmutexでロックすること。
やはりANSI-Cプログラミングでいちばんめんどうなのはエラー処理だ。
つぎはブロック先頭でしかできない変数宣言。
クラスはなくてもいいから、この2つだけでも克服したISO-Cがいいなあやっぱり。
あとCがC++より楽なのはやはりvoid*か。キャストが要らないから。
つぎはglibにしようか、でもglibは大きいしなあ。。。
そのまえにzlib(もちろんgzreadとかgzwriteとか)にしようか。。。
うーん、getoptとかregexとかも抑えておきたい気もする。。。