スレッドメモ

MLやNewsのスレッドをメモする試み。

2003|01|02|04|05|06|07|08|10|11|
2004|01|04|05|06|07|08|09|11|12|
2005|01|02|04|08|09|
2006|01|03|04|08|
2007|01|05|
2009|05|

2004-05-14 (金)

[fj][fj.os.linux] [Q] source code of connect system call

<86ad0bz0id.wl@soro1.cc.hokudai.ac.jp> Hiroki Kashiwazaki (5/14)

ネットワークプログラミングをして遊んでいる今日このごろなのですが、 connect のソースを読んでみたいなーとか考えて、libcのソースを get してきました (glibc_2.2.5.orig.tar.gz)。が、展開して探してみても connectがどこにあるのか探し当てる事は出来ませんでした。connectは system callだから、カーネルなのかしらんと、カーネルソースを取得 してきたのですが、これまた探し当てる事が出来ませんでした。

<3989746news.pl@insigna.ie.u-ryukyu.ac.jp> Shinji KONO (5/15)

それを見たいんだったら、gdb で、一回connect を呼び出してから、 x/20i connect で disassemeble するのが簡単です。何故一回呼び出すか というと、dynamic link されているから...

で、

0x400ff2f0 <__libc_connect>:    mov    %ebx,%edx
0x400ff2f2 <__libc_connect+2>:  mov    $0x66,%eax
0x400ff2f7 <__libc_connect+7>:  mov    $0x3,%ebx
0x400ff2fc <__libc_connect+12>: lea    0x4(%esp,1),%ecx
0x400ff300 <__libc_connect+16>: int    $0x80
0x400ff302 <__libc_connect+18>: mov    %edx,%ebx
0x400ff304 <__libc_connect+20>: cmp    $0xffffff83,%eax
0x400ff307 <__libc_connect+23>: jae    0x400ff30a <__libc_connect+26>
みたいなのが見れるので... 0x66 = 102 がシステムコール番号 だってのがわかります。

> #アセンブラソースも grep しました?>>柏崎さん

これもかなり正解に近いんですが、cpp を通るので、.s でなくて、.S だったりします。Linux には、システムコールの番号は、libc と entry.S に分離して記述されているんです。BSDだと、このあたりは config がやるんですが...

linux-2.6.5/arch/i386/kernel/entry.S

で、そこを見ても connect というのはなくて... 102 という番号を頼りに、

.long sys_fstatfs       /* 100 */
.long sys_ioperm
.long sys_socketcall
.long sys_syslog

とかいうのがあるので、sys_socketcall だってのがわかるわけですね。

でも、それでも、行きつけない。何故なら、

 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, sock->file->f_flags);

となっていて、実は、indirect call だから。そりゃそうなんで、connect といっても、TCPとは限らない。decnet (ふる〜) かも知れないし。

ってのがあるから、

In /Users/kono/src/linux/linux-2.6.5/net/ipv4/tcp_ipv4.c
753:/* This will initiate an outgoing connection. */
754:int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
755:{
756:    struct inet_opt *inet = inet_sk(sk);
だってのがわかりますね。

<86ekphxceq.wl@soro1.cc.hokudai.ac.jp> Hiroki Kashiwazaki (5/19)

ようやくクリアになりつつありますが、もう何点か。 理解のための僕の思考過程をまとめると、以下のようになります。

  • connect を使うのに <sys/socket.h> を include する。
  • <sys/socket.h> には extern int connect ... の宣言がある。
  • コンパイルする時に libc とリンクが行われる
  • libc で connect は アセンブラでコーディングされているので、connectのCのソースを探そうとしても見つからない。
  • connectのアセンブラソースには

> レジスタ EAX に 0x66 を、EBX に 3 を、ECX には呼び出し元から
> 渡されたディスクリプタをセットして、割り込み 0x80 を発生させる
というコードが書かれてある。 [でもこれはどこにある ?]

  • arch/i386/kernel/entry.S に記述されているように呼び出す関数から EAX==0x66に対応する sys_socketcall を得る。sys_socketcall に与える引数 には EBX==3 が定められる。

    ↓

  • sys_socketcall ( EBX==3==SYS_CONNECT , hogehoge ) を呼び出す

    ↓

  • sys_connect を呼び出す

    ↓

  • socket file descriptorに適切な関数を呼び出す

2003|01|02|04|05|06|07|08|10|11|
2004|01|04|05|06|07|08|09|11|12|
2005|01|02|04|08|09|
2006|01|03|04|08|
2007|01|05|
2009|05|