Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2036297
  • 博文数量: 610
  • 博客积分: 11499
  • 博客等级: 上将
  • 技术积分: 5511
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-12 19:27
文章分类

全部博文(610)

文章存档

2016年(5)

2015年(18)

2014年(12)

2013年(16)

2012年(297)

2011年(45)

2010年(37)

2009年(79)

2008年(101)

分类: LINUX

2009-10-24 00:42:02

POSIX线程(一)
第12章 POSIX线程

在第11章,我们看到在Linux中进程是如何被处理的。这些多进程的特性很久以来就是类Unix操作系统的特性。有时使用fork创建一个新进程的代价实在是太大了。在这种情况下,使得一个程序同时做两件事情,或者至少看起来是如此是十分有用的。相对应的,我们也许希望以同样的方式同时发生两个或是更多的事情。这就是线程开始的地方。

在这一章,我们将会了解:

在一个进程内创建一个线程
在一个进程的多个线程之间同步数据
修改一个线程的属性
在同一个进程中由一个线程控制另一个

什么是线程

一个程序内的多个执行线路被称之为线程。更为精确的定义是线程是一个进程内的控制队列。到目前为止我们所看到的所有程序都是作为单个进程来执行的,尽管与许多其他的操作系统相类似,Linux具有同时运行多个进程的能力。确实,所有的进程至少有一个执行线程。在本书中到目前为止我们所看到的所有进程都只有一个执行线程。

分清fork系统调用与新线程的创建是很重要的。当一个进程执行一个fork系统调用,就创建一个进程拷贝,具有其自己的变量与PID。这个新进程是单独调度的,而且(通常如此)其执行是与创建他的进程相独立的。当我们在进程内创建一个新的线程,新线程的执行拥有其自己的堆栈(因而具有局部变量),但是共享全局变量,文件描述符,信号处理器,而且其当前目录与创建他的进程相同。

线程的概念已经存在一段时间了,但是直到IEEE POSIX委员会发布了一些标准,但是他们在类Unix操作系统并不是广泛可用,而且其实现确实在不同的提供商之间存在着变化。有了POSIX 1003.1c规范,所有一切都变了;线程不仅进行了标准化,而且在绝大多数的Linux发行版本中都可用。

Linux首先在1996年左右使用一个通常被为"LinuxThreads"的库来支持线程。这与POSIX标准十分接近(确实,由于多种原因,许多区别并不明显),而他是使得Linux程序第一次使用线程的重要一步。然而,在Linux实现与POSIX标准之间有一些小的差异,大多数都是有关信号处理。这些限制不令在库实现上显现出来,而且更多的限制是由于Linux内核底层的支持。

许多项目关注于Linux上的线程支持如何得到改进,而不仅是消除Linux实现与POSIX标准之间的差异。许多工作将中心放在用户层线程应如何映射到内核层线程。两个主要的项目是New Generation POSIX Thread(NGPT)与Native POSIX Thread Library(NPTL)。两个项目都对Linux内核做出了修改以支持新的库,而且都在旧的Linux线程上提供了重要性能改进。

在2002年,NGPT团队声明他们不希望分裂社区,并且停止向NGPT中添加新的特性,但是继续在Linux线程支持方面进行工作,在NPTL努力的背后有他们的重要贡献。所以,很明显NPTL将成为Linux上新的线程标准,而且第一个NPTL主线版本出现在Red Hat Linux 9中。关于NPTL的一些有趣背景信息可以在一篇名为"The Native POSIX Thread Library for Linux"中看到。

本章的大多数代码都会使用这个线程库,因为他基于POSIX标准。然而,如果并没有使用过NPTL,我们就会觉得有些奇怪,特别是当他们运行时我们使用 ps来查看时更是如此。使用旧的Linux线程库,我们通常会看到多个进程,通常会多于我们所执行的线程;使用NPTL,我们只会看到一个程序,尽管在其内部有多个线程。

线程的优点与不足

在特定的条件下,与创建一个新进程相比,创建一个线程有一些特别的优点。创建一个新线程的代价要比创建一个新进程小得多(尽管与其他操作系统比起来,Linux在创建进程方面特别高效)。

下面是使用线程的一些例子:

有时使得一个程序看起来同时做两件事十分有用。一个经典的例子就是在一个文档上在编辑文本的同时进行实时的字数统计。一个线程可以管理用户的输入与执行编辑。可以看到文档内容的另一个线程可以持续的更新字数统计变量。前一个线程(或者是第三个线程)可以使用这个共享变量来提醒用户。另一个例子就是多线程数据服务器,当一个进程服务多个客户时,使用线程通过服务多个请求改善负载数据。对于一个数据服务器,透明的多任务在不同的进程是很难有效完成的,因为这要求锁,而数据一致会引起不同进程很难同步。这样的情况使用多线程要比使用多进程容易解决得多。

混全使用输入,计算与输出的程序通过将其作为三个独立的线程来运行,程序的性能会得到极大的改进。当输入或是输出线程等待连接时,另一个可以继续运行。所以,当程序最终只能一次只做一件事时,线程可以使得一个程序在等待连接时做一些有用的事。处理多个网络连接服务器程序就是适用多线程程序的一个例子。

通常而言,在线程之间进行切换对于操作系统的要求要比在进程之间切换小得多。所以,多线程比起多进程更少的依赖系统资源,这对于那些逻辑上要求在一个处理器的系统上有多个执行线程的程序更为实用。也就是说,编写一个多线程程序的设计困难是很大的,不应轻视。

线程的缺点:

编写多线程的程序需要小心的设计。引入潜在的时间错误,或是在一个多线程程序中未预料的共享变量引起的问题都需要考虑到。Alan Cox曾评价说,线程就是所谓的"如何同时射中自己的两只脚"。

调试多线程程序要比调试单线程程序困难得多,因为线程之间的交互非常难于控制。

将一个大的计算分为两部分并用作为不同的线程来运行这两部分在单处理器机器上并不见得会运行快,因为只有这么多的CPU周期,尽管并没有其他的程序在尝试运行,而且我们只有拥有多处理器或是超线程CPU,多线程的方法才会获得益处。
阅读(827) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~