Linux下的多进程编程初步(转载).pdf
《Linux下的多进程编程初步(转载).pdf》由会员分享,可在线阅读,更多相关《Linux下的多进程编程初步(转载).pdf(9页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、1引言对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。fork函数是Unix系统最杰出的成就之一,它是七十代UNIX早期的开发者经过长期在理论和实践上的艰苦探索后取得的成果,一方面,它使操作系统在进程管理上付出最小的代价,另一方面,又为程序员提供一个简洁明的多进程方法。与DOS和早期的Windows同,Unix/Linux系统是真正实现多任务操作的系统,可以说,使用多进程编程,就能算是真正的Linux环境下编程。多线程程序设计的概念早在六十代就被提出,但直到八十代中期,Unix系统中才引入多线程机制,如今,由于自身的许多优点,多线程编程
2、已经得到广泛的应用。下面,我们将介绍在Linux下编写多进程和多线程程序的一些初步知识。2多进程编程什么是一个进程?进程这个概念是针对系统而是针对用户的,对用户来说,他面对的概念是程序。当用户敲入命令执行一个程序的时候,对系统而言,它将启动一个进程。但和程序同的是,在这个进程中,系统可能需要再启动一个或多个进程来完成独立的多个任务。多进程编程的主要内容包括进程控制和进程间通信,在解这些之前,我们先要简单知道进程的结构。2.1Linux下进程的结构Linux下一个进程在内存里有三部分的数据,就是代码段、堆栈段和数据段。其实学过汇编语言的人一定知道,一般的CPU都有上述三种段寄存器,以方便操作系统
3、的运行。这三个部分也是构成一个完整的执行序列的必要的部分。代码段,顾名思义,就是存放程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。堆栈段存放的就是子程序的返回地址、子程序的参数以及程序的局部变。而数据段则存放程序的全局变,常数以及动态数据分配的数据空间(比如用malloc之类的函数取得的空间)。这其中有许多细节问题,这里限于篇幅就多介绍。系统如果同时运行数个相同的程序,它们之间就能使用同一个堆栈段和数据段。2.2Linux下的进程控制在传统的Unix环境下,有两个基本的操作用于创建和修改进程:函数fork()用来创建一个新的进程,该进程几乎是当前进程的
4、一个完全拷贝;函数族exec()用来启动另外的进程以取代当前运行的进程。Linux的进程控制和传统的Unix进程控制基本一致,只在一些细节的地方有些区别,例如在Linux系统中调用vfork和fork完全相同,而在有些版本的Unix系统中,vfork调用有同的功能。由于这些差别几乎影响我们大多数的编程,在这里我们予考虑。2.2.1fork()fork在英文中是分叉的意思。为什么取这个名字呢?因为一个进程在运行中,如果使用fork,就产生另一个进程,于是进程就分叉,所以这个名字取得很形象。下面就看看如何具体使用fork,这段程序演示使用fork的基本框架:cpp0 1.v o i d m a i
5、 n()0 2.i n t i 0 3.i f (f o r k()=0 )0 4./*子进程程序*/0 5.f o r (i =1 i 1 0 0 0 i +)p r i n t f(T h i s i s c h i l d p r o c e s s/n )0 6.0 7.e l s e 0 8./*父进程程序*/0 9.f o r (i =1 i )0 8.f g e t s(c o m m a n d,2 5 6,s t d i n )0 9.c o m m a n d s t r l e n(c o m m a n d)1 =0 1 0.i f (f o r k()=0 )1 1.
6、/*子进程执行此命令*/1 2.e x e c l p(c o m m a n d,c o m m a n d )1 3./*如果e x e c 函数返回,表明没有正常执行命令,打印错误信息*/1 4.p e r r o r(c o m m a n d )1 5.e x i t(e r r o r n o )1 6.1 7.e l s e 1 8./*父进程,等待子进程结束,并打印子进程的返回值*/1 9.w a i t (&r t n )2 0.p r i n t f(c h i l d p r o c e s s r e t u r n%d/n ,.r t n )2 1.2 2.2 3.此
7、程序从终端读入命令并执行之,执行完成后,父进程继续等待从终端读入命令。熟悉DOS和WINDOWS系统调用的朋友一定知道DOS/WINDOWS也有exec类函数,其使用方法是类似的,但DOS/WINDOWS还有spawn类函数,因为DOS是单任务的系统,它只能将父进程驻留在机器内再执行子进程,这就是spawn类的函数。WIN32已经是多任务的系统,但还保留spawn类函数,WIN32中实现spawn函数的方法同前述UNIX中的方法差多,开设子进程后父进程等待子进程结束后才继续运行。UNIX在其一开始就是多任务的系统,所以从核心角度上讲需要spawn类函数。在这一节里,我们还要讲讲system()
8、和popen()函数。system()函数先调用fork(),然后再调用exec()来执行用户的登录shell,通过它来查找可执行文件的命令并分析参数,最后它么使用wait()函数族无法加载插件。无法加载插件。无法加载插件。无法加载插件。之一来等待子进程的结束。函数popen()和函数system()相似,同的是它调用pipe()函数创建一个管道,通过它来完成程序的标准输入和标准输出。这两个函数是为那些太勤快的程序员设计的,在效率和安全方面都有相当的缺陷,在可能的情况下,应该尽避免。2.3Linux下的进程间通信详细的讲述进程间通信在这里绝对是可能的事情,而且笔者很难有信心说自己对这一部分内容
9、的认识达到什么样的地步,所以在这一节的开头首先向大家推荐著名作者RichardStevens的著名作品:AdvancedProgrammingintheUNIXEnvironment,它的中文译本UNIX环境高级编程已有机械工业出版社出版,原文精彩,译文同样地道,如果你的确对在Linux下编程有浓厚的兴趣,那么赶紧将这本书摆到你的书桌上或计算机旁边来。说这么多实在是难抑心中的景仰之情,言归正传,在这一节里,我们将介绍进程间通信最最初步和最最简单的一些知识和概念。首先,进程间通信至少可以通过传送打开文件来实现,同的进程通过一个或多个文件来传递信息,事实上,在很多应用系统里,都使用这种方法。但一般
10、说来,进程间通信(IPC:InterProcessCommunication)包括这种似乎比较低级的通信方法。Unix系统中实现进程间通信的方法很多,而且幸的是,极少方法能在所有的Unix系统中进行移植(唯一一种是半双工的管道,这也是最原始的一种通信方式)。而Linux作为一种新兴的操作系统,几乎支持所有的Unix下常用的进程间通信方法:管道、消息队列、共享内存、信号、套接口等等。下面我们将逐一介绍。2.3.1管道管道是进程间通信中最古的方式,它包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信。无名管道由pipe()函数创建:#inc
11、ludeintpipe(intfiledis2);参数filedis返回两个文件描述符:filedes0为读而打开,filedes1为写而打开。filedes1的输出是filedes0的输入。下面的例子示范如何在父进程和子进程间实现通信。cpp0 1.#d e f i n e I N P U T 0 0 2.#d e f i n e O U T P U T 1 0 3.0 4.v o i d m a i n()0 5.i n t f i l e _ d e s c r i p t o r s 2 0 6./*定义子进程号*/0 7.p i d _ t p i d 0 8.c h a r b u
12、 f 2 5 6 0 9.i n t r e t u r n e d _ c o u n t 1 0./*创建无名管道*/1 1.p i p e(f i l e _ d e s c r i p t o r s)1 2./*创建子进程*/1 3.i f(p i d =f o r k()=1)1 4.p r i n t f(E r r o r i n f o r k/n )1 5.e x i t(1)1 6.1 7./*执行子进程*/1 8.i f(p i d =0)1 9.p r i n t f(i n t h e s p a w n e d (c h i l d)p r o c e s s./
13、n )2 0./*子进程向父进程写数据,关闭管道的读端*/2 1.c l o s e(f i l e _ d e s c r i p t o r s I N P U T )2 2.w r i t e(f i l e _ d e s c r i p t o r s O U T P U T ,t e s t d a t a ,s t r l e n(t e s t d a t a )2 3.e x i t(0)2 4.e l s e 2 5./*执行父进程*/2 6.p r i n t f(i n t h e s p a w n i n g (p a r e n t)p r o c e s s./
14、n )2 7./*父进程从管道读取子进程写的数据,关闭管道的写端*/2 8.c l o s e(f i l e _ d e s c r i p t o r s O U T P U T )2 9.r e t u r n e d _ c o u n t =r e a d(f i l e _ d e s c r i p t o r s I N P U T ,b u f,s i z e o f(b u f)3 0.p r i n t f(%d b y t e s o f d a t a r e c e i v e d f r o m s p a w n e d p r o c e s s:%s/n ,
15、3 1.r e t u r n e d _ c o u n t,b u f)3 2.3 3.在Linux系统下,有名管道可由两种方式创建:命令行方式mknod系统调用和函数mkfifo。下面的两种途径都在当前目录下生成一个名为myfifo的有名管道:方式一:mkfifo(myfifo,rw)方式二:mknodmyfifop生成有名管道后,就可以使用一般的文件I/O函数如open、close、read、write等来对它进行操作。下面即是一个简单的例子,假设我们已经创建一个名为myfifo的有名管道。cpp0 1./*进程一:读有名管道*/0 2.#i n c l u d e 0 3.#i n
16、c l u d e 0 4.v o i d m a i n()0 5.F I L E *i n _ f i l e 0 6.i n t c o u n t =1 0 7.c h a r b u f 8 0 0 8.i n _ f i l e =f o p e n(m y p i p e ,r )0 9.i f (i n _ f i l e =N U L L)1 0.p r i n t f(E r r o r i n f d o p e n./n )1 1.e x i t(1)1 2.1 3.w h i l e (c o u n t =f r e a d(b u f,1,8 0,i n _ f
17、i l e)0)1 4.p r i n t f(r e c e i v e d f r o m p i p e:%s/n ,b u f)1 5.f c l o s e(i n _ f i l e)1 6.1 7./*进程二:写有名管道*/1 8.#i n c l u d e 1 9.#i n c l u d e 2 0.v o i d m a i n()2 1.F I L E *o u t _ f i l e 2 2.i n t c o u n t =1 2 3.c h a r b u f 8 0 2 4.o u t _ f i l e =f o p e n(m y p i p e ,w )2
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 进程 编程 初步 转载
限制150内