做大文件的快速传输,需要调查一下bit torrent,下载了opentracker。
在编译libowfat的过程中,出现错误:
t.o: In function `main':
t.c:(.text+0x76): undefined reference to `__sync_bool_compare_and_swap_4'
t.c:(.text+0xa2): undefined reference to `__sync_bool_compare_and_swap_4'
collect2: ld returned 1 exit status
make: *** [t] Error 1
这个函数没有找到定义,是在t.c中使用的函数。
往上看了几行,发现抛出这条错误的编译命令是:
gcc -c t.c -pipe -W -Wall -O2 -fomit-frame-pointer -D_REENTRANT -I.
In file included from t.c:25:
iarray.h:5:2: warning: #warning DO NOT USE THIS YET. It may look thread-safe but it is not!
In file included from t.c:27:
CAS.h: In function ‘compare_and_swap’:
CAS.h:31: warning: no return statement in function returning non-void
CAS.h: In function ‘atomic_add_return’:
CAS.h:61: warning: no return statement in function returning non-void
t.c: In function ‘main’:
t.c:50: warning: unused parameter ‘argc’
t.c:50: warning: unused parameter ‘argv’
gcc -g -o t t.o libowfat.a `cat libsocket` -lpthread
打开t.c看了一下,发现t.c代码很短,只有几十行,引发错误的应该是这个函数调用:
printf("%u/n",compare_and_swap(&x,26,17));
printf("%u/n",compare_and_swap(&x,23,17));
用__sync_bool_compare_and_swap_4没有找到源代码,在源代码中搜索了一下:
[whb@jcwkyl libowfat]$ grep sync_bool_compare_and_swap *
CAS.h: __sync_bool_compare_and_swap(x,oldval,newval);
Binary file t.o matches
发现它定义在CAS.h文件中。
CAS.h文件也非常短,相关的代码一下子就能看到:
#if defined(__INTEL_COMPILER) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))
#define USE_BUILTINS
#endif
/* if (*x == oldval) { *x=newval; return 1; } else return 0; */
static inline int compare_and_swap(volatile size_t* x,size_t oldval,size_t newval) {
#ifdef USE_BUILTINS
__sync_bool_compare_and_swap(x,oldval,newval);
#elif defined(__i386__)
char result;
asm volatile ("lock; cmpxchgl %3, %0; setz %1" : "=m"(*x), "=q" (result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
return result;
#elif defined(__x86_64__)
char result;
asm volatile ("lock; cmpxchgq %3, %0; setz %1" : "=m"(*x), "=q" (result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
return result;
#else
#error architecture not supported and gcc too old, edit CAS.h
#endif
}
很显然因为定义了USE_BUILTINS宏,所以compare_and_swap调用的是__sync_bool_compare_and_swap(x,oldval,newval);
把这个宏去掉,换成__i386__,应该就没问题了,看一下CAS.h被哪些源文件引用过。
[whb@jcwkyl libowfat]$ grep CAS.h *
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
GNUmakefile: havesigio.h CAS.h
Makefile: iarray.h CAS.h io_internal.h haveepoll.h havekqueue.h havedevpoll.h /
Makefile: havesigio.h CAS.h
t.c:#include "CAS.h"
非常幸运,只有t.c一个文件引用了这个文件。所以,可以大胆地修改CAS.h:
static inline int compare_and_swap(volatile size_t* x,size_t oldval,size_t newval) {
#undef USE_BUILTINS
#ifndef __i386__
#define __i386__
#define jcwkyl
#endif
#ifdef USE_BUILTINS
__sync_bool_compare_and_swap(x,oldval,newval);
#elif defined(__i386__)
char result;
asm volatile ("lock; cmpxchgl %3, %0; setz %1" : "=m"(*x), "=q" (result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
#ifdef jcwkyl
#undef __i386__
#endif
#define USE_BUILTINS
return result;
#elif defined(__x86_64__)
char result;
asm volatile ("lock; cmpxchgq %3, %0; setz %1" : "=m"(*x), "=q" (result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
return result;
#else
#error architecture not supported and gcc too old, edit CAS.h
#endif
}
高亮部分是新增加的代码。这次make没有出错了。
随后opentracker也顺利make成功。
google一下,会找到这个错误的原因和解决方法,解决方法就是给gcc传递-march=i486参数。可参考:
http://stackoverflow.com/questions/2118992/how-do-i-use-gcc-builtin-sync-bool-compare-and-swap-in-g-on-macosx
http://bugs.gentoo.org/show_bug.cgi?id=199904
http://dev.ryzom.com/issues/899
http://www.linuxquestions.org/questions/linux-from-scratch-13/glibc-1st-pass-wont-compile-possibly-i486-related-704580/
...
使用opentracker用bitorrent下载一个文件:
[root@jcwkyl opentracker]# ./opentracker
用ctorrent制作一个torrent文件:
[whb@jcwkyl Desktop]$ ctorrent -t -u http://10.60.56.90:6969/announce -s test.torrent 10.1.1.14.5976.pdf
Create hash table: 1/1
Create metainfo file test.torrent successful.
[whb@jcwkyl Desktop]$ ctorrent -x test.torrent
META INFO
Announce: http://10.60.56.90:6969/announce
Created On: Wed Dec 15 19:32:21 2010
Piece length: 262144
Created with: Enhanced-CTorrent/dnh3.3.2
FILES INFO
<1> 10.1.1.14.5976.pdf [90160]
Total: 0 MB
把这个torrent文件用ftp下载到一个client端。然后在那个client端下载:
[root@server ~]# ctorrent test.torrent
META INFO
Announce: http://10.60.56.90:6969/announce
Created On: Wed Dec 15 19:32:21 2010
Piece length: 262144
Created with: Enhanced-CTorrent/dnh3.3.2
FILES INFO
<1> 10.1.1.14.5976.pdf [90160]
Total: 0 MB
Creating file "10.1.1.14.5976.pdf"
Listening on 0.0.0.0:2706
Press 'h' or '?' for help (display/control client options).
| 0/0/1 [0/1/0] 0MB,0MB | 0,0K/s | 0,0K E:0,1
Download complete.
Total time used: 0 minutes.
Seed for others 72 hours
- 0/0/2 [1/1/1] 0MB,0MB | 0,0K/s | 0,0K E:0,3 Connecting
同时在原来的机器上做种:
[whb@jcwkyl Desktop]$ ctorrent test.torrent
META INFO
Announce: http://10.60.56.90:6969/announce
Created On: Wed Dec 15 19:32:21 2010
Piece length: 262144
Created with: Enhanced-CTorrent/dnh3.3.2
FILES INFO
<1> 10.1.1.14.5976.pdf [90160]
Total: 0 MB
warn, couldn't set bit field refer file "test.torrent.bf": No such file or directory
This is normal if you are seeding.
Listening on 0.0.0.0:2706
Press 'h' or '?' for help (display/control client options).
Checking completed.
FILES INFO
<1> 10.1.1.14.5976.pdf [90160] 1/1 (100%)
Total: 0 MB
- 0/0/1 [1/1/1] 0MB,0MB | 0,0K/s | 0,0K E:0,0 Connecting
Seed for others 72 hours
文件下载成功。
打开浏览器,输入:
http://10.60.56.90:6969/stats?mode=everything
会查看到所有torrent文件,以及上传下载信息。