??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲А∨精品天堂在线,中文字幕精品三区无码亚洲,亚洲AV无码成人网站在线观看 http://www.tkk7.com/tinysun/archive/2010/10/04/333723.html何克?/dc:creator>何克?/author>Mon, 04 Oct 2010 02:36:00 GMThttp://www.tkk7.com/tinysun/archive/2010/10/04/333723.htmlhttp://www.tkk7.com/tinysun/comments/333723.htmlhttp://www.tkk7.com/tinysun/archive/2010/10/04/333723.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/333723.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/333723.html全文转蝲Q?a >http://blog.csdn.net/forfuture1978/archive/2009/10/22/4711308.aspx

作者:forfuture1978 (from CSDN)

 

 

 

我们都知道,Lucene是一个开放源代码 的全文检索引擎工具包。那么全文检索到底是什么? q要从我们生zM的数据说赗?/span>

 

我们生活中的数据M分ؓ两种Q?span style="color: #0000ff">l构化数?/strong> ?span style="color: #0000ff">非结构化数据 ?/p>

  • l构化数据: 指具有固定格式或有限长度的数据,如数据库Q元数据{?
  • 非结构化数据Q?/strong> 指不定长或无固定格式的数据,如邮Ӟword文档{?

当然有的地方q会提到W三U,半结构化数据Q如XMLQHTML{,当根据需要可按结构化数据来处理,也可抽取出纯文本按非l构化数据来处理?/p>

非结构化数据又一U叫法叫全文数据?/strong>

 按照数据的分c,搜烦也分ZU:

  • 对结构化数据的搜?/strong> Q如Ҏ据库的搜索,用SQL语句。再如对元数据的搜烦Q如利用windows搜烦Ҏ件名Q类型,修改旉q行搜烦{?
  • 寚wl构化数据的搜烦 Q如利用windows的搜索也可以搜烦文g内容QLinux下的grep命oQ再如用Google和百度可以搜索大量内Ҏ据?

寚wl构化数据也卛_全文数据的搜索主要有两种ҎQ?/p>

 

一U是序扫描?/strong> (Serial Scanning) Q?/strong> 所谓顺序扫描,比如要找内容包含某一个字W串的文Ӟ是一个文档一个文档的看,对于每一个文档,从头看到,如果此文档包含此字符Ԍ则此文档为我们要扄文gQ接着看下一个文Ӟ直到扫描完所有的文g。如利用windows的搜索也可以搜烦文g内容Q只是相当的慢。如果你有一?0G盘Q如果想在上面找C个内容包含某字符串的文gQ不׃几个时Q怕是做不到。Linux下的grep命o也是q一U方式。大家可能觉得这U方法比较原始,但对于小数据量的文gQ这U方法还是最直接Q最方便的。但是对于大量的文gQ这U方法就很慢了?/p>

 

有h可能会说Q对非结构化数据序扫描很慢Q对l构化数据的搜烦却相对较快(׃l构化数据有一定的l构可以采取一定的搜烦法加快速度Q,那么把我们的非结构化数据惛_法弄得有一定结构不p了吗Q?/p>

 

q种x很天Ӟ却构成了全文索的基本思\Q也卛_非结构化数据中的一部分信息提取出来Q重新组l,使其变得有一定结构,然后Ҏ有一定结构的数据q行搜烦Q从而达到搜索相对较快的目的?/p>

q部分从非结构化数据中提取出的然后重新组l的信息Q我们称?strong>索引 ?/p>

 

q种说法比较抽象QD几个例子很Ҏ明白Q比如字典,字典的拼韌和部首检字表q当于字典的烦引,Ҏ一个字的解释是非结构化的,如果字典没有韌表和部首字表Q在茫茫辞v中找一个字只能序扫描。然而字的某些信息可以提取出来进行结构化处理Q比如读韻I比较结构化Q分声母和韵母,分别只有几种可以一一列DQ于是将读音拿出来按一定的序排列Q每一读音都指向此字的详l解释的|。我们搜索时按结构化的拼x到读韻I然后按其指向的页敎ͼ便可扑ֈ我们的非l构化数据——也卛_字的解释?/p>

 

q种先徏立烦引,再对索引q行搜烦的过E就叫全文检?Full-text Search) ?/strong>

下面q幅图来自《Lucene in action》,但却不仅仅描qCLucene的检索过E,而是描述了全文检索的一般过E?img height="479" alt="" src="http://dl.javaeye.com/upload/picture/pic/55997/9512a770-0784-3231-9da5-608a46014b2d.png" width="544" />

 

全文索大体分两个q程Q?span style="color: #0000ff">索引创徏 (Indexing) ?span style="color: #0000ff">搜烦索引 (Search) ?/p>

  • 索引创徏Q将现实世界中所有的l构化和非结构化数据提取信息Q创建烦引的q程?
  • 搜烦索引Q就是得到用L查询hQ搜索创建的索引Q然后返回结果的q程?

于是全文索就存在三个重要问题Q?/p>

1. 索引里面I竟存些什么?(Index)

2. 如何创徏索引Q?Indexing)

3. 如何对烦引进行搜索?(Search)

下面我们序Ҏ个个问题q行研究?/p>

 

 

一?/span> 索引里面I竟存些什么?(Index)

 

首先我们来看Z么顺序扫描的速度慢:

 

其实是由于我们想要搜索的信息和非l构化数据中所存储的信息不一致造成的?/p>

非结构化数据中所存储的信息是每个文g包含哪些字符Ԍ也即已知文gQ欲求字W串相对ҎQ也x从文件到字符串的映射。而我们想搜烦的信息是哪些文g包含此字W串Q也卛_知字W串Q欲求文Ӟ也即从字W串到文件的映射。两者恰恰相反。于是如果烦引总能够保存从字符串到文g的映,则会大大提高搜烦速度?/p>

 

׃从字W串到文件的映射是文件到字符串映的反向q程Q于是保存这U信息的索引UCؓ反向索引 ?/p>

 

反向索引的所保存的信息一般如下:

假设我的文档集合里面?00文档,Z方便表示Q我们ؓ文档~号??00Q得C面的l构

 

左边保存的是一pd字符ԌUCؓ词典 ?/span>

每个字符串都指向包含此字W串的文?Document)链表Q此文档链表UCؓ倒排?/strong> (Posting List) ?/p>

有了索引Q便使保存的信息和要搜烦的信息一_可以大大加快搜烦的速度?/p>

 

比如_我们要寻找既包含字符?#8220;lucene”又包含字W串“solr”的文档,我们只需要以下几步:

1. 取出包含字符?#8220;lucene”的文档链表?/p>

2. 取出包含字符?#8220;solr”的文档链表?/p>

3. 通过合ƈ链表Q找出既包含“lucene”又包?#8220;solr”的文件?img height="55" alt="" src="http://hxraid.javaeye.com/upload/picture/pic/56001/7e04a727-6cdb-3434-a260-023bc163b497.jpg" width="544" />

看到q个地方Q有人可能会_全文索的加快了搜烦的速度Q但是多了烦引的q程Q两者加h不一定比序扫描快多。的,加上索引的过E,全文索不一定比序扫描快,其是在数据量小的时候更是如此。而对一个很大量的数据创建烦引也是一个很慢的q程?/p>

 

然而两者还是有区别的,序扫描是每ơ都要扫描,而创建烦引的q程仅仅需要一ơ,以后便是一x逸的了,每次搜烦Q创建烦引的q程不必l过Q仅仅搜索创建好的烦引就可以了?/p>

 

q也是全文搜索相对于序扫描的优势之一Q一ơ烦引,多次使用?/strong>

 

 

二?/span> 如何创徏索引Q?Indexing)

 

全文索的索引创徏q程一般有以下几步Q?/p>

 

1、一些要索引的原始文?Document)

 

