??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人精品白浆久久69 ,午夜不卡888久久,成人精品一区二区久久久http://www.shnenglu.com/ivy-jie/category/10521.htmlprogress ...zh-cnThu, 17 Sep 2009 09:04:13 GMTThu, 17 Sep 2009 09:04:13 GMT60rpm安装包相兛_?/title><link>http://www.shnenglu.com/ivy-jie/articles/94173.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Sun, 23 Aug 2009 08:19:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/94173.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/94173.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/94173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/94173.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/94173.html</trackback:ping><description><![CDATA[<strong>使用rpm命o查询软g包:</strong> <p>  1、查询系l中安装的所有RPM?/p> <p>  $ rpm -qa</p> <p>  查询当前linuxpȝ中已l安装的软g包?/p> <p>  例:$ rpm -qa | grep -i x11 | head -3 察看pȝ中包含x11字符串的?行Y件包?/p> <p>  2、查询Y件包是否安装</p> <p>  $ rpm –q rpm包名U?察看pȝ中指定Y件包是否安?/p> <p>  ? $ rpm -q bash 察看pȝ中bash软g包是否安装?/p> <p>  "rpm -q"命o中指定的软g包名U需要准的拼写Q该命o不会在Y件包的名UCq行局部匹配的查询?/p> <p>  3、查询已安装软g包详l信?/p> <p>  $ rpm –qi RPM包名U?查询linuxpȝ中指定名UY件包的详l信息?/p> <p>  例:$ rpm -qi bash 察看bash软g包的详细信息?/p> <p>  "rpm -qi"命o的执行结果中包含较详l的信息Q包括:软g名称Q版本信息,包大,描述Q等?/p> <p>  4、查询已安装软g包中的文件列?/p> <p>  $ rpm –ql RPM包名U?查询已安装Y件包在当前系l中安装了哪些文件?/p> <p>  例:$ rpm -ql bash | head -3 查看bash软g在系l中已安装文件的?行文件列表?/p> <p>  $ rpm -ql bash | grep bin 用过滤方式察看bash中包含bin字符串的文g列表?/p> <p>  5、查询系l中文g所属的软g?/p> <p>  $ rpm –qf 文g名称 查询linuxpȝ中指定文件所属的软g包?/p> <p>  例:$ rpm -qf /bin/bash 察看bash文g所属的软g包?/p> <p>  bash-3.0-19.2 昄l果?/p> <p>  6、查询RPM安装包文件中的信?</p> <p>  $ rpm –qpi RPM包文件名 察看RPM包未安装前的详细信息?/p> <p>  $ rpm –qpl RPM包文件名 察看RPM包未安装前的文g列表?/p> <p>  "rpm -qpi和rpm -qpl q两条命令可作ؓ在安装Y件包之前对其的了解?/p> <p>  7、rpm命o查询实例</p> <p>  $ which mount 获得mount命o的可执行文g路径?/p> <p>  $ rpm –qf /bin/mount 查询/bin/mount所属的软g包?/p> <p>  $ rpm –qi util-linux 查询/bin/mount所属Y件包的详l信息?/p> <p>  $ rpm –qf util-linux | grep mount 查询/bin/mount所属Y件包中包括mount相关所有文件?/p> <p>  <strong taggedby="hylanda">使用rpm命o安装软g包:</strong></p> <p>  1、rpm软g包地基本安装</p> <p>  $ rpm –i rpm安装包文件名 安装该Y件包中的文g到当前系l,安装q程不提CZQ何信息?/p> <p>  2、在安装软g包的同时昄详细信息</p> <p>  $ rpm –ivh rpm安装包文?安装该Y件包中的文g到当前系l,安装q程会以癑ֈ比的形式昄安装的进度和一些其他信息?/p> <p>  3、RPM软g包安装的依赖关系</p> <p>  强制安装Q? rpm --force –i rpm包文件名</p> <p>  注:要先满软g包的依赖关系后再q行软g包的安装Q用强制安装命令安装不能保证Y件安装到pȝ后一定能</p> <p>  正常q行Q因此徏议慎重用?/p> <p>  <strong taggedby="hylanda">使用rpm命o卸蝲软g包:</strong></p> <p>  1、RPM软g包的卸蝲</p> <p>  $ rpm -e 软g包名U?/p> <p>  软g包的卸蝲Q在卸蝲时不昄M信息?/p> <p>  注:RPM软g包的卸蝲同样存在依赖关系Q只有在没有依赖关系存在时才能对其进行卸载?/p> <p>  2、rpm软g包卸载的依赖关系</p> <p>  在用RPM命oq行卸蝲ӞRPM命o会分析要卸蝲的Y件包的依赖关p,当存在依赖关pL会自动停止,q显?</p> <p>  哪个软g造成的卸载失败。根据RPM提示的错误信息,定先卸载的软g包,再卸载被依赖的Y件包?/p> <p>  <strong taggedby="hylanda">使用rpm命o升软g包:</strong></p> <p>  $ rpm - U rpm安装包文件名</p> <p>  注:"rpm -u"命o中用的升软g包文件最好用RED HAT公司针对当前的linux版本官方推出的升U文Ӟ不要使用W三Ҏ供的升包?/p> <p><!--分页--></p> <p>  <strong taggedby="hylanda">~译应用E序前的准备工作Q?/strong></p> <p>  1、确认系l中已经安装了编译环?/p> <p>  $ rpm -qa | grep gcc</p> <p>  定当前pȝ中安装了gcc~译器环境?/p> <p>  2、下载prozillaE序的源代码安装包文?/p> <p>  3、释攑ַ下蝲的源代码软g包文?/p> <p>  $ tar jxf prozilla-2.0.4.tar.bz2</p> <p>  释放以下载的源代码Y件包文g到当前目录。解压后的文件名Qprozilla-2.0.4</p> <p>  扩展Qtar的xzvf参数用于释放以tar.gz格式的压~包?/p> <p>  4、进入源代码目录</p> <p>  $ cd prozilla-2.0.4 q入目录?/p> <p>  $ pwd 昄当前目录路径?/p> <p>  /home/teacher/download/prozilla-2.0.4 昄l果?/p> <p>  ~译软g安装的\径:</p> <p>  $ ./configure --prefix=/home/teacher/proz </p> <p>  在prozillaE序的配|中Q?--prdfix"选项可以指定应用E序~译后的安装路径Q如果不使用"--prefix"</p> <p>  选项指定安装路径QconfigureE序配|prozilla的默认安装\径ؓ"/usr/local/bin"目录?/p> <p>  5、程序编译过E?/p> <p>  $ make</p> <p>  使用make命oq行E序的二q制~译?/p> <p>  6、程序安装过E?/p> <p>  $ make install</p> <p>  "make install"命o按照configuer命o?--prefix"选项中设定的安装路径已~译完成的应用程序安装到目标目录?/p> <p>  7、验证编译安装的E序</p> <p>  $ ls /home/teacher/proz </p> <p>  察看proz文g夹中的文件?/p> <p>  bin include lib man share</p> <p>  ~译前的配置</p> <p>  $ ./configure - - help </p> <p>  <strong taggedby="hylanda">~译与安装:</strong></p> <p>  1、程序编译过E?/p> <p>  $ make </p> <p>  2、程序安装过E?/p> <p>  $ make install</p> <p>  3、验证编译安装的E序</p> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/94173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-08-23 16:19 <a href="http://www.shnenglu.com/ivy-jie/articles/94173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux命o1http://www.shnenglu.com/ivy-jie/articles/89567.htmlivy-jieivy-jieWed, 08 Jul 2009 13:41:00 GMThttp://www.shnenglu.com/ivy-jie/articles/89567.htmlhttp://www.shnenglu.com/ivy-jie/comments/89567.htmlhttp://www.shnenglu.com/ivy-jie/articles/89567.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/89567.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/89567.htmlhttp://itbbs-arch.pconline.com.cn/topic.jsp?tid=2746314 

