システム・プログラムI 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro1-1998/1998-06-23
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
---------------------------------------------------------------------- 1: /* 2: vaddr-print.c -- 変数の番地をしらべるプログラム 3: ~yas/syspro1/cc/vaddr-print.c 4: $Header: vaddr-print.c,v 1.1 97/05/19 23:19:10 yas Exp $ 5: Start: 1997/05/19 22:58:49 6: */ 7: #include <stdlib.h> 8: 9: int x1=1 ; 10: int x2 ; 11: 12: extern int etext, edata, end ; 13: 14: main( argc,argv,envp ) 15: int argc ; 16: char *argv[] ; 17: char *envp[] ; 18: { 19: int x3 ; 20: char *x4p ; 21: 22: printf("&main == 0x%x \n",&main ); 23: printf("&etext == 0x%x \n",&etext ); 24: printf("&edata == 0x%x \n",&edata ); 25: printf("&end == 0x%x \n",&end ); 26: 27: printf("&x1 == 0x%x (data)\n",&x1 ); 28: printf("&x2 == 0x%x (bss)\n",&x2 ); 29: printf("&x3 == 0x%x (auto)\n",&x3 ); 30: x4p = malloc( 10 ); 31: printf("x4p == 0x%x (heap)\n",x4p ); 32: x4p = malloc( 10 ); 33: printf("x4p == 0x%x (heap)\n",x4p ); 34: recursive( 3 ); 35: } 36: 37: recursive( n ) 38: int n ; 39: { 40: int x5 ; 41: printf("&x5 == 0x%x (auto,%d)\n",&x5,n ); 42: if( n<=0 ) 43: return; 44: recursive( n-1 ); 45: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % cp ~yas/syspro1/cc/vaddr-print.c .% make vaddr-print
cc vaddr-print.c -o vaddr-print % ./vaddr-print
&main == 0x400ad0 &etext == 0x400cb0 &edata == 0x10002000 &end == 0x10002000 &x1 == 0x100010d0 (data) &x2 == 0x10001130 (bss) &x3 == 0x7fff2f1c (auto) x4p == 0x10002010 (heap) x4p == 0x10002028 (heap) &x5 == 0x7fff2ef4 (auto,3) &x5 == 0x7fff2ecc (auto,2) &x5 == 0x7fff2ea4 (auto,1) &x5 == 0x7fff2e7c (auto,0) % size vaddr-print
text data bss dec hex filename 2933 304 28 3265 cc1 vaddr-print %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: 2: /* 3: echo-client-udp.c -- 文字列を送受信するクライアント(UDP/IP版) 4: ~yas/syspro1/ipc/echo-client-udp.c 5: $Header: /home/lab2/OS/yas/syspro1/ipc/RCS/echo-client-udp.c,v 1.4 1998/06/22 14:23:48 yas Exp $ 6: Start: 1997/06/16 21:22:26 7: */ 8: #include <stdio.h> 9: #include <sys/types.h> /* socket() */ 10: #include <sys/socket.h> /* socket() */ 11: #include <netinet/in.h> /* struct sockaddr_in */ 12: #include <netdb.h> /* gethostbyname() */ 13: 14: extern void echo_client_udp( char *hostname, int portno ); 15: extern int udp_port_not_bound(); 16: extern int sockaddr_in_init( struct sockaddr_in *addr, char *hostname, int portno ); 17: extern void sockaddr_in_print( struct sockaddr_in *addr ); 18: extern void sockname_print( int s ); 19: 20: main( int argc, char *argv[] ) 21: { 22: if( argc != 3 ) 23: { 24: fprintf( stdout,"Usage: %s host port\n",argv[0] ); 25: exit( -1 ); 26: } 27: echo_client_udp( argv[1],atoi(argv[2]) ); 28: } 29: 30: void echo_client_udp( char *hostname, int portno ) 31: { 32: int s, rcount, scount, len, fromlen ; 33: struct sockaddr_in to, from ; 34: char buf[BUFSIZ]; 35: 36: s = udp_port_not_bound(); 37: if( s<0 ) 38: exit( -1 ); 39: printf("my port is "); sockname_print( s ); 40: 41: strncpy( buf,"hello",sizeof(buf) ); 42: len = strlen( buf ) + 1 ; 43: sockaddr_in_init( &to, hostname, portno ); 44: printf("sending [%s] (%d bytes) to ", buf,len ); 45: sockaddr_in_print( &to ); 46: if( scount = sendto( s, buf, len, 0, &to, sizeof(to) )!= len ) 47: { 48: perror("sendto()"); 49: exit( 1 ); 50: } 51: printf("after sendto(), my port is "); sockname_print( s ); 52: 53: fromlen = sizeof( from ); 54: if( (rcount = recvfrom( s, buf, BUFSIZ, 0, &from, &fromlen )) < 0 ) 55: { 56: perror("recvfrom()"); 57: exit( 1 ); 58: } 59: printf("received from "); sockaddr_in_print( &from ); 60: buf[rcount] = 0 ; 61: printf("%d bytes received. [%s] \n", rcount, buf ); 62: 63: close( s ); 64: } 65: 66: int udp_port_not_bound() 67: { 68: int s ; 69: if( (s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) 70: { 71: perror("socket"); 72: return( -1 ); 73: } 74: return( s ); 75: } 76: 77: int sockaddr_in_init( struct sockaddr_in *addr, char *hostname, int portno ) 78: { 79: struct hostent *hostent ; 80: addr->sin_family = AF_INET ; 81: if( (hostent = gethostbyname( hostname )) == NULL ) 82: { 83: fprintf(stderr,"unknown host %s\n",hostname ); 84: return( -1 ); 85: } 86: bcopy( hostent->h_addr, &addr->sin_addr, hostent->h_length ); 87: addr->sin_port = htons( portno ); 88: return( 0 ); 89: } 90: 91: void sockaddr_in_print( struct sockaddr_in *addr ) 92: { 93: union { 94: int i ; 95: unsigned char byte[4] ; 96: } x ; 97: x.i = addr->sin_addr.s_addr ; 98: printf("sockaddr_in: %d.%d.%d.%d:%d\n", 99: x.byte[0],x.byte[1],x.byte[2],x.byte[3], 100: ntohs( addr->sin_port )); 101: } 102: 103: void sockname_print( int s ) 104: { 105: struct sockaddr_in addr ; 106: int len ; 107: len = sizeof( addr ); 108: if( getsockname( s, &addr, &len )< 0 ) 109: { 110: perror("getsockname"); 111: exit( -1 ); 112: } 113: sockaddr_in_print( &addr ); 114: } ----------------------------------------------------------------------
クライアント側では、bind() で名前を付けていない。sendto() の時に、自動 的にオペレーティング・システムにより、名前が付けられる。同じことは、 porno=0 で bind() しても可能である。オペレーティング・システムによって 付けられた名前は、後で getsockname() で調べることができる。
明示的に bind() する方法もある。
実行例。
---------------------------------------------------------------------- % ./echo-client-udp adonis1 7my port is sockaddr_in: 0.0.0.0:0 sending [hello] (6 bytes) to sockaddr_in: 130.158.86.1:7 after sendto(), my port is sockaddr_in: 0.0.0.0:8013 received from sockaddr_in: 130.158.86.1:7 6 bytes received. [hello] % ./echo-client-udp adonis11 7
my port is sockaddr_in: 0.0.0.0:0 sending [hello] (6 bytes) to sockaddr_in: 130.158.86.11:7 after sendto(), my port is sockaddr_in: 0.0.0.0:8014 received from sockaddr_in: 130.158.86.11:7 6 bytes received. [hello] % ./echo-client-udp localhost 7
my port is sockaddr_in: 0.0.0.0:0 sending [hello] (6 bytes) to sockaddr_in: 127.0.0.1:7 after sendto(), my port is sockaddr_in: 0.0.0.0:8015 received from sockaddr_in: 127.0.0.1:7 6 bytes received. [hello] %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: 2: /* 3: echo-server-udp.c -- 文字列を送受信するサーバ(UDP/IP版) 4: ~yas/syspro1/ipc/echo-server-udp.c 5: $Header: /home/lab2/OS/yas/syspro1/ipc/RCS/echo-server-udp.c,v 1.3 1998/06/22 14:24:17 yas Exp $ 6: Start: 1997/06/16 21:22:26 7: */ 8: #include <stdio.h> 9: #include <sys/types.h> /* socket() */ 10: #include <sys/socket.h> /* socket() */ 11: #include <netinet/in.h> /* struct sockaddr_in */ 12: #include <netdb.h> /* gethostbyname() */ 13: 14: extern void echo_server_udp( int portno ); 15: extern int udp_port_bind( int portno ); 16: extern int sockaddr_in_init( struct sockaddr_in *addr, char *hostname, int portno ); 17: extern void sockaddr_in_print( struct sockaddr_in *addr ); 18: extern void sockname_print( int s ); 19: 20: main( int argc, char *argv[] ) 21: { 22: int portno ; 23: if( argc >= 3 ) 24: { 25: fprintf( stdout,"Usage: %s host port\n",argv[0] ); 26: exit( -1 ); 27: } 28: if( argc == 2 ) 29: portno = atoi( argv[1] ); 30: else 31: portno = getuid(); 32: echo_server_udp( portno ); 33: } 34: 35: void echo_server_udp( int portno ) 36: { 37: int s, rcount, scount, addrlen ; 38: struct sockaddr_in addr ; 39: char buf[BUFSIZ]; 40: 41: s = udp_port_bind( portno ); 42: if( s<0 ) 43: exit( -1 ); 44: printf("my port is "); sockname_print( s ); 45: 46: while( 1 ) 47: { 48: addrlen = sizeof( addr ); 49: if( (rcount = recvfrom( s, buf, BUFSIZ, 0, &addr, &addrlen )) < 0 ) 50: { 51: perror("recvfrom()"); 52: exit( 1 ); 53: } 54: buf[rcount] = 0 ; 55: printf("received %d bytes [%s] from ",rcount, buf ); 56: sockaddr_in_print( &addr ); 57: printf("sending back [%s] (%d bytes) to ", buf, rcount ); 58: sockaddr_in_print( &addr ); 59: if( scount = sendto( s, buf, rcount, 0, &addr, addrlen )!= rcount ) 60: { 61: perror("sendto()"); 62: exit( 1 ); 63: } 64: } 65: } 66: 67: int udp_port_bind( int portno ) 68: { 69: struct hostent *hostent ; 70: struct sockaddr_in addr ; 71: int addr_len ; 72: int s ; 73: 74: if( (s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) 75: { 76: perror("socket"); 77: return( -1 ); 78: } 79: 80: addr.sin_family = AF_INET ; 81: addr.sin_addr.s_addr = INADDR_ANY ; 82: addr.sin_port = htons( portno ); 83: 84: if( bind(s,&addr,sizeof(addr)) < 0 ) 85: { 86: perror( "bind: " ); 87: fprintf(stderr,"port number %d is already used. kill another program.", portno ); 88: return( -1 ); 89: } 90: return( s ); 91: } <以下省略> ----------------------------------------------------------------------実行例。
サーバ側。サーバは、終了しないので、最後に、^C か Del を押して、割り込みを掛けて終了させる。
クライアント側(その1)。---------------------------------------------------------------------- % ./echo-server-udpmy port is sockaddr_in: 0.0.0.0:1231 received 6 bytes [hello] from sockaddr_in: 130.158.86.11:5890 sending back [hello] (6 bytes) to sockaddr_in: 130.158.86.11:5890 received 6 bytes [hello] from sockaddr_in: 130.158.86.1:8023 sending back [hello] (6 bytes) to sockaddr_in: 130.158.86.1:8023 received 6 bytes [hello] from sockaddr_in: 127.0.0.1:8024 sending back [hello] (6 bytes) to sockaddr_in: 127.0.0.1:8024 ^C %
----------------------------------------------------------------------
クライアント側(その2)。---------------------------------------------------------------------- % ./echo-client-udp adonis1 1231my port is sockaddr_in: 0.0.0.0:0 sending [hello] (6 bytes) to sockaddr_in: 130.158.86.1:1231 after sendto(), my port is sockaddr_in: 0.0.0.0:5890 received from sockaddr_in: 130.158.86.1:1231 6 bytes received. [hello] %
----------------------------------------------------------------------
クライアント側(その3)。---------------------------------------------------------------------- % ./echo-client-udp adonis1 1231my port is sockaddr_in: 0.0.0.0:0 sending [hello] (6 bytes) to sockaddr_in: 130.158.86.1:1231 after sendto(), my port is sockaddr_in: 0.0.0.0:8023 received from sockaddr_in: 130.158.86.1:1231 6 bytes received. [hello] % ----------------------------------------------------------------------
---------------------------------------------------------------------- % ./echo-client-udp localhost 1231my port is sockaddr_in: 0.0.0.0:0 sending [hello] (6 bytes) to sockaddr_in: 127.0.0.1:1231 after sendto(), my port is sockaddr_in: 0.0.0.0:8024 received from sockaddr_in: 127.0.0.1:1231 6 bytes received. [hello] %
----------------------------------------------------------------------
malloc() は、brk() システム・コール、または、sbrk システム・コールでオ ペレーティング・システムからメモリの割り当てを受けている。brk(), sbrk() は、プロセスのデータ・セグメントの終わりを変化させるシステム・ コールである。
main(int argc, argv[])
の引数である argv
をコピーするプログラムを作りなさい。コピーの方法としては、次の2種類が
考えられる。
ヒント:malloc() でメモリを割り当てて、内容をコピーする。コピーの方法 では、浅いコピーでは、文字列(文字の配列の先頭番地)をコピーする。深い コピーでは、strlen() +1 バイト malloc() して、番地を保存して strncpy() する。配列の終わりの 0 を忘れないように。
strdup() というライブラリ関数を使うと便利。
UDP/IP では、一度に送ることができるデータの大きさにには、実装上の制限 が付いている。これがいくつかを調べるプログラムを作りなさい。
UDP/IP のデータを中継するようなプログラムを作りなさい。 単方向だけでなく、双方向で中継するようにしなさい。
このようなプログラムの例として、udprelay と呼ばれるプログラムがある。
UDP/IP のサーバ、または、中継プログラムで、クライアントの IP アドレス によってアクセスを許したりエラーを発生させたりしなさい。