Z方便说明索引创徏q程Q这里特意用两个文gZQ?/p>

文g一QStudents should be allowed to go out with their friends, but not allowed to drink beer.

文g二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

 

2、将原始文档传给分词lg(Tokenizer)

 

分词lg(Tokenizer)会做以下几g事情( 此过E称为Tokenize) Q?/strong>

1. 文档分成一个一个单独的单词?/strong>

2. 去除标点W号?/strong>

3. 去除停用?Stop word) ?/strong>

 

所?strong>停用?Stop word) 是一U语a中最普通的一些单词,׃没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建烦引时Q这U词会被L而减烦引的大小?/p>

p中挺?Stop word)如:“the”,“a”Q?#8220;this”{?/p>

对于每一U语a的分词组?Tokenizer)Q都有一个停?stop word)集合?/p>

 

l过分词(Tokenizer) 后得到的l果UCؓ词元(Token) ?/strong>

 

在我们的例子中,便得C下词?Token)Q?/p>

“Students”Q?#8220;allowed”Q?#8220;go”Q?#8220;their”Q?#8220;friends”Q?#8220;allowed”Q?#8220;drink”Q?#8220;beer”Q?#8220;My”Q?#8220;friend”Q?#8220;Jerry”Q?#8220;went”Q?#8220;school”Q?#8220;see”Q?#8220;his”Q?#8220;students”Q?#8220;found”Q?#8220;them”Q?#8220;drunk”Q?#8220;allowed”?/p>

 

3、将得到的词?Token)传给语言处理lg(Linguistic Processor)

 

语言处理lg(linguistic processor)主要是对得到的词?Token)做一些同语言相关的处理?/p>

对于pQ语a处理lg(Linguistic Processor) 一般做以下几点Q?/strong>

1. 变ؓ写(Lowercase) ?/strong>

2. 单词羃减ؓ词根形式Q如“cars ”?#8220;car ”{。这U操作称为:stemming ?/strong>

3. 单词{变ؓ词根形式Q如“drove ”?#8220;drive ”{。这U操作称为:lemmatization ?/strong>

 

Stemming ?lemmatization的异同:

  • 相同之处QStemming和lemmatization都要使词汇成根Ş式?
  • 两者的方式不同Q?
    • Stemming采用的是“~减”的方式:“cars”?#8220;car”Q?#8220;driving”?#8220;drive”?
    • Lemmatization采用的是“转变”的方式:“drove”?#8220;drive”Q?#8220;driving”?#8220;drive”?
  • 两者的法不同Q?
    • Stemming主要是采取某U固定的法来做q种~减Q如去除“s”Q去?#8220;ing”?#8220;e”Q将“ational”变ؓ“ate”Q将“tional”变ؓ“tion”?
    • Lemmatization主要是采用保存某U字典的方式做这U{变。比如字怸?#8220;driving”?#8220;drive”Q?#8220;drove”?#8220;drive”Q?#8220;am, is, are”?#8220;be”的映,做{变时Q只要查字典可以了?
  • Stemming和lemmatization不是互斥关系Q是有交集的Q有的词利用q两U方式都能达到相同的转换?

语言处理lg(linguistic processor)的结果称(Term) ?/strong>

在我们的例子中,l过语言处理Q得到的?Term)如下Q?/p>

“student”Q?#8220;allow”Q?#8220;go”Q?#8220;their”Q?#8220;friend”Q?#8220;allow”Q?#8220;drink”Q?#8220;beer”Q?#8220;my”Q?#8220;friend”Q?#8220;jerry”Q?#8220;go”Q?#8220;school”Q?#8220;see”Q?#8220;his”Q?#8220;student”Q?#8220;find”Q?#8220;them”Q?#8220;drink”Q?#8220;allow”?/p>

也正是因为有语言处理的步骤,才能使搜索droveQ而drive也能被搜索出来?/p>


4、将得到的词(Term)传给索引lg(Indexer)

 

索引lg主要是ؓ了得C面这个图Q?img alt="" src="http://hxraid.javaeye.com/upload/picture/pic/56003/7ca0f9b1-e82a-35c1-a97e-e40c2d4a70c9.jpg" />

 

在此表中Q有几个定义Q?/p>

  • Document Frequency x档频ơ,表示d有多文件包含此?Term)?
  • Frequency 卌频率Q表C此文g中包含了几个此词(Term)?

