ImageVerifierCode 换一换
格式:DOCX , 页数:32 ,大小:36.20KB ,
资源ID:8161483      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/8161483.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Unix 多进程编程.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Unix 多进程编程.docx

1、Unix 多进程编程精华 Unix 多进程编程 作者:htldm发表于:2003-08-27 15:10:25【发表评论】【查看原文】【SCO UNIX讨论区】【关闭】 一.多进程程序的特点 由于UNIX系统是分时多用户系统,CPU按时间片分配给各个用户使用,而在 实质上应该说CPU按时间片分配给各个进程使用,每个进程都有自己的运行环境 以使得在CPU做进程切换时不会忘记该进程已计算了一半的半成品.以DOS 的概念来说,进程的切换都是一次DOS中断处理过程,包括三个层次: (1)用户数据的保存:包括正文段(TEXT),数据段(DATA,BSS),栈段 (STACK),共享内存段(SHAREDM

2、EMORY)的保存. (2)寄存器数据的保存:包括PC(programcounter,指向下一条要执行的指 令的地址),PSW(processorstatusword,处理机状态字),SP(stack pointer,栈指针),PCBP(pointerofprocesscontrolblock,进程控 制块指针),FP(framepointer,指向栈中一个函数的local变量的首地 址),AP(augumentpointer,指向栈中函数调用的实参位置),ISP( interruptstackpointer,中断栈指针),以及其他的通用寄存器等. (3)系统层次的保存:包括proc,u,虚拟

3、存储空间管理表格,中断处理栈. 以便于该进程再一次得到CPU时间片时能正常运行下去. 既然系统已经处理好所有这些中断处理的过程,我们做程序还有什么要担 心的呢?我们尽可以使用系统提供的多进程的特点,让几个程序精诚合作,简 单而又高效地把结果给它搞出来. 另外,UNIX系统本身也是用C语言写的多进程程序,多进程编程是UNIX的特 点,当我们熟悉了多进程编程后,将会对UNIX系统机制有一个较深的认识. 首先我介绍一下多进程程序的一些突出的特点: 1.并行化 一件复杂的事件是可以分解成若干个简单事件来解决的,这在程序员 的大脑中早就形成了这种概念,首先将问题分解成一个个小问题,将小问 题再细分,最后

4、在一个合适的规模上做成一个函数.在软件工程中也是这 么说的.如果我们以图的方式来思考,一些小问题的计算是可以互不干扰 的,可以同时处理,而在关键点则需要统一在一个地方来处理,这样程序 的运行就是并行的,至少从人的时间观念上来说是这样的.而每个小问题 的计算又是较简单的. 2.简单有序 这样的程序对程序员来说不亚于管理一班人,程序员为每个进程设计 好相应的功能,并通过一定的通讯机制将它们有机地结合在一起,对每个 进程的设计是简单的,只在总控部分小心应付(其实也是蛮简单的),就可 完成整个程序的施工. 3.互不干扰 这个特点是操作系统的特点,各个进程是独立的,不会串位. 4.事务化 比如在一个数据

5、电话查询系统中,将程序设计成一个进程只处理一次 查询即可,即完成一个事务.当电话查询开始时,产生这样一个进程对付 这次查询;另一个电话进来时,主控程序又产生一个这样的进程对付,每 个进程完成查询任务后消失.这样的编程多简单,只要做一次查询的程序 就可以了. 二.常用的多进程编程的系统调用 1.fork() 功能:创建一个新的进程. 语法:#include #include pid_tfork(); 说明:本系统调用产生一个新的进程,叫子进程,是调用进程的一个复 制品.调用进程叫父进程,子进程继承了父进程的几乎所有的属 性: .实际UID,GID和有效UID,GID. .环境变量. .附加GID

6、. .调用exec()时的关闭标志. .UID设置模式比特位. .GID设置模式比特位. .进程组号. .会话ID. .控制终端. .当前工作目录. .根目录. .文件创建掩码UMASK. .文件长度限制ULIMIT. .预定值,如优先级和任何其他的进程预定参数,根据种类不同 决定是否可以继承. .还有一些其它属性. 但子进程也有与父进程不同的属性: .进程号,子进程号不同与任何一个活动的进程组号. .父进程号. .子进程继承父进程的文件描述符或流时,具有自己的一个拷贝 并且与父进程和其它子进程共享该资源. .子进程的用户时间和系统时间被初始化为0. .子进程的超时时钟设置为0. .子进程的信

