📄 00000019.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: mry (木日), 信区: Linux <BR>标 题: 多进程编程 <BR>发信站: BBS 水木清华站 (Thu Nov 18 21:04:41 1999) <BR> <BR>多谢bug2k提供的网址 <BR>===================================================== <BR> <BR>多进程编程 <BR>写在前面的话 <BR> 本文主要根据本人在UNIX系统上的编程实践经验总结而成, 既做为自己在 <BR>一个时期内编程实践的部分总结, 又可成为文章发表. 对UNIX程序员初学者来 <BR>说是一个小小的经验, 仅供参考; 对UNIX老手来说则不值一哂, 请各位多多指 <BR>教. <BR>一.多进程程序的特点 <BR> 由于UNIX系统是分时多用户系统, CPU按时间片分配给各个用户使用, 而在 <BR>实质上应该说CPU按时间片分配给各个进程使用, 每个进程都有自己的运行环境 <BR>以使得在CPU做进程切换时不会"忘记"该进程已计算了一半的"半成品". 以DOS <BR>的概念来说, 进程的切换都是一次"DOS中断"处理过程, 包括三个层次: <BR> (1)用户数据的保存: 包括正文段(TEXT), 数据段(DATA,BSS), 栈段 <BR> (STACK), 共享内存段(SHARED MEMORY)的保存. <BR> (2)寄存器数据的保存: 包括PC(program counter,指向下一条要执行的指 <BR> 令的地址), PSW(processor status word,处理机状态字), SP(stack <BR> pointer,栈指针), PCBP(pointer of process control block,进程控 <BR> 制块指针), FP(frame pointer,指向栈中一个函数的local变量的首地 <BR> 址), AP(augument pointer,指向栈中函数调用的实参位置), ISP( <BR> interrupt stack pointer,中断栈指针), 以及其他的通用寄存器等. <BR> (3)系统层次的保存: 包括proc,u,虚拟存储空间管理表格,中断处理栈. <BR>以便于该进程再一次得到CPU时间片时能正常运行下去. <BR> 既然系统已经处理好所有这些中断处理的过程, 我们做程序还有什么要担 <BR>心的呢? 我们尽可以使用系统提供的多进程的特点, 让几个程序精诚合作, 简 <BR>单而又高效地把结果给它搞出来. <BR> 另外,UNIX系统本身也是用C语言写的多进程程序,多进程编程是UNIX的特 <BR>点,当我们熟悉了多进程编程后,将会对UNIX系统机制有一个较深的认识. <BR> 首先我介绍一下多进程程序的一些突出的特点: <BR> 1.并行化 <BR> 一件复杂的事件是可以分解成若干个简单事件来解决的, 这在程序员 <BR> 的大脑中早就形成了这种概念, 首先将问题分解成一个个小问题, 将小问 <BR> 题再细分, 最后在一个合适的规模上做成一个函数. 在软件工程中也是这 <BR> 么说的. 如果我们以图的方式来思考, 一些小问题的计算是可以互不干扰 <BR> 的, 可以同时处理, 而在关键点则需要统一在一个地方来处理, 这样程序 <BR> 的运行就是并行的, 至少从人的时间观念上来说是这样的. 而每个小问题 <BR> 的计算又是较简单的. <BR> 2.简单有序 <BR> 这样的程序对程序员来说不亚于管理一班人, 程序员为每个进程设计 <BR> 好相应的功能, 并通过一定的通讯机制将它们有机地结合在一起, 对每个 <BR> 进程的设计是简单的, 只在总控部分小心应付(其实也是蛮简单的), 就可 <BR> 完成整个程序的施工. <BR> 3.互不干扰 <BR> 这个特点是操作系统的特点, 各个进程是独立的, 不会串位. <BR> 4.事务化 <BR> 比如在一个数据电话查询系统中, 将程序设计成一个进程只处理一次 <BR> 查询即可, 即完成一个事务. 当电话查询开始时, 产生这样一个进程对付 <BR> 这次查询; 另一个电话进来时, 主控程序又产生一个这样的进程对付, 每 <BR> 个进程完成查询任务后消失. 这样的编程多简单, 只要做一次查询的程序 <BR> 就可以了. <BR>二.常用的多进程编程的系统调用 <BR> 1.fork() <BR> 功能:创建一个新的进程. <BR> 语法:#include <unistd.h> <BR> #include <sys/types.h> <BR> pid_t fork(); <BR> 说明:本系统调用产生一个新的进程, 叫子进程, 是调用进程的一个复 <BR> 制品. 调用进程叫父进程, 子进程继承了父进程的几乎所有的属 <BR> 性: <BR> . 实际UID,GID和有效UID,GID. <BR> . 环境变量. <BR> . 附加GID. <BR> . 调用exec()时的关闭标志. <BR> . UID设置模式比特位. <BR> . GID设置模式比特位. <BR> . 进程组号. <BR> . 会话ID. <BR> . 控制终端. <BR> . 当前工作目录. <BR> . 根目录. <BR> . 文件创建掩码UMASK. <BR> . 文件长度限制ULIMIT. <BR> . 预定值, 如优先级和任何其他的进程预定参数, 根据种类不同 <BR> 决定是否可以继承. <BR> . 还有一些其它属性. <BR> 但子进程也有与父进程不同的属性: <BR> . 进程号, 子进程号不同与任何一个活动的进程组号. <BR> . 父进程号. <BR> . 子进程继承父进程的文件描述符或流时, 具有自己的一个拷贝 <BR> 并且与父进程和其它子进程共享该资源. <BR> . 子进程的用户时间和系统时间被初始化为0. <BR> . 子进程的超时时钟设置为0. <BR> . 子进程的信号处理函数指针组置为空. <BR> . 子进程不继承父进程的记录锁. <BR> 返回值: 调用成功则对子进程返回0, 对父进程返回子进程号, 这也是 <BR> 最方便的区分父子进程的方法. 若调用失败则返回-1给父进程, <BR> 子进程不生成. <BR> 例子:pid_t pid; <BR> if ((pid=fork())>0) { <BR> /*父进程处理过程*/ <BR> } <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -