TV WATCH

Latest 5 days
Last Modified : 11/17 22:42
Total Access :
Today Access :
Your Access : COOKIE_TIMES: deprecated in static mode.

Prev 2001/11 Next
Sun Mon Tue Wed Thu Fri Sat
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
Schedule
TODO
  • 99 日記を書く

2001/11/17 (Sat)

#1 [PC] ( ^ ^) < TDS更新

1.5.4にシテミマシタ。
さあ容量が尽きるまでいくか。

2001/11/07 (Wed)

#1 [PC] ( ^^) < 無線LANにしちゃった。

サトームセンのパソコン館でSANWA SUPPLYのワイヤレスLANセット LAN-WL11SETを17800円+税で買った。 アクセスポイントをハブにつないで電源を入れて、PCカードを Linuxノートにさし込んだらすぐに使えた。
Windowsではドライバを入れるのに苦労した。 だってドライバがCD-ROMに入ってるんだもん。 PCカードさしたらCD-ROMが使えないのに。。。
アクセスポイントはなるべく下に置くことにした。 上半面だけしか電波が飛ばないみたいからだ。 まあ天上にさかさまにつけてもいいだろうけど。
アクセスポイント管理ツールがWindows専用なのは唯一のマイナス。 まあ自分で独自プロトコルを解析すればいいんだろうけど。 ブラウザでアクセスできればいいのにね。
サンワサプライのLinuxページ

2001/10/03 (Wed)

#3 [PC] ( T T) < Emacsの補完

Emacsつかってプログラムを書いているのに補完を知らない人が多い。
M-/」です。
ちなみにとっても賢いインデントはTABね。

#2 [PC] ( ^ ^) < kernel-2.4.10へ

debian sidにkernel-2.4.10登場。 さっそくアップデート。 debianのカーネル2.4はinitrdがcramfs(Compresed RAM File System?)になっていて、 起動時に/initrdにマウントできるパッチが当たっています。 だからide-diskやext2、reiserfsなどもモジュールでOKなんです。 もちろんcramfsはカーネルに組み込まれているわけですが。
kernel.org などからダウンロードしたものをdebianで使うには/をマウントするのに最低限 必要なものはカーネルに組み込まなくてはいけないでしょう。 つまり、ディスクを認識するドライバ(ATAPI-IDEの場合ide-disk)と ルートファイルで使っているファイルシステムのドライバ(ext2とかreiserfsとか) をモジュールではなく組み込む必要があるでしょう。

#1 [PC] ( ;^ ^) < /var/lib/dpkg/以下のファイルを回復する方法

最近、apt-getでインストールに失敗するなどで /var/lib/dpkg/availableや/var/lib/dpkg/statusがこわれてしまう ことが多い。等間隔で文字のコードが+1されていたりと、 こわれ方に規則性があるのでたぶんdpkgのバグだろうか。
初めはテキストエディタで該当個所を修正していたが、 なんとdselect(apt-getでもaptitudeでもなく)で直るではないか。 dselectの中で[U]pdateしたらこれらのファイルは正しくなります。
dselectなんてslink以降もう使わないだろうと思っていた。 でもdpkgがなおるまでまた何回もお世話になるだろうな。

2001/09/25 (Tue)

#4 [プログラミング] ( ;^ ^) < ANSI-C言語のめんどうな点

やはりANSI-Cプログラミングでいちばんめんどうなのはエラー処理だ。 つぎはブロック先頭でしかできない変数宣言。 クラスはなくてもいいから、この2つだけでも克服したISO-Cがいいなあやっぱり。
あとCがC++より楽なのはやはりvoid*か。キャストが要らないから。
つぎはglibにしようか、でもglibは大きいしなあ。。。 そのまえにzlib(もちろんgzreadとかgzwriteとか)にしようか。。。 うーん、getoptとかregexとかも抑えておきたい気もする。。。

#3 [プログラミング] ( ^ ^) < pthread プログラミング3

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(&notify_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でロックすること。

#2 [プログラミング] ( ^ ^) < pthread プログラミング2

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を使う。 排他する領域はなるべくちいさくするのがいい。

#1 [プログラミング] ( ^ ^) < pthread プログラミング1

データ渡しっぱなしでスレッド立ち上げ。 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しない(戻り値を使わない)スレッドに使う。

2001/09/24 (Mon)

#1 [プログラミング] ( ^ ^) < ソケットプログラミング

サーバ

 #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は引数で設定することができるようにするべきだろう。


for 5 day(s).

[最新] [先月] [今月] [来月] [一覧]

[URL List] [Dictionary]

[static,style:t-hermes,cache:on]
Powered by Tomsoft Diary System 1.5.5
Copyright(C) 2001 by ichiyama ryoichi <ichiyama@jc4.so-net.ne.jp>. All rights reserved.