Linux thread programming


    Linux 的多线程编程相对 Windows 而言,确实比较麻烦,有些东西还往往让初学者却步。不过 hackers 却很少将大家的糟糕体验当作一回事,有时甚至会埋怨用户水平太差。让我们先看一个简单的示例程序。

    确认一下我所使用的 Linux 内核版本:

$ uname -a
Linux dev 2.4.21-9.30AXsmp #1 SMP Wed May 26 23:37:09 EDT 2004 i686 i686 i386 GNU/Linux

$ cat -n pthread.c
    1
    2 #include <signal.h>
    3 #include <pthread.h>
    4
    5 int main(void)
    6 {
    7     kill(54321, SIGUSR1);
    8     pthread_kill(54321, SIGUSR1);
    9
   10    return 0;
   11 }
   12

    我们想简单的测试一下 kill(), pthread_kill(),kill 一个不存在的进程或线程,看看系统是怎么反应的。很不幸,一出手就遇到了问题:

$ gcc -Wall -pthread pthread.c
$ .a.out
Segmentation fault

    把 man 手册打开看看,这种用法明明是正确的啊。上面这个小程序中 kill() 的执行是正确的,问题出在 pthread_kill()。Google 一番,找到了以下的一些链接:

What is wrong with pthread_kill on Redhat Linux ???

Crash running pthread_kill on dead thread

Explaining LD_ASSUME_KERNEL,Ulrich Drepper, 2004-5-12

Installing Oracle9i 32-bit on Red Hat Enterprise Linux Advanced Server 4, 3, 2.1, and on Red Hat 9, 8.0, 7.3, 7.2, 7.1 (x86),by Werner Puschitz

    原来 Linux 下有几种不同的线程实现,Ulrich Drepper 在 Explaining LD_ASSUME_KERNEL 中说得很清楚。我们需要做:

$ export LD_ASSUME_KERNEL=2.4.1
$ ./a.out (OK)

    现在,我们来看看下一个问题。一般的,我们要引用某个函数库 libfoo.a ,都是加个编译参数 -lfoo ,怎么对多线程就成了上面的 -pthread 了呢?原来 -pthread 和 -lpthread 之间的差别还是很重要的。我们试试:

$ gcc -Wall --verbose -pthread pthread.c
Reading specs from /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/u
sr/share/info --enable-shared --enable-threads=posix --disable-checking --with-s
ystem-zlib --enable-__cxa_atexit --host=i386-asianux-linux
Thread model: posix
gcc version 3.2.3 20030502 (Asianux 1.0 3.2.3-36)
/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/cc1 -lang-c -v -D__GNUC__=3 -D__GNUC_
MINOR__=2 -D__GNUC_PATCHLEVEL__=3 -D__GXX_ABI_VERSION=102 -D__ELF__ -Dunix -D__g
nu_linux__ -Dlinux -D__ELF__ -D__unix__ -D__gnu_linux__ -D__linux__ -D__unix -D_
_linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1 -Acpu=i386 -Amachine=i
386 -Di386 -D__i386 -D__i386__ -D__tune_i386__ -D_REENTRANT pthread.c -quiet -du
mpbase pthread.c -Wall -version -o /tmp/ccXGJ44s.s
GNU CPP version 3.2.3 20030502 (Asianux 1.0 3.2.3-36) (cpplib) (i386 Linux/ELF)
GNU C version 3.2.3 20030502 (Asianux 1.0 3.2.3-36) (i386-asianux-linux)
compiled by GNU C version 3.2.3 20030502 (Asianux 1.0 3.2.3-36).
ignoring nonexistent directory "/usr/i386-asianux-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/include
/usr/include
End of search list.
as -V -Qy -o /tmp/ccmf0nLO.o /tmp/ccXGJ44s.s
GNU assembler version 2.14.90.0.4 (i386-asianux-linux) using BFD version 2.14.90
.0.4 20030523
/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/collect2 --eh-frame-hdr -m elf_i386 -
dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../.
./../crt1.o /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../../../crti.o /usr/lib/g
cc-lib/i386-asianux-linux/3.2.3/crtbegin.o -L/usr/lib/gcc-lib/i386-asianux-linux
/3.2.3 -L/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../../.. /tmp/ccmf0nLO.o -lgc
c -lgcc_eh -lpthread -lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-asianux-linux/3.2.
3/crtend.o /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../../../crtn.o

$ gcc -Wall --verbose -lpthread pthread.c
Reading specs from /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/u
sr/share/info --enable-shared --enable-threads=posix --disable-checking --with-s
ystem-zlib --enable-__cxa_atexit --host=i386-asianux-linux
Thread model: posix
gcc version 3.2.3 20030502 (Asianux 1.0 3.2.3-36)
/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/cc1 -lang-c -v -D__GNUC__=3 -D__GNUC_
MINOR__=2 -D__GNUC_PATCHLEVEL__=3 -D__GXX_ABI_VERSION=102 -D__ELF__ -Dunix -D__g
nu_linux__ -Dlinux -D__ELF__ -D__unix__ -D__gnu_linux__ -D__linux__ -D__unix -D_
_linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1 -Acpu=i386 -Amachine=i
386 -Di386 -D__i386 -D__i386__ -D__tune_i386__ pthread.c -quiet -dumpbase pthrea
d.c -Wall -version -o /tmp/ccFonYlv.s
GNU CPP version 3.2.3 20030502 (Asianux 1.0 3.2.3-36) (cpplib) (i386 Linux/ELF)
GNU C version 3.2.3 20030502 (Asianux 1.0 3.2.3-36) (i386-asianux-linux)
compiled by GNU C version 3.2.3 20030502 (Asianux 1.0 3.2.3-36).
ignoring nonexistent directory "/usr/i386-asianux-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/include
/usr/include
End of search list.
as -V -Qy -o /tmp/ccizA2YS.o /tmp/ccFonYlv.s
GNU assembler version 2.14.90.0.4 (i386-asianux-linux) using BFD version 2.14.90
.0.4 20030523
/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/collect2 --eh-frame-hdr -m elf_i386 -
dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../.
./../crt1.o /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../../../crti.o /usr/lib/g
cc-lib/i386-asianux-linux/3.2.3/crtbegin.o -L/usr/lib/gcc-lib/i386-asianux-linux
/3.2.3 -L/usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../../.. -lpthread /tmp/ccizA
2YS.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-asianux-linux/3.2.
3/crtend.o /usr/lib/gcc-lib/i386-asianux-linux/3.2.3/../../../crtn.o

    原来前者自动加了个 -D_REENTRANT,至于这个东西有什么特殊之处,还是看看 Dave Butenhof 等的回答吧:-pthread and -lpthread


Copyright 2006-2007,zedware_at_gmail_dot_com
Last modified on Monday, 2006-08-21