.long SYMBOL_NAME(sys_sched_yield)
/*用来强制核心重新调度进程(或线程)*/
.long SYMBOL_NAME(sys_sched_get_priority_max)
/*用来设置进程(或线程)的调度参数*/
.long SYMBOL_NAME(sys_sched_get_priority_min)
/*用来获取进程(或线程)的调度参数*/
.long SYMBOL_NAME(sys_sched_rr_get_interval) /* 系统调用161 */
/*用来获取进程(或线程)的调度时间间隔*/
3 Linux线程的实现
现在的0.8版LinuxThreads,是迄今为止在Linux下支持threads的最好的
Runtime-library,而包含0.8版LinuxThreads的最好的Runtime-library
是glibc- 2.1,下文所要分析的正是glibc-linuxthreads-2.1。
首先介绍一下0.8版LinuxThreads,它实现了一种BiCapitalized面向
Linux的Posix 1003.1c"pthread"标准接口。LinuxThreads提供核心级线
程即每个线程是一个独立的UNIX进程,通过调用新的系统调用与其它线程
共享地址空间。线程由核心调度,就象UNIX进程调度一样。使用它的要求
是:LINUX 版本2.0 或以上(要求有新的clone() 系统调用和新的实时调
度程序)。对于Intel平台:要求有libc 5.2.18或后续版本,推荐使用
5.2.18 或 5.4.12 及其后续版本;5.3.12和5.4.7有问题,也支持glibc 2
,实际上是支持它的一个特别合适的版本。到目前支持Intel, Alpha, Sparc
, Motorola 68k, ARM and MIPS平台,还支持多处理器
4 问题及发展
4.1LinuxThread与POSIX标准
4.1.1 已知的漏洞和局限
A 没有共享的是它们的进程号和父进程号。根据标准应该相同,但这是我们没
有实现的(直到clone()的CLONE_PID标志可用)。在最近的内核中(最近的
2.1版本和即将发布的2.2版本),超过32个信号是作为实时信号提供的。当
运行在这些内核上时,LinuxThreads使用两个保留的实时信号为内部操作用
,因而留下两个空余信号SIGUSR1和SIGUSR2给用户代码用。线程共享进程号
会使/proc出现问题并且信号可能会错传到父进程那里。现在,实现时使用
了两个信号SIGUSR1和SIGUSR2,所以用户不能使用它们。理论上,应该为库
保留两个信号,但是大概2.1.60版本以上就没有这个问题了。
B 线程栈分配在高端存储空间,在初始进程的堆栈下2M远处。采用"按需增长"
策略,所以初始化时不会使用很多虚拟空间(现在是4K),如果需要可以增
长到2M。为每个线程保留这么大的地址空间意味着,在32位体系结构下,每
个进程不能有超过大约1023个线程共存(假设每个用户进程有2GB地址空间)
,但是这是合理的,因为每个线程使用核心的进程表的一项,而它通常限制
为512项。
C “按需增长”的潜在问题是无法防止用户映射某些数据到为线程栈保留的2M
地址,这可能导致以后的堆栈扩展失败。在使用这个库的时候,应该避免在
固定的地址上映射。
D 信号处理不是与Posix标准完全一致,基于一个事实即线程是可以能够单独发
送信号的特殊进程,所以没有发送一个信号到这个进程(所有线程的集合)
的概念。更精确的说,如下是标准的要求和实现如何满足它们的:(括号中
是LINUX的具体处理方法)
1-同步信号(比如SIGFPE,是由线程的执行产生的)被传送到产生它们的线
程那里(符合标准)。
2-一个致命的异步信号将终止进程中的所有线程。(符合标准。线程处理器
一旦发现某一个线程因一个信号而终止,它将同时终止接收到此信号的其
它线程。)
3-一个异步信号将被送给程序的某一个没有阻塞该信号的线程(未指定具体
是哪一个)。(不符合标准,信号只会根据进程ID发送给相应的线程,如
果该线程正在阻塞该信号则该信号被阻塞。)
4-信号将被发送给至少一个线程。(符合标准。对于由终端产生或发送给进
程组的信号,它们将被发送给所有符合条件的线程。)
E 目前对MIPS支持的实现是基于MIPS ISA II或更高级的处理器的。这些处理器
通过ll/sc指令支持原子操作。而老式的R2000/R3000系列的处理器目前还不
被支持,支持这些老式处理器需要更大的开销。
F 目前对ARM系列处理器的支持的实现中假设它们都有SWP指令(内存原子交换
登记)。但实际是ARM1和ARM2处理器并不支持此指令。在StrongARM处理器中
,SWP指令没有绕过CACHE,因此实现对多处理器的支持将会比较复杂。
4.1.2 进程共享的互斥、条件和信号量
为什么Linux线程没有实现进程共享的互斥、条件和信号量?
这是POSIX标准的一个可选部分。可移植的程序在使用此机制之前必需检查宏
_POSIX_THREAD_PROCESS_SHARED是否存在。
该扩展标准的目的是使不同的进程(也就是说在不同的地址空间中)可以通过
在共享内存(无论是SRV4的共享内存段还是用mmfile()产生的内存文件)中的
互斥、条件和信号量来实现进程间的同步。
在Linux线程中没有实现此功能的原因是在Linux中互斥、条件和信号并不是独
立的:它们的等待队列包含着指向线程描述符连接表的指针,而这些指针只在
特定的地址空间才有效。
Matt Messier和Sean Walton花了相当长的时间来设计一个在进程间共享等待队
列的适合的机制。我们得到了数个可以将下列三项特点中的两项结合起来的解决
方案,但没有一个可以将三者结合起来:
* 允许不同UID的进程之间的共享;
* 支持取消操作;
* 支持pthread_cond_timedwait
由此我们知道进程间共享互斥、条件和信号量需要内核的某些支持(而目前并不
支持)。这也许是Linus Torvalds的直觉“在内核中我们只需要clone()”的失败
之处之一。
在内核提供对它们的支持之前,你最好使用传统的进程间通讯方式来同步进程:
SYSTEM V信号量和消息队列,或管道或SOCKETS。
4.2 Linux线程展望
未来的目标是全面的兼容POSIX标准和尽可能实现POSIX标准中可选的功能,并进一步
提高LinuxThreads的效率。我相信这一天很快就会到来。
---pcjockey@21cn.com
综合了一些资料加上自己的一些解释
引用包括:
〈Write Multi-thread Code Solaris> -- 来自SUN的网站
〈Beyond Multiprocessing ...Multithreading the SunOS Kernel〉
-- J. R. Eykholt, S. R. Kleiman, S. Barton,
R. Faulkner, A. Shivalingiah, M. Smith,
D. Stein, J. Voll, M. Weeks, D. Williams ?
SunSoft, Inc.