所以对?Term) “allow”来讲Qd有两文档包含此?Term)Q从而词(Term)后面的文档链表d有两,W一表C包?#8220;allow”的第一文档,?1h档,此文档中Q?#8220;allow”出现?ơ,W二表C包?#8220;allow”的第二个文档Q是2h档,此文档中Q?#8220;allow”出现?ơ?/p>

 

到此为止Q烦引已l创建好了,我们可以通过它很快的扑ֈ我们惌的文档?/p>

 

而且在此q程中,我们惊喜地发玎ͼ搜烦“drive”Q?#8220;driving”Q?#8220;drove”Q?#8220;driven”也能够被搜到。因为在我们的烦引中Q?#8220;driving”Q?#8220;drove”Q?#8220;driven”都会l过语言处理而变?#8220;drive”Q在搜烦Ӟ如果您输?#8220;driving”Q输入的查询语句同样l过我们q里的一C步,从而变为查?#8220;drive”Q从而可以搜索到惌的文档?/p>

 

三?/span> 如何对烦引进行搜索?(Search)

 

到这里似乎我们可以宣?#8220;我们扑ֈ惌的文档了”?/p>

 

然而事情ƈ没有l束Q找C仅仅是全文检索的一个方面。不是吗Q如果仅仅只有一个或十个文档包含我们查询的字W串Q我们的找C。然而如果结果有一千个Q甚x千上万个呢?那个又是您最惌的文件呢Q?/p>

 

打开Google吧,比如说您惛_微Y找䆾工作Q于是您输入“Microsoft job”Q您却发现d?2600000个结果返回。好大的数字呀Q突然发现找不到是一个问题,扑ֈ的太多也是一个问题。在如此多的l果中,如何最相关的放在最前面呢?

 

当然Google做的很不错,您一下就扑ֈ了jobs at Microsoft。想象一下,如果前几个全部是“Microsoft does a good job at software industry…”是多么可怕的事情呀?/p>

 

如何像Google一P在成千上万的搜烦l果中,扑ֈ和查询语句最相关的呢Q?/span>

如何判断搜烦出的文档和查询语句的相关性呢Q?/span>

 

q要回到我们W三个问题:如何对烦引进行搜索?

搜烦主要分ؓ以下几步Q?/p>

 

1、用于输入查询语?/span>

 

查询语句同我们普通的语言一P也是有一定语法的?/p>

不同的查询语句有不同的语法,如SQL语句有一定的语法?/p>

查询语句的语法根据全文检索系l的实现而不同。最基本的有比如QAND, OR, NOT{?/p>

举个例子Q用戯入语句:lucene AND learned NOT hadoop?/p>

说明用户x一个包含lucene和learned然而不包括hadoop的文档?/p>

 

2、对查询语句q行词法分析Q语法分析及语言处理

 

׃查询语句有语法,因而也要进行语法分析,语法分析及语a处理?/p>

 

词法分析主要用来识别单词和关键字?/strong>

如上qC子中Q经q词法分析,得到单词有luceneQlearnedQhadoop, 关键字有AND, NOT?/p>

如果在词法分析中发现不合法的关键字,则会出现错误。如lucene AMD learnedQ其中由于AND拼错Q导致AMD作ؓ一个普通的单词参与查询?/p>

 

语法分析主要是根据查询语句的语法规则来Ş成一语法树?/strong>

如果发现查询语句不满法规则,则会报错。如lucene NOT AND learnedQ则会出错?/p>

 

语言处理同烦引过E中的语a处理几乎相同?/strong>

如learned变成learn{?/p>

 

3、搜索烦引,得到W合语法树的文档

 

此步骤有分几步Q?/p>

首先Q在反向索引表中Q分别找出包含luceneQlearnQhadoop的文档链表?strong>

其次Q对包含luceneQlearn的链表进行合q操作,得到既包含lucene又包含learn的文档链表?strong>

然后Q将此链表与hadoop的文档链表进行差操作Q去除包含hadoop的文档,从而得到既包含lucene又包含learn而且不包含hadoop的文档链表?strong>

最后,此文档链表就是我们要扄文档?

 

4、根据得到的文档和查询语句的相关性,对结果进行排序?/span>

虽然在上一步,我们得到了想要的文档Q然而对于查询结果应该按照与查询语句的相x进行排序,相兌越靠前?/p>

 

如何计算文档和查询语句的相关性呢Q?/span>

 

不如我们把查询语句看作一片短的文档Q对文档与文档之间的相关?relevance)q行打分(scoring)Q分数高的相x好Q就应该排在前面?/p>


那么又怎么Ҏ档之间的关系q行打分呢?

 

首先Q一个文档有很多?Term)l成 Q?/span> 如search, lucene, full-text, this, a, what{?/p>

其次对于文档之间的关p,不同的Term重要性不?/strong> Q?/span> 比如对于本篇文档Qsearch, Lucene, full-textq寚w要一些,this, a , what可能相对不重要一些。所以如果两文档都包含search, LuceneQfulltextQ这两篇文档的相x好一些,然而就一文档包含this, a, whatQ另一文档不包含this, a, whatQ也不能影响两篇文档的相x?/p>

因而判断文档之间的关系Q首先找出哪些词(Term)Ҏ档之间的关系最重要Q如search, Lucene, fulltext。然后判断这些词(Term)之间的关pR?/p>

扑և?Term) Ҏ档的重要性的q程UCؓ计算词的权重(Term weight) 的过E?/strong>