1、安装以rpm方式提供的Y?br>Rpm(the red hat package manager)是一个开攄软g包管理系l?br>功能Q可以安装和卸蝲RPM包的软g
#rpm –ivh *.rpm 安装RPM包;
#rpm –ivh –force *.rpm 在原先安装的基础上再安装一ơ;
#rpm –Uvh *.rpm 升rpm?br>#rpm –qa 查找列出pȝ中所有安装的rpm?br>#rpm –q sendmailQ查看sendmail包的情况
#rpm –ql sendmail:查看sendmail安装的位|?br>#rpm –e *.rpm 卸蝲rpm?br>#rpm - qlp name.rpm 查看name.rpm有哪些文?br>#rpm - qf name.rpm 查看已经装好的文件属于哪个rpm?br>#rpm2cpio filename.rpm 使用“rpm2cpio”来从RPM文档中提取文?br>

2. 安装以源代码方式提供的Y?br>Q?Q、解包解压:
#tar –xzvf *.tar.gz 解包解压后会在当前目录下建立一个子目录,如xxxx
Q?Q?cd xxxx
Q?Q?./configure
Q?Q?make
Q?Q?make install 

3.Find使用范例
find . -name ls.txt
find . -name ls.txt –print
find / -name ‘c??’ –print
find / -name ‘f*’ –print
find . -name ‘f*’ –exec ls –l { } \; 
find . -name f\* –ok rm { } \; Q交互式提问Q?br>find . -perm 644 –mtime 4 
find . -name ‘c??’ –o -name ‘d??’
4. grep
功能Q在文g中搜d配的行ƈq行输出
语法Qgrep [参数]<要找的字?gt;<原文?gt;
-num:输出匚w行前后各num行的内容
-A num:输出匚w行后num行的内容
-B num:输出匚w行前num行的内容
-iQ忽略大写的区?br>-v:只显C出那些不包括某字串的行和文Ӟ和默认的相反
5. mkdir
功能Q创Z个目录(cMMSDOS下的md命oQ?br>语法Qmkdir [选项] dir-name 
- m Ҏ建目录设|存取权限。也可以用chmod命o讄?br>- p 可以是一个\径名U。此时若路径中的某些目录不存在Q?nbsp;加上此选项后, pȝ自动徏立好那些不存在的目录,即一ơ可以徏立多个目录?br>#mkdir –m a=rwx test
#mkdir –m u=rwx,g=rx,o=rx test1
#mkdir –m 755 test2
#mkdir –p test3/test4(test3和test4均ؓ新目录)

6、rmdir
功能Q删除空目录?br>语法Qrmdir [选项] dir-name 
- p 递归删除目录dirnameQ当子目录删除后其父目录为空Ӟ也一同被删除?br>7、file
功能Q查看文件类?br>语法Qfile 文g?br>
8、cat
功能Q查看文本文件的内容
语法Qcat 文g?br>9、more
功能Q分屏显C文本文件的内容?br>10、less
功能Q显C文本文件的内容Q可使用pageup和pagedown上翻下页?br>
11、head
功能Q查看文件的开头部分内?br>语法Qhead [行数] 文g?br>用法Q?head test.txt:昄?0行内?br>#head -20 test.txt 昄?0行内宏V?br>12、tail
功能Q查看文件的l尾部分内容?br>语法Qtail [行数] 文g?br>默认的行Cؓ10行?br>
13、sort
功能Q对文本文g中的各行q行排序
用法Qsort 文g?br>例:#sort 123.txt >456.txt ?23.txt排序后重定向?56.txt文g中?br>14、uniq
功能Q将重复行从输出文g中删除,只留下每条记录的唯一h 
语法Q?nbsp;uniq 文g?br>#uniq 456.txt文g中的重复行删除后输出

 

ivy-jie 2009-07-08 21:41 发表评论
]]>
vi命o http://www.shnenglu.com/ivy-jie/articles/88479.htmlivy-jieivy-jieThu, 25 Jun 2009 00:27:00 GMThttp://www.shnenglu.com/ivy-jie/articles/88479.htmlhttp://www.shnenglu.com/ivy-jie/comments/88479.htmlhttp://www.shnenglu.com/ivy-jie/articles/88479.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/88479.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/88479.html    三种模式:
  CommandQ命令)模式Q用于输入命令;
 InsertQ插入)模式Q用于插入文本;
 VisualQ可视)模式Q用于视化的的高亮ƈ选定正文

   默认模式是Command,当我们按ESC键后Q接着再输?hQ进入command模式
   :wq 强制性写入文件ƈ退出。即使文件没有被修改也强制写入,q更新文件的修改旉?br>   :x 写入文gq出。仅当文件被修改时才写入Qƈ更新文g修改旉Q否则不会更新文件修Ҏ间?br>   q两者一般情况下没什么不一P但是在编E方面,对编辑源文g可能会生重要媄响。因为文件即使没有修改,":wq"强制更新文g的修Ҏ_q样会让make~译整个目时以为文件被修改q了Q然后就得重新编译链接生成可执行文g。这可能会生让解的后果Q当然也产生了不必要的系l资源花销?span style="COLOR: red">?x
   :w  保存Q?br> :w  filename 另存为filenameQ?br> :wq! 保存退出;
 :wq! filename 注:以filename为文件名保存后退出;
 :q! 不保存退出;
2



ivy-jie 2009-06-25 08:27 发表评论
]]>
Linux下C多线E编E?/title><link>http://www.shnenglu.com/ivy-jie/articles/87518.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Fri, 12 Jun 2009 11:47:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/87518.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/87518.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/87518.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/87518.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/87518.html</trackback:ping><description><![CDATA[  Linuxpȝ下的多线E遵循POSIXU程接口Q称为pthread。编写Linux下的多线E程序,需要用头文gpthread.hQ连接时需要用库libpthread.a。顺便说一下,Linux下pthread的实现是通过pȝ调用cloneQ)来实现的。cloneQ)是Linux所Ҏ的系l调用,它的使用方式cMforkQ关于cloneQ)的详l情况,有兴的读者可以去查看有关文档说明。下面我们展CZ个最单的多线E程序example1.c?<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>/* example.c*/<br>#include <stdio.h><br>#include <pthread.h><br>void thread(void)<br>{<br> int i;<br> for(i=0;i<3;i++)<br>  printf("This is a pthread.n");<br>}<br><br>int main(void)<br>{<br> pthread_t id;<br> int i,ret;<br> ret=pthread_create(&id,NULL,(void *) thread,NULL);<br> if(ret!=0){<br>  printf ("Create pthread error!n");<br>  exit (1);<br> }<br> for(i=0;i<3;i++)<br>  printf("This is the main process.n");<br> pthread_join(id,NULL);<br> return (0);<br>}</td> </tr> </tbody> </table> <br>  我们~译此程序:<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>gcc example1.c -lpthread -o example1</td> </tr> </tbody> </table> <br>  q行example1Q我们得到如下结果:<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>This is the main process.<br>This is a pthread.<br>This is the main process.<br>This is the main process.<br>This is a pthread.<br>This is a pthread.</td> </tr> </tbody> </table> <br>  再次q行Q我们可能得到如下结果:<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>This is a pthread.<br>This is the main process.<br>This is a pthread.<br>This is the main process.<br>This is a pthread.<br>This is the main process.</td> </tr> </tbody> </table> <br>  前后两次l果不一Pq是两个U程争夺CPU资源的结果。上面的CZ中,我们使用C两个函数Qpthread_create和pthread_joinQƈ声明了一个pthread_t型的变量?br><br>  pthread_t在头文g/usr/include/bits/pthreadtypes.h中定义:<br><br>  typedef unsigned long int pthread_t;<br><br>  它是一个线E的标识W。函数pthread_create用来创徏一个线E,它的原型为:<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,void *(*__start_routine) (void *), void *__arg));</td> </tr> </tbody> </table> <br>  W一个参Cؓ指向U程标识W的指针Q第二个参数用来讄U程属性,W三个参数是U程q行函数的v始地址Q最后一个参数是q行函数的参数。这里,我们的函数thread不需要参敎ͼ所以最后一个参数设为空指针。第二个参数我们也设为空指针Q这样将生成默认属性的U程。对U程属性的讑֮和修Ҏ们将在下一节阐q。当创徏U程成功Ӟ函数q回0Q若不ؓ0则说明创建线E失败,常见的错误返回代码ؓEAGAIN和EINVAL。前者表C系l限制创建新的线E,例如U程数目q多了;后者表C第二个参数代表的线E属性值非法。创建线E成功后Q新创徏的线E则q行参数三和参数四确定的函数Q原来的U程则l运行下一行代码?<br><br>  函数pthread_join用来{待一个线E的l束。函数原型ؓQ?br><br>  extern int pthread_join __P ((pthread_t __th, void **__thread_return));<br><br>  W一个参Cؓ被等待的U程标识W,W二个参Cؓ一个用户定义的指针Q它可以用来存储被等待线E的q回倹{这个函数是一个线E阻塞的函数Q调用它的函数将一直等待到被等待的U程l束为止Q当函数q回Ӟ被等待线E的资源被收回。一个线E的l束有两U途径Q一U是象我们上面的例子一P函数l束了,调用它的U程也就l束了;另一U方式是通过函数pthread_exit来实现。它的函数原型ؓQ?br><br>  extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));<br><br>  唯一的参数是函数的返回代码,只要pthread_join中的W二个参数thread_return不是NULLQ这个值将被传递给thread_return。最后要说明的是Q一个线E不能被多个U程{待Q否则第一个接收到信号的线E成功返回,其余调用pthread_join的线E则q回错误代码ESRCH?br><br>  在这一节里Q我们编写了一个最单的U程Qƈ掌握了最常用的三个函数pthread_createQpthread_join和pthread_exit。下面,我们来了解线E的一些常用属性以及如何设|这些属性?br><br>  <strong>修改U程的属?/strong><br><br>  在上一节的例子里,我们用pthread_create函数创徏了一个线E,在这个线E中Q我们用了默认参数Q即该函数的第二个参数设ؓNULL。的,对大多数E序来说Q用默认属性就够了Q但我们q是有必要来了解一下线E的有关属性?br><br>  属性结构ؓpthread_attr_tQ它同样在头文g/usr/include/pthread.h中定义,喜欢q根问底的h可以自己L看。属性g能直接设|,M用相兛_数进行操作,初始化的函数为pthread_attr_initQ这个函数必dpthread_create函数之前调用。属性对象主要包括是否绑定、是否分R堆栈地址、堆栈大、优先。默认的属性ؓ非绑定、非分离、缺?M的堆栈、与父进E同L别的优先U?br><br>  关于U程的绑定,牉|到另外一个概念:轻进E(LWPQLight Weight ProcessQ。轻q程可以理解为内核线E,它位于用户层和系l层之间。系l对U程资源的分配、对U程的控制是通过轻进E来实现的,一个轻q程可以控制一个或多个U程。默认状况下Q启动多轻q程、哪些轻q程来控制哪些线E是ql来控制的,q种状况即称为非l定的。绑定状况下Q则֐思义Q即某个U程固定?l?在一个轻q程之上。被l定的线E具有较高的响应速度Q这是因为CPU旉片的调度是面向轻q程的,l定的线E可以保证在需要的时候它L一个轻q程可用。通过讄被绑定的轻进E的优先U和调度U可以得绑定的U程满诸如实时反应之类的要求?br><br>  讄U程l定状态的函数为pthread_attr_setscopeQ它有两个参敎ͼW一个是指向属性结构的指针Q第二个是绑定类型,它有两个取|PTHREAD_SCOPE_SYSTEMQ绑定的Q和PTHREAD_SCOPE_PROCESSQ非l定的)。下面的代码卛_Z一个绑定的U程?<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>#include <pthread.h><br>pthread_attr_t attr;<br>pthread_t tid;<br><br>/*初始化属性|均设为默认?/<br>pthread_attr_init(&attr);<br>pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);<br><br>pthread_create(&tid, &attr, (void *) my_function, NULL);</td> </tr> </tbody> </table> <br>  U程的分ȝ态决定一个线E以什么样的方式来l止自己。在上面的例子中Q我们采用了U程的默认属性,即ؓ非分ȝ态,q种情况下,原有的线E等待创建的U程l束。只有当pthread_joinQ)函数q回Ӟ创徏的线E才终止,才能释放自己占用的系l资源。而分ȝE不是这样子的,它没有被其他的线E所{待Q自p行结束了Q线E也q止了Q马上释攄l资源。程序员应该Ҏ自己的需要,选择适当的分ȝ态。设|线E分ȝ态的函数为pthread_attr_setdetachstateQpthread_attr_t *attr, int detachstateQ。第二个参数可选ؓPTHREAD_CREATE_DETACHEDQ分ȝE)?PTHREAD _CREATE_JOINABLEQ非分离U程Q。这里要注意的一ҎQ如果设|一个线Eؓ分离U程Q而这个线E运行又非常快,它很可能在pthread_create函数q回之前q止了Q它l止以后可能将U程号和pȝ资源UMl其他的U程使用Q这栯用pthread_create的线E就得到了错误的U程受要避免q种情况可以采取一定的同步措施Q最单的Ҏ之一是可以在被创建的U程里调用pthread_cond_timewait函数Q让q个U程{待一会儿Q留够的旉让函数pthread_createq回。设|一D늭待时_是在多线E编E里常用的方法。但是注意不要用诸如waitQ)之类的函敎ͼ它们是整个q程睡眠Qƈ不能解决U程同步的问题?br><br>  另外一个可能常用的属性是U程的优先Q它存放在结构sched_param中。用函数pthread_attr_getschedparam和函数pthread_attr_setschedparamq行存放Q一般说来,我们L先取优先U,对取得的g改后再存攑֛厅R下面即是一D늮单的例子?<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>#include <pthread.h><br>#include <sched.h><br>pthread_attr_t attr;<br>pthread_t tid;<br>sched_param param;<br>int newprio=20;<br><br>pthread_attr_init(&attr);<br>pthread_attr_getschedparam(&attr, &param);<br>param.sched_priority=newprio;<br>pthread_attr_setschedparam(&attr, &param);<br>pthread_create(&tid, &attr, (void *)myfunction, myarg);</td> </tr> </tbody> </table> <strong>U程的数据处?br><br></strong>  和进E相比,U程的最大优点之一是数据的׃n性,各个q程׃n父进E处沿袭的数据段Q可以方便的获得、修Ҏ据。但q也l多U程~程带来了许多问题。我们必d心有多个不同的进E访问相同的变量。许多函数是不可重入的,卛_时不能运行一个函数的多个拯Q除非用不同的数据D)。在函数中声明的静态变量常常带来问题,函数的返回g会有问题。因为如果返回的是函数内部静态声明的I间的地址Q则在一个线E调用该函数得到地址后用该地址指向的数据时Q别的线E可能调用此函数q修改了q一D|据。在q程中共享的变量必须用关键字volatile来定义,q是Z防止~译器在优化Ӟ如gcc中?OX参数Q改变它们的使用方式。ؓ了保护变量,我们必须使用信号量、互斥等Ҏ来保证我们对变量的正用。下面,我们逐步介绍处理U程数据时的有关知识?br><br>  1、线E数?br><br>  在单U程的程序里Q有两种基本的数据:全局变量和局部变量。但在多U程E序里,q有W三U数据类型:U程数据QTSD: Thread-Specific DataQ。它和全局变量很象Q在U程内部Q各个函数可以象使用全局变量一栯用它Q但它对U程外部的其它线E是不可见的。这U数据的必要性是显而易见的。例如我们常见的变量errnoQ它q回标准的出错信息。它昄不能是一个局部变量,几乎每个函数都应该可以调用它Q但它又不能是一个全局变量Q否则在AU程里输出的很可能是BU程的出错信息。要实现诸如此类的变量,我们必M用线E数据。我们ؓ每个U程数据创徏一个键Q它和这个键相关联,在各个线E里Q都使用q个键来指代U程数据Q但在不同的U程里,q个键代表的数据是不同的Q在同一个线E里Q它代表同样的数据内宏V?br><br>  和线E数据相关的函数主要?个:创徏一个键Qؓ一个键指定U程数据Q从一个键dU程数据Q删除键?br><br>  创徏键的函数原型为:<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>extern int pthread_key_create __P ((pthread_key_t *__key,void (*__destr_function) (void *)));</td> </tr> </tbody> </table>   <br>  W一个参Cؓ指向一个键值的指针Q第二个参数指明了一个destructor函数Q如果这个参C为空Q那么当每个U程l束Ӟpȝ调用这个函数来释放l定在这个键上的<a target=_blank><font color=#000000><u>内存</u></font></a>块。这个函数常和函数pthread_once ((pthread_once_t*once_control, void (*initroutine) (void)))一起用,Z让这个键只被创徏一ơ。函数pthread_once声明一个初始化函数Q第一ơ调用pthread_once时它执行q个函数Q以后的调用被它忽略?br><br>  在下面的例子中,我们创徏一个键Qƈ它和某个数据相兌。我们要定义一个函数createWindowQ这个函数定义一个图形窗口(数据cd为Fl_Window *Q这是图形界面开发工具FLTK中的数据cdQ。由于各个线E都会调用这个函敎ͼ所以我们用线E数据?br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>/* 声明一个键*/<br>pthread_key_t myWinKey;<br>/* 函数 createWindow */<br>void createWindow ( void ) {<br> Fl_Window * win;<br> static pthread_once_t once= PTHREAD_ONCE_INIT;<br> /* 调用函数createMyKeyQ创建键*/<br> pthread_once ( & once, createMyKey) ;<br> /*win指向一个新建立的窗?/<br> win=new Fl_Window( 0, 0, 100, 100, "MyWindow");<br> /* ҎH口作一些可能的讄工作Q如大小、位|、名U等*/<br> setWindow(win);<br> /* 窗口指针值绑定在键myWinKey?/<br> pthread_setpecific ( myWinKey, win);<br>}<br><br>/* 函数 createMyKeyQ创Z个键Qƈ指定了destructor */<br>void createMyKey ( void ) {<br> pthread_keycreate(&myWinKey, freeWinKey);<br>}<br><br>/* 函数 freeWinKeyQ释攄?/<br>void freeWinKey ( Fl_Window * win){<br> delete win;<br>}</td> </tr> </tbody> </table> <br>  q样Q在不同的线E中调用函数createMyWinQ都可以得到在线E内部均可见的窗口变量,q个变量通过函数pthread_getspecific得到。在上面的例子中Q我们已l用了函数pthread_setspecific来将U程数据和一个键l定在一赗这两个函数的原型如下:<br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>  extern int pthread_setspecific __P ((pthread_key_t __key,__const void *__pointer));<br>  extern void *pthread_getspecific __P ((pthread_key_t __key));</td> </tr> </tbody> </table> <br>  q两个函数的参数意义和用方法是显而易见的。要注意的是Q用pthread_setspecificZ个键指定新的U程数据Ӟ必须自己释放原有的线E数据以回收I间。这个过E函数pthread_key_delete用来删除一个键Q这个键占用的内存将被释放,但同栯注意的是Q它只释N占用的内存,q不释放该键兌的线E数据所占用的内存资源,而且它也不会触发函数pthread_key_create中定义的destructor函数。线E数据的释放必须在释N之前完成?br><br>  2、互斥锁<br><br>  互斥锁用来保证一D|间内只有一个线E在执行一D代码。必要性显而易见:假设各个U程向同一个文仉序写入数据,最后得到的l果一定是N性的?br><br>  我们先看下面一D代码。这是一个读/写程序,它们公用一个缓冲区Qƈ且我们假定一个缓冲区只能保存一条信息。即~冲区只有两个状态:有信息或没有信息?br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>void reader_function ( void );<br>void writer_function ( void ); <br><br>char buffer;<br>int buffer_has_item=0;<br>pthread_mutex_t mutex;<br>struct timespec delay;<br>void main ( void ){<br> pthread_t reader;<br> /* 定义延迟旉*/<br> delay.tv_sec = 2;<br> delay.tv_nec = 0;<br> /* 用默认属性初始化一个互斥锁对象*/<br> pthread_mutex_init (&mutex,NULL);<br> pthread_create(&reader, pthread_attr_default, (void *)&reader_function), NULL);<br> writer_function( );<br>}<br><br>void writer_function (void){<br> while(1){<br>  /* 锁定互斥?/<br>  pthread_mutex_lock (&mutex);<br>  if (buffer_has_item==0){<br>   buffer=make_new_item( );<br>   buffer_has_item=1;<br>  }<br>  /* 打开互斥?/<br>  pthread_mutex_unlock(&mutex);<br>  pthread_delay_np(&delay);<br> }<br>}<br><br>void reader_function(void){<br> while(1){<br>  pthread_mutex_lock(&mutex);<br>  if(buffer_has_item==1){<br>   consume_item(buffer);<br>   buffer_has_item=0;<br>  }<br>  pthread_mutex_unlock(&mutex);<br>  pthread_delay_np(&delay);<br> }<br>}</td> </tr> </tbody> </table> <br>  q里声明了互斥锁变量mutexQ结构pthread_mutex_tZ公开的数据类型,其中包含一个系l分配的属性对象。函数pthread_mutex_init用来生成一个互斥锁。NULL参数表明使用默认属性。如果需要声明特定属性的互斥锁,调用函数pthread_mutexattr_init。函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用来讄互斥锁属性。前一个函数设|属性psharedQ它有两个取|PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用来不同进E中的线E同步,后者用于同步本q程的不同线E。在上面的例子中Q我们用的是默认属性PTHREAD_PROCESS_ PRIVATE。后者用来设|互斥锁cdQ可选的cd有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它们分别定义了不同的上所、解锁机Ӟ一般情况下Q选用最后一个默认属性?br><br>  pthread_mutex_lock声明开始用互斥锁上锁,此后的代码直臌用pthread_mutex_unlock为止Q均被上锁,卛_一旉只能被一个线E调用执行。当一个线E执行到pthread_mutex_lock处时Q如果该锁此时被另一个线E用,那此U程被阻塞,即程序将{待到另一个线E释放此互斥锁。在上面的例子中Q我们用了pthread_delay_np函数Q让U程睡眠一D|_是Z防止一个线E始l占据此函数?br><br>  上面的例子非常简单,׃再介l了Q需要提出的是在使用互斥锁的q程中很有可能会出现死锁Q两个线E试囑֐时占用两个资源,q按不同的次序锁定相应的互斥锁,例如两个U程都需要锁定互斥锁1和互斥锁2QaU程先锁定互斥锁1QbU程先锁定互斥锁2Q这时就出现了死锁。此时我们可以用函数pthread_mutex_trylockQ它是函数pthread_mutex_lock的非d版本Q当它发现死锁不可避免时Q它会返回相应的信息Q程序员可以针对死锁做出相应的处理。另外不同的互斥锁类型对死锁的处理不一P但最主要的还是要E序员自己在E序设计注意q一炏V?br><br>  3、条件变?br><br>  前一节中我们讲述了如何用互斥锁来实现线E间数据的共享和通信Q互斥锁一个明昄~点是它只有两种状态:锁定和非锁定。而条件变量通过允许U程d和等待另一个线E发送信LҎ弥补了互斥锁的不I它常和互斥锁一起用。用时Q条件变量被用来d一个线E,当条件不满ӞU程往往解开相应的互斥锁q等待条件发生变化。一旦其它的某个U程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的U程。这些线E将重新锁定互斥锁ƈ重新试条g是否满。一般说来,条g变量被用来进行线扉K的同步?<br><br>  条g变量的结构ؓpthread_cond_tQ函数pthread_cond_initQ)被用来初始化一个条件变量。它的原型ؓQ?br><br>  extern int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t *__cond_attr));<br><br>  其中cond是一个指向结构pthread_cond_t的指针,cond_attr是一个指向结构pthread_condattr_t的指针。结构pthread_condattr_t是条件变量的属性结构,和互斥锁一h们可以用它来讄条g变量是进E内可用q是q程间可用,默认值是PTHREAD_ PROCESS_PRIVATEQ即此条件变量被同一q程内的各个U程使用。注意初始化条g变量只有未被使用时才能重新初始化或被释放。释放一个条件变量的函数为pthread_cond_ destroyQpthread_cond_t condQ。 <br><br>  函数pthread_cond_waitQ)使线E阻塞在一个条件变量上。它的函数原型ؓQ?br><br>  extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));<br><br>  U程解开mutex指向的锁q被条g变量condd。线E可以被函数pthread_cond_signal和函数pthread_cond_broadcast唤醒Q但是要注意的是Q条件变量只是vd和唤醒线E的作用Q具体的判断条gq需用户l出Q例如一个变量是否ؓ0{等Q这一Ҏ们从后面的例子中可以看到。线E被唤醒后,它将重新查判断条件是否满I如果q不满Q一般说来线E应该仍d在这里,被等待被下一ơ唤醒。这个过E一般用while语句实现?br><br>  另一个用来阻塞线E的函数是pthread_cond_timedwaitQ)Q它的原型ؓQ?br>  extern int pthread_cond_timedwait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex, __const struct timespec *__abstime));<br><br>  它比函数pthread_cond_waitQ)多了一个时间参敎ͼl历abstimeD|间后Q即使条件变量不满Q阻塞也被解除?br><br>  函数pthread_cond_signalQ)的原型ؓQ?br><br>  extern int pthread_cond_signal __P ((pthread_cond_t *__cond));<br><br>  它用来释放被d在条件变量cond上的一个线E。多个线E阻塞在此条件变量上Ӟ哪一个线E被唤醒是由U程的调度策略所军_的。要注意的是Q必ȝ保护条g变量的互斥锁来保护这个函敎ͼ否则条g满信号又可能在试条g和调用pthread_cond_wait函数之间被发出,从而造成无限制的{待。下面是使用函数pthread_cond_waitQ)和函数pthread_cond_signalQ)的一个简单的例子?br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>pthread_mutex_t count_lock;<br>pthread_cond_t count_nonzero;<br>unsigned count;<br>decrement_count () {<br> pthread_mutex_lock (&count_lock);<br> while(count==0) <br>  pthread_cond_wait( &count_nonzero, &count_lock);<br>  count=count -1;<br> pthread_mutex_unlock (&count_lock);<br>}<br><br>increment_count(){<br> pthread_mutex_lock(&count_lock);<br> if(count==0)<br>  pthread_cond_signal(&count_nonzero);<br>  count=count+1;<br> pthread_mutex_unlock(&count_lock);<br>}</td> </tr> </tbody> </table> <br>  countgؓ0Ӟdecrement函数在pthread_cond_wait处被dQƈ打开互斥锁count_lock。此Ӟ当调用到函数increment_countӞpthread_cond_signalQ)函数改变条g变量Q告知decrement_countQ)停止d。读者可以试着让两个线E分别运行这两个函数Q看看会出现什么样的结果?br><br>  函数pthread_cond_broadcastQpthread_cond_t *condQ用来唤醒所有被d在条件变量cond上的U程。这些线E被唤醒后将再次竞争相应的互斥锁Q所以必d心用这个函数?br><br>  4、信号量<br><br>  信号量本质上是一个非负的整数计数器,它被用来控制对公p源的讉K。当公共资源增加Ӟ调用函数sem_postQ)增加信号量。只有当信号量值大于0Ӟ才能使用公共资源Q用后Q函数sem_waitQ)减少信号量。函数sem_trywaitQ)和函数pthread_ mutex_trylockQ)起同L作用Q它是函数sem_waitQ)的非d版本。下面我们逐个介绍和信号量有关的一些函敎ͼ它们都在头文?usr/include/semaphore.h中定义?br><br>  信号量的数据cd为结构sem_tQ它本质上是一个长整型的数。函数sem_initQ)用来初始化一个信号量。它的原型ؓQ?br><br>  extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));<br><br>  sem为指向信号量l构的一个指针;pshared不ؓQ时此信号量在进E间׃nQ否则只能ؓ当前q程的所有线E共享;valuel出了信号量的初始倹{?br><br>  函数sem_post( sem_t *sem )用来增加信号量的倹{当有线E阻塞在q个信号量上Ӟ调用q个函数会其中的一个线E不在阻塞,选择机制同样是由U程的调度策略决定的?br><br>  函数sem_wait( sem_t *sem )被用来阻塞当前线E直C号量sem的值大?Q解除阻塞后sem的值减一Q表明公p源经使用后减。函数sem_trywait ( sem_t *sem )是函数sem_waitQ)的非d版本Q它直接信号量sem的值减一?br><br>  函数sem_destroy(sem_t *sem)用来释放信号量sem?br><br>  下面我们来看一个用信号量的例子。在q个例子中,一共有4个线E,其中两个U程负责从文件读取数据到公共的缓冲区Q另两个U程从缓冲区d数据作不同的处理Q加和乘q算Q?br><br> <table align=center bgColor=#e3e3e3 border=1> <tbody> <tr> <td>/* File sem.c */<br>#include <stdio.h><br>#include <pthread.h><br>#include <semaphore.h><br>#define MAXSTACK 100<br>int stack[MAXSTACK][2];<br>int size=0;<br>sem_t sem;<br>/* 从文?.datd数据Q每Mơ,信号量加一*/<br>void ReadData1(void){<br> FILE *fp=fopen("1.dat","r");<br> while(!feof(fp)){<br>  fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]);<br>  sem_post(&sem);<br>  ++size;<br> }<br> fclose(fp);<br>}<br>/*从文?.datd数据*/<br>void ReadData2(void){<br> FILE *fp=fopen("2.dat","r");<br> while(!feof(fp)){<br>  fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]);<br>  sem_post(&sem);<br>  ++size;<br> }<br> fclose(fp);<br>}<br>/*d{待~冲区有数据Q读取数据后Q释攄_l箋{待*/<br>void HandleData1(void){<br> while(1){<br>  sem_wait(&sem);<br>  printf("Plus:%d+%d=%dn",stack[size][0],stack[size][1],<br>  stack[size][0]+stack[size][1]);<br>  --size;<br> }<br>}<br><br>void HandleData2(void){<br> while(1){<br>  sem_wait(&sem);<br>  printf("Multiply:%d*%d=%dn",stack[size][0],stack[size][1],<br>  stack[size][0]*stack[size][1]);<br>  --size;<br> }<br>}<br>int main(void){<br> pthread_t t1,t2,t3,t4;<br> sem_init(&sem,0,0);<br> pthread_create(&t1,NULL,(void *)HandleData1,NULL);<br> pthread_create(&t2,NULL,(void *)HandleData2,NULL);<br> pthread_create(&t3,NULL,(void *)ReadData1,NULL);<br> pthread_create(&t4,NULL,(void *)ReadData2,NULL);<br> /* 防止E序q早退出,让它在此无限期等?/<br> pthread_join(t1,NULL);<br>}</td> </tr> </tbody> </table> <br>  在Linux下,我们用命令gcc -lpthread sem.c -o sem生成可执行文件sem?我们事先~辑好数据文?.dat?.datQ假讑֮们的内容分别? 2 3 4 5 6 7 8 9 10?-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 Q我们运行semQ得到如下的l果Q?br><br>Multiply:-1*-2=2<br>Plus:-1+-2=-3<br>Multiply:9*10=90<br>Plus:-9+-10=-19<br>Multiply:-7*-8=56<br>Plus:-5+-6=-11<br>Multiply:-3*-4=12<br>Plus:9+10=19<br>Plus:7+8=15<br>Plus:5+6=11<br><br>  从中我们可以看出各个U程间的竞争关系。而数值ƈ未按我们原先的顺序显C出来这是由于sizeq个数D各个U程L修改的缘故。这也往往是多U程~程要注意的问题?br> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/87518.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-06-12 19:47 <a href="http://www.shnenglu.com/ivy-jie/articles/87518.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linuxq程通信http://www.shnenglu.com/ivy-jie/articles/87516.htmlivy-jieivy-jieFri, 12 Jun 2009 11:45:00 GMThttp://www.shnenglu.com/ivy-jie/articles/87516.htmlhttp://www.shnenglu.com/ivy-jie/comments/87516.htmlhttp://www.shnenglu.com/ivy-jie/articles/87516.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/87516.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/87516.html1、管?pipe)

用语h亲缘关系q程间的通信

匿名一ơ性用的Q半双工。一个进E往输出端写道Q另一个进E从输入端读道?br>  #include<unistd.h>
  int pipe(int fd[2]);
  fd[0]:表示ȝ
  fd[1]:表示写端

 

2、有名管?named pipe)

允许无亲~关p进E间的通信

有名道Q作为特别文件存储于文gpȝ中。有名管道一旦徏立就存在于文件系l中Q除非显C的unlink
  #include<sys/tpes.h>
  #include<sys/stat.h>
  int mknod(const char *path,mode_t mod,dev_t dev);
  int mkfifo(const char *path,mode_t mode);
  path:创徏有名道的全路径?br>  mod:创徏有名道的模式,指存取权?br>  dev:讑֤|该值取决于文g创徏的种c,它只在创备文件时才会用到
  注意:有名道创徏后就可以使用了,有名道和管道的使用Ҏ基本是相同的。只是用有名管道的时候必d调用open()其打开
  因ؓ有名道是一个存在于盘上的文gQ而管道是存在于内存中的特D文?/p>

  下面的程序一个读道Q另一个写道Q这两个函数用的是非dd道

 

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"

main(int argc, char** argv)
{
    char buf_r[100];
    int fd;
    int nread;
  
    if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
        printf("cannot create fifoserver\n");
    printf("Preparing for reading bytes...\n");
    memset(buf_r,0,sizeof(buf_r));

    fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
    if(fd==-1)
    {
        perror("open");
        exit(1);
    }
    while(1)
    {
        memset(buf_r,0,sizeof(buf_r));
        if((nread=read(fd,buf_r,100))==-1){
            if(errno==EAGAIN)
                printf("no data yet\n");
     }
        printf("read %s from FIFO\n",buf_r);
        sleep(1);
    }
    pause();
    unlink(FIFO);
}

 