7、号处理函数指针组置为空. .子进程不继承父进程的记录锁. 返回值:调用成功则对子进程返回0,对父进程返回子进程号,这也是 最方便的区分父子进程的方法.若调用失败则返回-1给父进程, 子进程不生成. 例子:pid_tpid; if(pid=fork();0) /*父进程处理过程*/ elseif(pid=0) /*子进程处理过程*/ exit(0);/*注意子进程必须用exit()退出运行*/ else printf(forkerrorn); exit(0); 2.system() 功能:产生一个新的进程,子进程执行指定的命令. 语法:#include #include intsystem(st

8、ring) char*string; 说明:本调用将参数string传递给一个命令解释器(一般为sh)执行,即 string被解释为一条命令,由sh执行该命令.若参数string为一 个空指针则为检查命令解释器是否存在. 该命令可以同命令行命令相同形式,但由于命令做为一个参数放 在系统调用中,应注意编译时对特殊意义字符的处理.命令的查 找是按PATH环境变量的定义的.命令所生成的后果一般不会对父 进程造成影响. 返回值:当参数为空指针时,只有当命令解释器有效时返回值为非零. 若参数不为空指针,返回值为该命令的返回状态(同waitpid() 的返回值.命令无效或语法错误则返回非零值,所执行的命令

9、被 终止.其他情况则返回-1. 例子:charcommand81; inti; for(i=1;i;0) wait(int*)0); /*父进程等待子进程的返回*/ else /*子进程处理过程*/ exit(0); 7.waitpid() 功能:等待指定进程号的子进程的返回并修改状态 语法:#include #include pid_twaitpid(pid,stat_loc,options) pid_tpid; int*stat_loc,options; 说明:当pid等于-1,options等于0时,该系统调用等同于wait().否则该 系统调用的行为由参数pid和options决定.

10、pid指定了一组父进程要求知道其状态的子进程: -1:要求知道任何一个子进程的返回状态. ;0:要求知道进程号为pid值的子进程的状态. ;0) waitpid(pid,&stat_loc,0); /*父进程等待进程号为pid的子进程的返回*/ else /*子进程的处理过程*/ exit(1); /*父进程*/ printf(stat_locis%dn,stat_loc); /*字符串stat_locis1将被打印出来*/ 8.setpgrp() 功能:设置进程组号和会话号. 语法:#include pid_tsetpgrp() 说明:若调用进程不是会话首进程.将进程组号和会话号都设

11、置为与它 的进程号相等.并释放调用进程的控制终端. 返回值:调用成功后,返回新的进程组号. 例子:/*父进程处理*/ if(fork();0) /*父进程处理*/ else setpgrp(); /*子进程的进程组号已修改成与它的进程号相同*/ exit(0); 9.exit() 功能:终止进程. 语法:#include voidexit(status) intstatus; 说明:调用进程被该系统调用终止.引起附加的处理在进程被终止前全 部结束. 返回值:无 10.signal() 功能:信号管理功能 语法:#include void(*signal(sig,disp)(int) intsi