计算词的权重(term weight)有两个参敎ͼW一个是?Term)Q第二个是文?Document)?/p>

词的权重(Term weight)表示此词(Term)在此文档中的重要E度Q越重要的词(Term)有越大的权重(Term weight)Q因而在计算文档之间的相x中发挥更大的作用?/p>

判断?Term) 之间的关pM而得到文档相x的q程应用一U叫做向量空间模型的法(Vector Space Model) ?/strong>

下面仔细分析一下这两个q程Q?/p>

1. 计算权重(Term weight)的过E?/strong>

影响一个词(Term)在一文档中的重要性主要有两个因素Q?/p>

  • Term Frequency (tf)Q即此Term在此文档中出C多少ơ。tf 大说明重要?
  • Document Frequency (df)Q即有多文档包含次Term。df 大说明不重要 ?/span>

Ҏ理解吗??Term)在文档中出现的次数越多,说明此词(Term)对该文档重要,?#8220;搜烦”q个词,在本文档中出现的ơ数很多Q说明本文档主要是讲这斚w的事的。然而在一英语文档中Qthis出现的次数更多,p明越重要吗?不是的,q是q二个因素q行调整Q第二个因素说明Q有多的文档包含此?Term), 说明此词(Term)太普通,不以区分这些文档,因而重要性越低?/p>

 

q也如我们程序员所学的技术,对于E序员本w来_q项技术掌握越p好(掌握深说明花时间看的越多,tf大Q,扑ַ作时有竞争力。然而对于所有程序员来说Q这Ҏ术懂得的越好(懂得的hdf)Q找工作有竞争力。h的h值在于不可替代性就是这个道理?/p>

 

道理明白了,我们来看看公式:

 

q仅仅只term weight计算公式的简单典型实现。实现全文检索系l的Z有自q实现QLucene׃此稍有不同?/p>

2. 判断Term之间的关pM而得到文档相x的q程Q也卛_量空间模型的法(VSM)?/strong>

我们把文档看作一pd?Term)Q每一个词(Term)都有一个权?Term weight)Q不同的?Term)Ҏ自己在文档中的权重来影响文档相关性的打分计算?/p>

于是我们把所有此文档中词(term)的权?term weight) 看作一个向量?/p>

Document = {term1, term2, …… ,term N}

Document Vector = {weight1, weight2, …… ,weight N}

同样我们把查询语句看作一个简单的文档Q也用向量来表示?/p>

Query = {term1, term 2, …… , term N}

Query Vector = {weight1, weight2, …… , weight N}

我们把所有搜索出的文档向量及查询向量攑ֈ一个Nl空间中Q每个词(term)是一l?/p>

 

我们认ؓ两个向量之间的夹角越,相关性越大?/p>

所以我们计夹角的余ug为相x的打分Q夹角越,余uD大,打分高Q相x越大?/p>

有h可能会问Q查询语句一般是很短的,包含的词(Term)是很的Q因而查询向量的l数很小Q而文档很长,包含?Term)很多Q文档向量维数很大。你的图中两者维数怎么都是N呢?

在这里,既然要放到相同的向量I间Q自然维数是相同的,不同Ӟ取二者的qQ如果不含某个词(Term)Ӟ则权?Term Weight)??/p>

相关性打分公式如下:

 

Ҏq个公式p出文档与查询之间的怼E度了?/p>

 

四、ȝ

对上q烦引创建和搜烦q程所一个ȝQ如图:

此图参照http://www.lucene.com.cn/about.htm 中文章《开放源代码的全文检索引擎Lucene?/p>

 

1. 索引q程Q?/strong>

 

a 有一pd被烦引文?/strong>

b) 被烦引文件经q语法分析和语言处理形成一pd?Term) ?/strong>

c) l过索引创徏形成词典和反向烦引表?/strong>

d) 通过索引存储烦引写入硬盘?/strong>

 

2. 搜烦q程Q?/strong>

 

a) 用户输入查询语句?/strong>

b) Ҏ询语句经q语法分析和语言分析得到一pd?Term) ?/strong>

c) 通过语法分析得到一个查询树?/strong>

d) 通过索引存储烦引读入到内存?/strong>

e) 利用查询树搜索烦引,从而得到每个词(Term) 的文档链表,Ҏ档链表进行交Q差Qƈ得到l果文档?/strong>

f) 搜索到的结果文档对查询的相x进行排序?/strong>