#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"

main(int argc,char** argv)
{
    int fd;
    char w_buf[100];
    int nwrite;
    if(fd==-1)
        if(errno==ENXIO)
            printf("open error; no reading process\n");
  
    fd=open(FIFO,O_WRONLY|O_NONBLOCK,0);
    if(argc==1)
        printf("Please send something\n");
    strcpy(w_buf,argv[1]);

    if((nwrite=write(fd,w_buf,100))==-1)
    {
        if(errno==EAGAIN)
            printf("The FIFO has not been read yet.Please try later\n");
    }
    else
        printf("write %s to the FIFO\n",w_buf);
}


3、信号量

主要用于q程间及同一q程不同U程之间的同步手D?/p>


4、消息队?/p>

克服信号量有限,可写可读


5、信PSignalQ?/p>

比较复杂Q用于通知接受q程有某事发?/p>


6、共享内?/p>

最有用的进E间通信方式Q得多个进E可讉K同以内存I间Q但需要依靠某U同步机?/p>

W一步:创徏׃n内存

W二步:映射׃n内存


7、套接字

不同机器之间通信

 



ivy-jie 2009-06-12 19:45 发表评论
]]>
þùһ| þѴƬ| þþ| ƷžžþƵ | þþƷ鶹| 99þþƷѿһ| þѹۿƵ| þþþ18| һۺϾþù| ٸþþþþñŪ߳| þþþAVרվ| ƷŮͬһþ| þþƷһӰ| þþƷɭ| ձɫվWWWþ | ޹պۺϾþþƷ| þӰ| þ¶ݺɫ| ŷպۺϾþ| ˾þþƷavһ| ҹƷþ| þþƷAV| þþþ뾫Ʒ| 99þѹػ| 99þþƷ| ij˾þþþӰԺѹۿ| ˾þó˳ۺ222| ɫ͵͵þһ| Ʒþþþþ| 51þҹɫƷ| ɫɫۺϾþҹҹ| 91Ʒ9lþþþ| þwww˳ɾƷ㽶| þˬˬˬ| þþƷavӰԺ| Ʒ99þþƷ| þAV| ޹þþþþþ| Ʒþþþþþù˽| þþŷղ| ҹӰþ|