12、g; void(*disp)(int); void(*sigset(sig,disp)(int) intsig; void(*disp)(int); intsighold(sig) intsig; intsigrelse(sig) intsig; intsigignore(sig) intsig; intsigpause(sig) intsig; 说明:这些系统调用提供了应用程序对指定信号的简单的信号处理. signal()和sigset()用于修改信号定位.参数sig指定信号(除了 SIGKILL和SIGSTOP,这两种信号由系统处理,用户程序不能捕捉到). disp指定新的信号定位,即新的

13、信号处理函数指针.可以为 SIG_IGN,SIG_DFL或信号句柄地址. 若使用signal(),disp是信号句柄地址,sig不能为SIGILL,SIGTRAP 或SIGPWR,收到该信号时,系统首先将重置sig的信号句柄为SIG_DFL, 然后执行信号句柄. 若使用sigset(),disp是信号句柄地址,该信号时,系统首先将该 信号加入调用进程的信号掩码中,然后执行信号句柄.当信号句柄 运行结束 后,系统将恢复调用进程的信号掩码为信号收到前的状态.另外, 使用sigset()时,disp为SIG_HOLD,则该信号将会加入调用进程的 信号掩码中而信号的定位不变. sighold()将信号

14、加入调用进程的信号掩码中. sigrelse()将信号从调用进程的信号掩码中删除. sigignore()将信号的定位设置为SIG_IGN. sigpause()将信号从调用进程的信号掩码中删除,同时挂起调用 进程直到收到信号. 若信号SIGCHLD的信号定位为SIG_IGN,则调用进程的子进程在终 止时不会变成僵死进程.调用进程也不用等待子进程返回并做相 应处理. 返回值:调用成功则signal()返回最近调用signal()设置的disp的值. 否则返回SIG_ERR. 例子一:设置用户自己的信号中断处理函数,以SIGINT信号为例: intflag=0; voidmyself() fla

15、g=1; printf(getsignalSIGINTn); /*若要重新设置SIGINT信号中断处理函数为本函数则执行以 *下步骤*/ void(*a)(); a=myself; signal(SIGINT,a); flag=2; main() while(1) sleep(2000);/*等待中断信号*/ if(flag=1) printf(skipsystemcallsleepn); exit(0); if(flag=2) printf(skipsystemcallsleepn); printf(waitingfornextsignaln); 11.kill() 功能:向一个或一组进程发

16、送一个信号. 语法:#include #include intkill(pid,sig); pid_tpid; intsig; 说明:本系统调用向一个或一组进程发送一个信号,该信号由参数sig指 定,为系统给出的信号表中的一个.若为0(空信号)则检查错误但 实际上并没有发送信号,用于检查pid的有效性. pid指定将要被发送信号的进程或进程组.pid若大于0,则信号将 被发送到进程号等于pid的进程;若pid等于0则信号将被发送到所 有的与发送信号进程同在一个进程组的进程(系统的特殊进程除 外);若pid小于-1,则信号将被发送到所有进程组号与pid绝对值 相同的进程;若pid等于-1,则信号

17、将被发送到所有的进程(特殊系 统进程除外). 信号要发送到指定的进程,首先调用进程必须有对该进程发送信 号的权限.若调用进程有合适的优先级则具备有权限.若调用进程 的实际或有效的UID等于接收信号的进程的实际UID或用setuid() 系统调用设置的UID,或sig等于SIGCONT同时收发双方进程的会话 号相同,则调用进程也有发送信号的权限. 若进程有发送信号到pid指定的任何一个进程的权限则调用成功, 否则调用失败,没有信号发出. 返回值:调用成功则返回0,否则返回-1. 例子:假设前一个例子进程号为324,现向它发一个SIGINT信号,让它做 信号处理: kill(pid_t)324,S

18、IGINT); 12.alarm() 功能:设置一个进程的超时时钟. 语法:#include unsignedintalarm(sec) unsignedintsec; 说明:指示调用进程的超时时钟在指定的时间后向调用进程发送一个 SIGALRM信号.设置超时时钟时时间值不会被放入堆栈中,后一次 设置会把前一次(还未到超时时间)冲掉. 若sec为0,则取消任何以前设置的超时时钟. fork()会将新进程的超时时钟初始化为0.而当一个进程用exec() 族系统调用新的执行文件时,调用前设置的超时时钟在调用后仍 有效. 返回值:返回上次设置超时时钟后到调用时还剩余的时间秒数. 例子:intflag

19、=0; voidmyself() flag=1; printf(getsignalSIGALRMn); /*若要重新设置SIGALRM信号中断处理函数为本函数则执行 *以下步骤*/ void(*a)(); a=myself; signal(SIGALRM,a); flag=2; main() alarm(100);/*100秒后发超时中断信号*/ while(1) sleep(2000);/*等待中断信号*/ if(flag=1) printf(skipsystemcallsleepn); exit(0); if(flag=2) printf(skipsystemcallsleepn); printf(waitingfornextsignaln); 13.msgsnd() 功能:发送消息到指定的消息队列中. 语法:#include #include #include intmsgsnd(msqid,msgp,msgsz,msgflg) intmsqid; void*msgp; size_tmsgsz; intmsgflg; 说明:发送一个消息到由msqid指定消息队列标识号的消息队列. 参数msgp指向一个用户定义的缓冲区,并且缓冲区的第一个域应 为长整型,指定消息类型,其他数据放在缓冲区的消息中其他正文 区内.下面是消息元

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1