g) q回查询l果l用戗?/strong>



]]>
用户态非抢占式线E库实现 (?http://www.tkk7.com/tinysun/archive/2010/05/30/322278.html何克?/dc:creator>何克?/author>Sun, 30 May 2010 06:49:00 GMThttp://www.tkk7.com/tinysun/archive/2010/05/30/322278.htmlhttp://www.tkk7.com/tinysun/comments/322278.htmlhttp://www.tkk7.com/tinysun/archive/2010/05/30/322278.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/322278.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/322278.html阅读全文

]]>
用户态多U程实现的基本原?/title><link>http://www.tkk7.com/tinysun/archive/2010/05/30/322275.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Sun, 30 May 2010 06:33:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2010/05/30/322275.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/322275.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2010/05/30/322275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/322275.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/322275.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cde9d1">本文参考了用户态非抢占式线E库实现 一文以及GNU Pth 。前者是一U用h线E库的简单实玎ͼ属于一个很好的demoQ后者就是大家熟知的Pthread的用h实玎ͼ比较完善?/font></p> <p><font style="background-color: #cde9d1">Keywords: User-Space MultiThreading, Pth</font></p> <p><font style="background-color: #cde9d1">所谓多U程Q简单讲是能够让几个不同的代码片段轮流执行。内核实现多U程的方法比较直观,在每ơ时钟中断到来时或者用戯用syscall陷入内核时进行上下文切换卛_。用h切换线E要解决两个问题Q?/font></p> <p><font style="background-color: #cde9d1">1、时机,即何时切换线E?</font></p> <p><font style="background-color: #cde9d1">2、方法,x样切换上下文?</font></p> <p><font style="background-color: #cde9d1">Z军_切换时机Q需要确定所设计的线E库是可剥夺(preemptive)的还是不可剥?non-preemptive)的。一般,用户态线E库都选择使用不可剥夺的设计方案,q么做的好处是将控制权交l用P而用h了解何时需要放弃执行权。这么做减少了系l切换次敎ͼ实现了最高的CPU利用率,非常适合用于U学计算环境。但是,另一斚wq么做也存在~点Q其它线E的响应速度变慢Q他们必ȝ到当前CPU攑ּ执行权后才能被执行。能不能用LE设计成可剥夺的呢?q应该也是可行的。每个用LE运行一D|间后会被q暂停执行,被动地将控制权交回给调度器。怎样才能“被迫暂停执行”Q这是方法问题,下面p讲到?/font></p> <p><font style="background-color: #cde9d1">对于不可剥夺方式Q需要用L写程序的时候主动调用诸如thread_yeild(), thread_wai()之类的函敎ͼq些函数会将当前用户U程的执行上下文保存hQ然后让调度器选择一个新的用LE投入执行。底层操作系l提供了一些列的机制支持上下文的获得和切换Q如setjmp,longjmp,getcontext,swapcontext{。用h非抢占式线E库实现 一文用了前面两个函数QGNU Pth 使用了后面两个函数。可剥夺方式的实现需要更多的操作pȝ支持Q如可以利用alarm函数周期性地产生用户态中断,每次中断到来的时候线E库q行U程切换?/font></p> <p><font style="background-color: #cde9d1">单纯的用h线E库一般都是基于一个单U程q程实现的,一旦用LE阻塞,q个q程pdQ进而导致整个用h线E组得不到CPU。基于单q程实现的用h线E库在SMP/多CPU环境下性能很差Q多出来的核无法被线E库利用Q这跟当前的微处理器架构发展势十分不符。ؓ了解册个问题,可以考虑使用一U؜合结构:在少量内核线E的基础上实现大量的用户U程?/font></p> <p><font style="background-color: #cde9d1"> </font></p> <p><font style="background-color: #cde9d1">最后思考一个问题:Z么用h线E库比内核态线E库h更高的性能呢?其实用户态线E库同样M开q入内核态这一q程Q以getcontext,swapcontex实现方式ZQgetcontext要进Zơ内核,swapcontex又要q出一ơ内核,而内核线E切换则只需要一ơ时钟中断,只进出内怸ơ即可。这么说来,用户态线E库的性能应该劣于内核态线E库。但是,注意到每ơ时钟中断所做的工作q远不止上下文切换这么简单,q应该是用户态线E库更优的原因吧。基于这个分析,如果应用需要创建的U程数ƈ不多Q二者应该性能相当。但是,一旦线E数巨大且切换频J,用户态线E库的优势就能体现出来了?/font></p> <p><font style="background-color: #cde9d1"></font> </p> <p><font style="background-color: #cde9d1">本文来自CSDN博客Q{载请标明出处Qhttp://blog.csdn.net/maray/archive/2009/12/05/4946245.aspx</font></p> <img src ="http://www.tkk7.com/tinysun/aggbug/322275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2010-05-30 14:33 <a href="http://www.tkk7.com/tinysun/archive/2010/05/30/322275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>U程控制Q-U有数据http://www.tkk7.com/tinysun/archive/2010/05/29/322210.html何克?/dc:creator>何克?/author>Sat, 29 May 2010 07:16:00 GMThttp://www.tkk7.com/tinysun/archive/2010/05/29/322210.htmlhttp://www.tkk7.com/tinysun/comments/322210.htmlhttp://www.tkk7.com/tinysun/archive/2010/05/29/322210.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/322210.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/322210.html     U程U有数据采用了一U被UCؓ一键多值的技术,即一个键对应多个数倹{访问数据时都是通过键值来讉KQ好像是对一个变量进行访问,其实是在讉K不同的数据。用线E私有数据时Q首先要为每个线E数据创Z个相兌的键。在各个U程内部Q都使用q个公用的键来指代线E数据,但是在不同的U程中,q个键代表的数据是不同的。操作线E私有数据的函数主要?个:pthread_key_createQ创Z个键Q,pthread_setspecificQؓ一个键讄U程U有数据Q,pthread_getspecificQ从一个键dU程U有数据Q,pthread_key_deleteQ删除一个键Q。这几个函数的声明如下:
#include <pthread.h>
int pthread_key_create(pthread_key_t *key,void (*destr_function)(void *));
int pthread_setspecific(pthread_key_t key,const void *pointer));
void *pthread_getspecific(pthread_key_t key);
int pthread_key_delete(pthread_key_t key);
    pthread_key_createQ从Linux的TSD池中分配一,其Dlkey供以后访问用,它的W一个参数key为指向键值的指针Q第二个参数Z个函数指针,如果指针不ؓI,则在U程退出时以key所兌的数据ؓ参数调用destr_function()Q释攑ֈ配的~冲区?br />     key一旦被创徏Q所有线E都可以讉K它,但各U程可以Ҏ自己的需要往key中填入不同的|q就相当于提供了一个同名而不同值的全局变量Q一键多倹{一键多值靠的是一个关键数据结构数l,即TSD池其l构如下Q?br /> static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] ={{0,NULL}};
    创徏一个TSDq当于结构数l中的某一设|ؓ“in_use”Qƈ其索引q回l*keyQ然后设|destructor函数destr_function?br />     pthread_setspecificQ该函数pointer的|不是内容Q与key相关联。用pthread_setspecificZ个键指定新的U程数据ӞU程必须先释攑֎有的U程数据用以回收I间?br />     pthread_getspecificQ通过该函数得Ckey相关联的数据?br />     pthread_key_deleteQ该函数用来删除一个键Q键所占用的内存将被释放。需要注意的是,键占用的内存被释放,与该键关联的U程数据所占用的内存ƈ不被释放。因此,U程数据的释攑ֿd释放键之前完成?br />     ?Q?实现如何创建和使用U程的私有数据,具体代码如下所C?br />     ?Q?
#include <stdio.h>
#include <string.h>
#include <pthread.h>

pthread_key_t key;

void * thread2(void *arg)
{
int tsd = 5;
printf("thread %d is running\n",pthread_self());
pthread_setspecific(key,(void *)tsd);
printf("thread %d returns %d\n",pthread_self(),pthread_getspecific(key));
}

void * thread1(void *arg)
{
int tsd = 0;
pthread_t thid2;

printf("thread %d is running\n",pthread_self());
pthread_setspecific(key,(void *)tsd);
pthread_create(&thid2,NULL,thread2,NULL);
sleep(2);
printf("thread %d return %d\n",pthread_self(),pthread_getspecific(key));
}

int main(void)
{
pthread_t thid1;
printf("main thread begins running\n");
pthread_key_create(&key,NULL);
pthread_create(&thid1,NULL,thread1,NULL);
sleep(5);
pthread_key_delete(key);
printf("main thread exit\n");
return 0;
}
    ~译q执行,l果如下Q?br /> $ gcc -o 8-4 8-4.c -g -l pthread
$ ./8-4
main thread begins running
thread -1209746544 is running
thread -1218139248 is running
thread -1218139248 returns 5
thread -1209746544 return 0
main thread exit
    E序说明Q程序中Q主U程创徏了线Ethread1Q线Ethread1创徏了线Ethread2。两个线E分别将tsd作ؓU程U有数据。从E序q行l果可以看出Q两个线Etsd的修改互不干扎ͼ可以看出thread2先于thread1l束Q线E在创徏thread2后,睡眠3s{待thread2执行完毕。主U程睡眠5s{待thread1l束。可以看出thread2对tsd的修改ƈ没媄响到thread1的tsd的取倹{?br />

]]>
վ֩ģ壺 þþþóƬѹۿѿ| ۺŷ㻨 | պaƵ| Ʒһ߹ۿ | ޾Ʒ㶮վ| ĻAVÿ| һ߹ۿѸ߹ۿ | ƷŮٸAVѹۿ| ˳www߲| ŮɫëƬѿ| AVɫ߹ۿ| ȫaëƬ| һëƬ**ѿԿ20| Ʒһ߹ۿ| һƬѿ| ޾Ʒ| Ļݺ| ۺͼƬС˵| žƷƵվ| ؼëƬ69ѹۿ| ޾Ʒ΢ľƷ| þþѾƷre6| Ļ| av˾Ʒ߲ | ޷| Av߹ۿɫ| ĻѸƵ| Ƶ| ŷ޹ۺ| Ƶ97| ŮƵۿ| վ߹ۿ| ˳߹ۿվƷձ| þþþþһ| ҹ߲| þӰԺһ| ԻȫƵ߹ۿ| һһƬƵ| Ƶ| ޾Ʒa vС˵| ƷѾƷ߹ۿ|