《Linux内核与编程学习教案》由会员分享,可在线阅读,更多相关《Linux内核与编程学习教案(37页珍藏版)》请在金锄头文库上搜索。
1、会计学1Linux内核内核(ni h)与编程与编程第一页,共37页。提纲提纲(tgng)结束(jish)n n进程间通信概述进程间通信概述n n目标问题目标问题哲学家进餐问题哲学家进餐问题n n问题描述问题描述n n错误与不好的解法错误与不好的解法n n并行度较高的解法并行度较高的解法n nLinuxLinux高级高级IPCIPC机制机制n n概述概述n nSystem VSystem V信号灯信号灯n nSystem VSystem V共享内存区共享内存区n n实现的其他实现的其他(qt)(qt)问题问题n n实习题实习题第1页/共36页第二页,共37页。进程间通信概述进程间通信概述(i s
2、h)(1):):引子引子#include #include #include #include int result;int result;main()main() pid_t pid; pid_t pid; result=0; result=0; pid=fork(); pid=fork(); if(pid0) exit(-1); if(pid0) exit(-1);if(pid) pid=fork(); if(pid0) exit(-1); if(pid=0) sleep(3); result=result+20; exit(0); else sleep(3); result=result
3、+10; exit(0); while(wait(int*)0)!=-1); printf(%dn, result); exit(0);输出输出(shch)结果是什么?结果是什么?第2页/共36页第三页,共37页。进程进程(jnchng)间通信概述间通信概述(2)n n进程是相互独立的,进程间的通信需要专门的机制。n n进程之间的通信可以经由文件系统,但实际使用较为(jio wi)复杂(例如,需要锁机制)。n nUNIX IPC (InterProcess Communication)机制是各种进程通信方式的统称。n nLinux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的
4、。第3页/共36页第四页,共37页。进程进程(jnchng)间通信概述间通信概述(3)n n对于UNIX的发展,贝尔实验室和BSD在进程间通信方面(fngmin)的侧重点有所不同:n n贝尔实验室对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“System V IPC”,通信进程局限在单个计算机内;n nBSD则主要考虑跨计算机的进程间通信,形成了基于套接口(socket)的进程间通信机制。第4页/共36页第五页,共37页。进程进程(jnchng)间通信概述间通信概述(4)返回(fnhu)最初的最初的UNIX IPCSystem V IPC基于基于Socket的的IPCLinux
5、 IPCPOSIX IPC最初的最初的Unix IPC:信号、管道:信号、管道(gundo)、FIFO;System V IPC:消息队列、信号量、共享内存区;:消息队列、信号量、共享内存区;POSIX IPC:消息队列、信号量、共享内存区。:消息队列、信号量、共享内存区。 第5页/共36页第六页,共37页。哲学家进餐问题哲学家进餐问题(wnt)的描述的描述n n五个哲学家围坐在一张圆桌周围,每个五个哲学家围坐在一张圆桌周围,每个哲学家面前都有一碗米饭,相邻的两碗哲学家面前都有一碗米饭,相邻的两碗之间有一支筷子(如图)。之间有一支筷子(如图)。n n哲学家的生活包含两种活动:即吃饭和哲学家的生
6、活包含两种活动:即吃饭和思考。当一个哲学家觉得饿时,他就试思考。当一个哲学家觉得饿时,他就试图分两次去取他左边和右边的筷子,每图分两次去取他左边和右边的筷子,每次拿起一支,但不分次序次拿起一支,但不分次序(cx)(cx)。如果。如果成功地获得了一双筷子,他就开始吃饭,成功地获得了一双筷子,他就开始吃饭,吃完以后放下筷子继续思考。这样,问吃完以后放下筷子继续思考。这样,问题就是,为每个哲学家写一段程序来描题就是,为每个哲学家写一段程序来描述其行为,要求不死锁。述其行为,要求不死锁。返回(fnhu)第6页/共36页第七页,共37页。错误错误(cuw)与不好的解法(与不好的解法(1)n n解法解法(
7、ji f(ji f ) )一:可能进入一:可能进入“ “死锁死锁” ”状态状态#define N 5void philosopher(int i) while(TRUE) think(); take-chopstick(i); take-chopstick(i+1)%N); eat(); put-chopstick(i); put-chopstick(i+1)%N); 若每个哲学家进程若每个哲学家进程都运行到此句后发都运行到此句后发生进程切换,则进生进程切换,则进入死锁。入死锁。第7页/共36页第八页,共37页。错误错误(cuw)与不好的解法(与不好的解法(2)#define N 5#defi
8、ne N 5void philosopher(int i)void philosopher(int i) while(TRUE) while(TRUE) think(); think(); do do take-chopstick(i); take-chopstick(i); if(can-take-chopstick(i+1)%N) break; if(can-take-chopstick(i+1)%N) break; else put-chopstick(i); else put-chopstick(i); while(TRUE); while(TRUE); eat(); eat(); p
9、ut-chopstick(i);put-chopstick(i+1)%N); put-chopstick(i);put-chopstick(i+1)%N); 解法解法(ji f)二:可能进入二:可能进入“饥饿饥饿”状态状态不妨假设此函数能做不妨假设此函数能做到到“测试且设置测试且设置”。这种解法可能会造成下面情况:这种解法可能会造成下面情况:哲学家们不断地重复哲学家们不断地重复“拿起各自左边拿起各自左边的筷子又放下的筷子又放下”的动作的动作(dngzu),谁,谁也不能进餐。注意:这时和解法一的也不能进餐。注意:这时和解法一的状态不同,这时进程都没有阻塞。状态不同,这时进程都没有阻塞。第8页/共
10、36页第九页,共37页。错误与不好错误与不好(b ho)的解法(的解法(3)#define N 5#define N 5typedef int semaphore;typedef int semaphore;semaphore mutex=1;semaphore mutex=1;void philosopher(int i)void philosopher(int i) while(TRUE) while(TRUE) think(); think(); down(mutex); down(mutex); take-chopstick(i); take-chopstick(i+1)%N); ta
11、ke-chopstick(i); take-chopstick(i+1)%N); eat(); eat(); put-chopstick(i); put-chopstick(i+1)%N); put-chopstick(i); put-chopstick(i+1)%N); up(mutex); up(mutex); 返回(fnhu)解法三:可行但效率解法三:可行但效率(xio l)低下低下本解法从理论上可行,本解法从理论上可行,但从实际角来看,有一局限但从实际角来看,有一局限性:同一时刻只能有一位哲性:同一时刻只能有一位哲学家进餐。而这里有五支筷学家进餐。而这里有五支筷子,实际上应能允许两位哲
12、子,实际上应能允许两位哲学家同时进餐。学家同时进餐。第9页/共36页第十页,共37页。并行度较高的解法并行度较高的解法(ji f)(1)#define N#define N 5 5#define LEFT#define LEFT (i+N-1)%N (i+N-1)%N#define RIGHT#define RIGHT (i+1)%N (i+1)%N#define THINKING#define THINKING 0 0#define HUNGRY#define HUNGRY 1 1#define EATING#define EATING 2 2typedef int semaphore;ty
13、pedef int semaphore;int stateN;int stateN;semaphore mutex=1;semaphore mutex=1;semaphore sN;semaphore sN; void philosopher(int i) while(TRUE) think(); take-chopsticks(i); eat(); put-chopsticks(i); 第10页/共36页第十一页,共37页。并行度较高的解法并行度较高的解法(ji f)(2)返回(fnhu)void put-chopsticks(int i) down(&mutex); statei=THIN
14、KING; test(LEFT); test(RIGHT); up(&mutex);void test(i) if(statei=HUNGRY &stateLEFT!=EATING&stateRIGHT!=EATING) statei=EATING;up(&si); void take-chopsticks(int i) down(&mutex); statei=HUNGRY; test(i); up(&mutex); down(&si);第11页/共36页第十二页,共37页。概述概述(i sh)n nSystem V IPCSystem V IPC包含了三种机制,在实现包含了三种机制,在实现
15、“ “哲学家进餐哲学家进餐(jn cn)(jn cn)问题问题” ”时,我们只使时,我们只使用信号灯机制和共享存储区机制。主要的函数如下:用信号灯机制和共享存储区机制。主要的函数如下:n n信号灯信号灯共享内存区共享内存区n n头文件头文件n n创建或打开创建或打开IPCIPCsemgetsemgetshmgetshmgetn n控制控制IPCIPC操作操作semctlsemctlshmctlshmctln nIPCIPC操作函数操作函数semopsemopshmat, shmdtshmat, shmdtn nSystem V IPCSystem V IPC对象以对象以key_tkey_t类型
16、的值作为其名字。类型的值作为其名字。n nSystem V IPCSystem V IPC对象以一定的存取权限来控制其访问。对象以一定的存取权限来控制其访问。返回(fnhu)第12页/共36页第十三页,共37页。System V IPC的名字的名字(mng zi)n nSystem V IPCSystem V IPC是有名是有名(y (y u mng)u mng)的,这样可以支持无亲缘关系的进程的,这样可以支持无亲缘关系的进程访问同一的访问同一的IPCIPC对象。其名字的类型为对象。其名字的类型为key_tkey_t,可以由,可以由ftokftok函数赋予或函数赋予或直接取值直接取值IPC_P
17、RIVATEIPC_PRIVATE。n nftokftok函数函数n n原型:原型:#include #include #include #include key_t ftok(const char * pathname, int id);key_t ftok(const char * pathname, int id);n n功能:把已存在的路径名和一整数标识符转换成一个功能:把已存在的路径名和一整数标识符转换成一个key_tkey_t值,称为值,称为IPCIPC键。键。n n返回值:成功时返回返回值:成功时返回IPCIPC键,出错返回键,出错返回-1-1。n n说明:说明:1 1、ftok
18、ftok产生的键值不会是产生的键值不会是IPC_PRIVATEIPC_PRIVATE;2 2、不能保证、不能保证ftokftok生成的键值唯一;生成的键值唯一;3 3、用于产生键的文件不能在该、用于产生键的文件不能在该IPCIPC对象存活其对象存活其内删除。内删除。返回(fnhu)第13页/共36页第十四页,共37页。System V IPC对象对象(duxing)的存的存取权限取权限n n为防止共享的为防止共享的IPCIPC对象被非法访问,必须为对象被非法访问,必须为IPCIPC对象设置存取权限。对象设置存取权限。n nSystem V IPCSystem V IPC对象的存取权限和文件系统
19、中文件的存取权限类似,对象的存取权限和文件系统中文件的存取权限类似,也用也用9 9位分位分3 3组表示,三组分别代表属主、组成员和其他用户对该组表示,三组分别代表属主、组成员和其他用户对该IPCIPC对象的存取权限;每组中三位,只用其中的两位表示是否可读对象的存取权限;每组中三位,只用其中的两位表示是否可读和是否可写。一般为了安全和是否可写。一般为了安全(nqun)(nqun),在创建,在创建IPCIPC对象时应该设置对象时应该设置存取权限制为存取权限制为06000600,表示仅仅对属主是可读,可写的。,表示仅仅对属主是可读,可写的。返回(fnhu)第14页/共36页第十五页,共37页。Sys
20、tem V信号灯信号灯n nsemgetn nsemctln nsemopn ndown和up的实现(shxin)返回(fnhu)第15页/共36页第十六页,共37页。semget(1)函数函数(hnsh)说明说明n n原型:原型:#include #include #include #include #include #include int semget(key_t key, int nsems, int oflag);int semget(key_t key, int nsems, int oflag);n n功能:创建或打开信号灯集合。功能:创建或打开信号灯集合。n n返回值:成功返回
21、非负信号灯标识符,出错返回返回值:成功返回非负信号灯标识符,出错返回-1-1。n n说明:说明:1 1、keykey是欲创建或打开的信号灯集合的名字;是欲创建或打开的信号灯集合的名字;n n2 2、nsemsnsems指明信号灯集合中包含的信号灯数;指明信号灯集合中包含的信号灯数;n n3 3、oflagoflag是一个位信息标志是一个位信息标志(biozh)(biozh),含两部分信,含两部分信息,即存息,即存取权限和控制字段。低取权限和控制字段。低9 9位表示存取权限,控位表示存取权限,控制字段中制字段中IPC_CREATIPC_CREAT位和位和IPC_EXCLIPC_EXCL位的设位的
22、设置情况与参数置情况与参数keykey共同决定了本调用的操作。共同决定了本调用的操作。第16页/共36页第十七页,共37页。semget(2)工作工作(gngzu)流流程程if (key=IPC_PRIVATE)if (key=IPC_PRIVATE) 创建新信号灯集并返回其创建新信号灯集并返回其id;id;else if (else if (与与keykey相关相关(xinggun)(xinggun)的信号灯集合存在的信号灯集合存在) ) if (oflag&IPC_CREAT)&(oflag&IPC_EXCL) if (oflag&IPC_CREAT)&(oflag&IPC_EXCL) 返
23、回返回-1;-1; else if ( else if (访问权限允许访问权限允许) ) 返回与返回与keykey相关相关(xinggun)(xinggun)的信号灯集的信号灯集id;id; else else 返回返回-1;-1;else if (oflag&IPC_CREAT)else if (oflag&IPC_CREAT) 创建新信号灯集并返回其创建新信号灯集并返回其id;id;elseelse 返回返回-1;-1;返回(fnhu)第17页/共36页第十八页,共37页。semctl(1)函数函数(hnsh)说明说明n n原型:原型:#include #include #include
24、#include #include #include int semctl(int semid, int semnum, int cmd,int semctl(int semid, int semnum, int cmd, union semun arg); union semun arg);n n功能:对功能:对semidsemid标识的信号灯集合进行控制。标识的信号灯集合进行控制。n n返回返回(f (f nhu)nhu)值:成功返回值:成功返回(f (f nhu)nhu)非负值,出错返回非负值,出错返回(f (f nhu)-1nhu)-1。n n说明:说明:1 1、cmdcmd是对信号灯
25、集的控制命令,有是对信号灯集的控制命令,有GETVALGETVAL, SETVAL SETVAL,GETALLGETALL,SETALLSETALL,IPC_RMIDIPC_RMID 等,我们只用最后的两个。等,我们只用最后的两个。2 2、semnumsemnum标识该信号灯集中某成员(以标识该信号灯集中某成员(以0 0为第为第 一个),仅用于一个),仅用于GETVALGETVAL,SETVALSETVAL等命令。等命令。3 3、argarg是可选的,取决于参数是可选的,取决于参数cmdcmd,GETALLGETALL或或 SETALL SETALL等命令就要用到参数等命令就要用到参数arga
26、rg。第18页/共36页第十九页,共37页。semctl(2)union semunn nunion semununion semun的定义为:的定义为:union semununion semun int val; int val;/仅用于仅用于SETVALSETVAL命令命令 struct semid_ds * buf; struct semid_ds * buf;/用于用于IPC_SETIPC_SET等命令等命令 ushort * array; ushort * array;/用于用于SETALLSETALL等命令等命令 n n注意,本联合未在出现在任何系统头文件中,因此必须注意,本联合
27、未在出现在任何系统头文件中,因此必须(bx)(bx)由应用程序声明。由应用程序声明。返回(fnhu)第19页/共36页第二十页,共37页。semop(1)函数函数(hnsh)说明说明n n原型:原型:#include #include #include #include #include #include int semop(int semid,int semop(int semid, struct sembuf * opsptr, struct sembuf * opsptr, size_t nops); size_t nops);n n功能功能(gngnng)(gngnng):对:对sem
28、idsemid标识的信号灯集合中信号灯进行操作。标识的信号灯集合中信号灯进行操作。n n返回值:成功返回返回值:成功返回0 0,出错返回,出错返回-1-1。n n说明:说明:1 1、opsptropsptr是指向结构是指向结构struct sembufstruct sembuf的指针,可的指针,可 以是这种类型的结构数组的头指针。数组的每以是这种类型的结构数组的头指针。数组的每 个元素包含对信号灯集合中一个信号的的操作个元素包含对信号灯集合中一个信号的的操作 的信息,从而可实现同时对多信号灯的操作。的信息,从而可实现同时对多信号灯的操作。2 2、nopsnops指出指出opsptropsptr
29、指向的结构数组中元素数。指向的结构数组中元素数。第20页/共36页第二十一页,共37页。semop(2)struct sembufn nstruct sembufstruct sembuf的定义为:的定义为:struct sembufstruct sembuf short sem_num; short sem_num; /信号灯号:信号灯号:0,1,nsems-10,1,nsems-1 short sem_op; short sem_op;/信号灯操作:信号灯操作:00 short sem_flg; short sem_flg;/操作标识:这里我们操作标识:这里我们(w(w men) men)
30、只要置只要置0 0 n nsem_opsem_op不同值对应的操作(设信号灯当前值为不同值对应的操作(设信号灯当前值为svsv):):n nsem-op0sem-op=abs (sem_op)start: if (sv=abs (sem_op) sv=sv-abs(sem_op); sv=sv-abs(sem_op); else sleep; goto start; else sleep; goto start;n nsem_op0sem_op0:sv=sv+sem_op; sv=sv+sem_op; 唤醒所有阻塞于该信号量的进程唤醒所有阻塞于该信号量的进程; ;n nsem_op=0sem_
31、op=0:测试:测试svsv是否为是否为0 0。返回(fnhu)第21页/共36页第二十二页,共37页。down和和up的实现的实现(shxin)void down(int sid, int sn)void down(int sid, int sn) struct sembuf op; struct sembuf op; op.sem_num=sn; op.sem_num=sn; op.sem_op=-1; op.sem_op=-1; op.sem_flg=0; op.sem_flg=0; semop(sid, &op, 1); semop(sid, &op, 1); void up(int
32、sid, int sn) struct sembuf op; op.sem_num=sn; op.sem_op=1; op.sem_flg=0; semop(sid, &op, 1);返回(fnhu)第22页/共36页第二十三页,共37页。System V共享内存区共享内存区n nshmgetn nshmctln nshmat和shmdtn n使用(shyng)共享内存区的一般流程返回(fnhu)第23页/共36页第二十四页,共37页。shmgetn n原型:原型:#include #include #include #include #include #include int shmget(
33、key_t key, size_t size, int oflag);int shmget(key_t key, size_t size, int oflag);n n功能:创建或打开共享内存功能:创建或打开共享内存(ni cn)(ni cn)区。区。n n返回值:成功返回非负内存返回值:成功返回非负内存(ni cn)(ni cn)区标识符,出错返回区标识符,出错返回-1-1。n n说明:说明:1 1、sizesize指明共享内存指明共享内存(ni cn)(ni cn)区大小(字节为单位);区大小(字节为单位);2 2、keykey和和oflagoflag的说明基本和的说明基本和semgets
34、emget相同;相同;3 3、打开或创建一个共享内存、打开或创建一个共享内存(ni cn)(ni cn)区,并没提供调用进区,并没提供调用进 程访问该内存程访问该内存(ni cn)(ni cn)区的手段。必须调用区的手段。必须调用shmatshmat。返回(fnhu)第24页/共36页第二十五页,共37页。shmctln n原型:原型:#include #include #include #include #include #include int shmctl(int shmid, int cmd,int shmctl(int shmid, int cmd, struct shmid_ds
35、*buff); struct shmid_ds *buff);n n功能:对功能:对shmidshmid标识的共享内存区进行控制。标识的共享内存区进行控制。n n返回值:成功返回返回值:成功返回0 0,出错返回,出错返回-1-1。n n说明:说明:1 1、参数、参数cmdcmd是对共享内存区的控制命令,可以是是对共享内存区的控制命令,可以是 IPC_RMID IPC_RMID,IPC_SETIPC_SET或或IPC_STATIPC_STAT,我们,我们(w(w men) men)仅仅 用第一个;用第一个;2 2、buffbuff主要用于命令主要用于命令IPC_SETIPC_SET和和IPC_S
36、TATIPC_STAT,命,命 令为令为IPC_RMIDIPC_RMID时可直接提供时可直接提供NULLNULL;返回(fnhu)第25页/共36页第二十六页,共37页。shmat和和shmdtn n原型:原型:#include #include #include #include #include #include void * shmat(int shmid,void * shmat(int shmid, const void * shmaddr, const void * shmaddr, int flag); int flag);int shmdt(const void * shmad
37、dr);int shmdt(const void * shmaddr);n n功能:功能:shmatshmat用于将一个打开的共享内存区附接到调用进程的地址空间。用于将一个打开的共享内存区附接到调用进程的地址空间。shmdtshmdt用于切断这个内存区域。用于切断这个内存区域。n n返回值:出错返回返回值:出错返回-1-1,shmatshmat成功返回映射区的起始地址而成功返回映射区的起始地址而shmdtshmdt成功时候返回成功时候返回0 0。n n说明:说明:shmatshmat中中shmaddrshmaddr和和flagflag可用来影响映射区起始地址的选取。一般可用来影响映射区起始地址
38、的选取。一般(ybn)(ybn)应该分别提供应该分别提供NULLNULL和和0 0。返回(fnhu)第26页/共36页第二十七页,共37页。使用使用(shyng)共享内存区的一共享内存区的一般流程般流程n n使用使用System VSystem V共享内存区时的一般流程:共享内存区时的一般流程:n n用用shmgetshmget创建或打开一个创建或打开一个(y (y ) )共享内存区共享内存区n n用用shmatshmat将打开的共享内存区附接到进程地址空将打开的共享内存区附接到进程地址空间间n n对共享内存区进行操作对共享内存区进行操作n n用用shmdtshmdt切断共享内存区与本进程地址
39、空间的联切断共享内存区与本进程地址空间的联系系n n用用shmctlshmctl拆除共享内存区(用命令拆除共享内存区(用命令IPC_RMIDIPC_RMID)返回(fnhu)第27页/共36页第二十八页,共37页。实现的其他实现的其他(qt)问题问题n n如何创建多个进程n n创建一个进程链n n创建一个进程扇n n创建一个进程树n n程序的结束(jish)n n程序失败后如何释放资源返回(fnhu)第28页/共36页第二十九页,共37页。创建创建(chungjin)一个进程链一个进程链#define N 4#define N 4#include #include #include #incl
40、ude #include #include main()main() int i; int i; for (i=1;iN;+i) for (i=1;iN;+i) if (fork() break; if (fork() break; fprintf(stderr, #%d is process %ld with parent %ldn, fprintf(stderr, #%d is process %ld with parent %ldn, i, (long)getpid(), (long)getppid(); i, (long)getpid(), (long)getppid(); 注意:本程
41、序未考虑注意:本程序未考虑forkfork失败失败(shbi)(shbi)的情况。的情况。1234返回(fnhu)第29页/共36页第三十页,共37页。创建创建(chungjin)一个进程扇一个进程扇#define N 4#define N 4#include #include #include #include #include #include main()main() int i; int i; for (i=1;iN;+i) for (i=1;iN;+i) if (fork()=0) break; if (fork()=0) break; fprintf(stderr, #%d is
42、process %ld with parent %ldn, fprintf(stderr, #%d is process %ld with parent %ldn, i, (long)getpid(), (long)getppid(); i, (long)getpid(), (long)getppid(); 注意:本程序注意:本程序(chngx)(chngx)未考虑未考虑forkfork失败的情况。失败的情况。1234返回(fnhu)第30页/共36页第三十一页,共37页。创建一个创建一个(y )进程树进程树#define N 4#define N 4#include #include #in
43、clude #include #include #include main()main() int i, id=0; int i, id=0; for (i=1;iN;+i) for (i=1;iN;+i) if (fork()=0) id=i; if (fork()=0) id=i; fprintf(stderr, #%d is process %ld with parent %ldn, fprintf(stderr, #%d is process %ld with parent %ldn, id, (long)getpid(), (long)getppid(); id, (long)get
44、pid(), (long)getppid(); 注意注意(zh y)(zh y):本程序未考虑:本程序未考虑forkfork失败的情况。失败的情况。02a13a3b3c3d2b返回(fnhu)第31页/共36页第三十二页,共37页。程序程序(chngx)的结束的结束n n在什么时机结束程序(chngx)n n以某个外部文件的存在与否来决定:每个哲学家在“吃”完后都检测某个特定的文件(例如:/quit)是否已经被创建。若是则结束程序(chngx)。n n利用信号(signal)截取键盘Ctrl-C信号。n n程序(chngx)结束时候要记得回收IPC资源返回(fnhu)第32页/共36页第三十三
45、页,共37页。程序失败后如何程序失败后如何(rh)释放资源释放资源n n杀掉垃圾进程n n使用ps ax查看所有进程n n使用killall name进行删除(shnch)n n删除(shnch)垃圾IPC资源n n使用ipcs -a查看所有IPC资源n n使用ipcrm shm|sem id进行删除(shnch)返回(fnhu)第33页/共36页第三十四页,共37页。实习实习(shx)题题n n理解实现进程通信的难点n n练习创建多个进程的方法n n解决哲学家进餐问题n n实现不好的或有错误的算法,观察运行情况n n实现正确(zhngqu)的算法(需要检查)n n也实现其他方法返回(fnhu
46、)第34页/共36页第三十五页,共37页。iQfNcK8H5E2A+x*u$rZnWkThPeMaJ7G4C1z-w&t!pYmVjRgOdL9I6E3B0y(v%s#oXlTiQfNbK8H5D2A+x*u$qZnWkShPeMaJ7F4C1z)w&t!pYmUjRgOcL9I6E3B+y(v%r#oXlTiQeNbK8G5D2A-x*t$qZnVkShPdMaI7F4C0z)w&s!pXmUjRfOcL9H6E3B+y(u%r#oWlTiQeNbJ8G5D1A-x*t$qYnVkSgPdMaI7F3C0z)v&s!pXmUiRfOcK9H6E2B+x(u%rZoWlThQeMbJ8G4D1
47、A-w*t$qYnVjSgPdLaI7F3C0y)v&s#pXmUiRfNcK9H5E2B+x(u$rZoWkThQeMbJ7G4D1z-w*t!qYmVjSgOdLaI6F3B0y)v%s#pXlUiQfNcK8H5E2A+x(u$rZnWkThPeMbJ7G4C1z-w&t!qYmVjRgOdL9I6F3B0y(v%s#oXlUiQfNbK8H5D2A+x*u$qZnWkShPeMaJ7F4C1z)w&t!pYmVjRgOcL9I6E3B0y(v%r#oXlTiQfNbK8G5D2A-x*u$qZnVkShPdMaJ7F4C0z)w&s!pYmUjRfOcL9H6E3B+y(u%r#oWl
48、TiQeNbK8G5D1A-x*t$qZnVkSgPdMaI7F4C0z)v&s!pXmUjRfOcK9H6E2B+y(u%rZoWlThQeNbJ8G4D1A-s!pYmUjRfOcL9H6E3B+y(v%r#oWlTiQeNbK8G5D1A-x*t$qZnVkSgPdMaI7F4C0z)v&s!pXmUjRfOcK9H6E2B+y(u%rZoWlThQeNbJ8G4D1A-w*t$qYnVkSgPdLaI7F3C0z)v&s#pXmUiRfOcK9H5E2B+x(u%rZoWkThQeMbJ8G4D1z-w*t!qYnVjSgOdLaI6F3C0y)v%s#pXlUiRfNcK8H5E2A
49、+x(u$rZoWkThPeMbJ7G4D1z-w&t!qYmVjSgOdL9I6F3B0y)v%s#oXlUiQfNcK8H5D2A+x*u$rZnWkShPeMaJ7G4C1z)w&t!pYmVjRgOdL9I6E3B0y(v%s#oXlTiQfNbK8H5D2A-x*u$qZnWkShPdMaJ7F4C1z)w&s!pYmUjRgOcL9H6E3B+y(v%r#oWlTiQeNbK8G5D2A-x*t$qZnVkShPdMaI7F4C0z)w&s!pXmUjRfOcL9H6E2B+y(u%r#oWlThQeNbJ8G5D1A-w*t$qYnVkSgPdLaI7F3C0z)v&s#pXmU
50、iRfOcK9H6E2B+x(u%rZoWlThQeMbJ8G4D1A-w*t!qYnVjSgPdLaI6F3C0y)v&s#pXlUiRfNcK9H5E2A+x(u$rZoWkThPeMbJ7G4D1z-w*t!qYmVjSgOdLaI6F3B0y)v%s#pXlUiQfNcK8H5E2A+x*u$rZnWkThPeI6F3C0y)v&s#pXlUiRfNcK9H5E2A+x(u$rZoWkThQeMbJ7G4D1z-w*t!qYmVjSgOdLaI6F3B0y)v%s#pXlUiQfNcK8H5E2A+x*u$rZnWkThPeMaJ7G4C1z-w&t!pYmVjRgOdL9I6F3B0
51、y(v%s#oXlUiQfNbK8H5D2A+x*u$qZnWkShPeMaJ7F4C1z)w&t!pYmUjRgOcL9I6E3B+y(v%r#oXlTiQeNbK8G5D2A-x*u$qZnVkShPdMaJ7F4C0z)w&s!pYmUjRfOcL9H6E3B+y(u%r#oWlTiQeNbJ8G5D1A-x*t$qYnVkSgPdMaI7F3C0z)v&s!pXmUiRfOcK9H6E2B+y(u%rZoWlThQeNbJC0z)w&s!pYmUjRfOcL9H6E3B+y(u%r#oWlTiQeNbJ8G5D1A-x*t$qYnVkSgPdMaI7F4C0z)v&s!pXmUjRfO
52、cK9H6E2B+y(u%rZoWlThQeNbJ8G4D1A-w*t$qYnVjSgPdLaI7F3C0y)v&s#pXmUiRfNcK9H5E2B+x(u$rZoWkThQeMbJ8G4D1z-w*t!qYnVjSgOdLaI6F3C0y)v%s#pXlUiRfNcK8H5E2A+x(u$rZnWkThPeMbJ7G4C1z-w&t!qYmVjRgOdL9I6F3B0y)v%s#oXlUiQfNcK8H5D2A+x*u$rZnWkShPeMaJ7G4C1z)w&t!pYmVjRgOcL9I6E3B0y(v%r#oXlTiQfNbK8G5D2A-x*u$qZnWkShPdMaJ7F4C1z)
53、w&s!pYmUjRgOcL9H6E3B+y(v%r#oWlTiQeNbK8G5D1A-x*t$qZnVkSgPdMaI7F4C0z)v&s!pXmUjRfOcK9H6E2B+y(u%r#oWlThQeNbJ8G5D1A-s!pYmUjRgOcL9H6E3B+y(v%r#oWlTiQeNbK8G5D1A-x*t$qZnVkSgPdMaI7F4C0z)w&s!pXmUjRfOcL9H6E2B+y(u%r#oWlThQeNbJ8G5D1A-w*t$qYnVkSgPdLaI7F3C0z)v&s#pXmUiRfOcK9H5E2B+x(u%rZoWkThQeMbJ8G4D1A-w*t!qYnVjSgPd
54、LaI6F3C0y)v&s#pXlUiRfNcK9H5E2A+x(u$rZoWkdLaI7F3C0z)v&s#pXmUiRfOcK9H6E2B+x(u%rZoWlThQeMbJ8G4D1A-w*t!qYnVjSgPdLaI6F3C0y)v&s#pXlUiRfNcK9H5E2A+x(u$rZoWkThPeMbJ7G4D1z-w&t!qYmVjSgOdLaI6F3B0y)v%s#pXlUiQfNcK8H5E2A+x*u$rZnWkThPeMaJ7G4C1z-w&t!pYmVjRgOdL9I2A+x(u$rZoWkThQeMbJ7G4D1z-w*t!qYmVjSgOdLaI6F3B0y)v%s#pX
55、lUiQfNcK8H5E2A+x*u$rZnWkThPeMaJ7G4C1z-w&t!pYmVjRgOdL9I6E3B0y(v%s#oXlUiQfNbK8H5D2A+x*u$qZnWkShPeMaJ7F4C1z)w&t!UiQfNcK8H5E2A+x*u$rZnWkThPeMaJ7G4C1z-w&t!qYmVjRgOdL9I6F3B0y(v%s#oXlUiQfNbK8H5D2A+x*u$qZnWkShPeMaJ7F4C1z)w&t!pYmUjRgOcL9I6E3B+y(v%r#oXlTiQfNbK8G5D2A-x*u$qZnVkShPdMaJ7F0y(v%s#oXlUiQfNbK8H5D2A+x
56、*u$qZnWkShPeMaJ7F4C1z)w&t!pYmUjRgOcL9I6E3B0y(v%r#oXlTiQfNbK8G5D2A-x*u$qZnVkShPdMaJ7F4C0z)w&s!pYmUjRfOcL9H6E3B+y(u%r#oWlTiQeNbJ8G5D1A-x*t$qZnVkSgPdMaI7F4C0z)v&s!pXmUjRfOcK9H6E2B+y(u%rZoWlThQeNbJ8G4D1A-w*t$qYnVjSgPdLaI7F3C0y)v&s#pXmUiRfNcK9H5E2B+x(u%rZoWkThQeMbJ8G4D1z-w*t!qYnVjSgOdLaI6F3C0y)v%s#pXlUiR
57、fNcK8H5E2A+x(u$rZnWkThPeMbJ7G4C1z-w&t!qYmVjSgOdL9I6F3B0y)v%s#oXlUiQfNcK8H5D2A+x*u$rZnWkShPeMaJ7G4C1z)w&t!pYmVjRgOcL9I6E3B0y(v%r#oXlTiQfNbK8G5D-w&t!qYmVjSgOdL9I6F3B0y)v%s#oXlUiQfNcK8H5D2A+x*u$rZnWkShPeMaJ7G4C1z)w&t!pYmVjRgOcL9I6E3B0y(v%s#oXlTiQfNbK8H5D2A-x*u$qZnWkShPdMaJ7F4C1z)w&s!pYmUjRgOcL9H6E3B+y(
58、v%r#oWlTiQeNbK8G5D1A-x*t$qZnVkShPdMaI7F4C0z)w&s!pXmUjRfOcL9H6E2B+y(u%r#oWlThQeNbJ8G5D1A-w*t$qYnVkSgPdLaI7F3C0z)v&s#pXmUiRfOcK9H5E2B+x(u%rZoWlThQeMbJC0z)w&s!pXmUjRfOcL9H6E2B+y(u%r#oWlThQeNbJ8G5D1A-w*t$qYnVkSgPdLaI7F3C0z)v&s!pXmUiRfOcK9H6E2B+x(u%rZoWlThQeMbJ8G4D1A-w*t!qYnVjSgPdLaI6F3C0y)v&s#pXlUiRfNcK
59、9H5E2A+x(u$rZoWkThPeMbJ7G4D1z-w*t!qYmVjSgOdLaI6F3B0y)v%s#pXlUiQfNcK8D1A-w*t!qYnVjSgPdLaI6F3C0y)v&s#pXlUiRfNcK9H5E2B+x(u$rZoWkThQeMbJ7G4D1z-w*t!qYmVjSgOdLaI6F3B0y)v%s#pXlUiQfNcK8H5E2A+x*u$rZnWkThPeMaJ7G4C1z-w&t!pYmVjRgOdL9I6F3B0y(v%s#oXlUiQfNbK8H5D2A+x*u$qZnWkShPeMaJ7F4C1z)w&t!pYmUjRgOcL9I6E3B+y(v%r#
60、oXlTiQeNbK8G5D2A-x*u$qZnVkShPdMaJ7F4C0z)w&s!pYmUjRfOcL9H6E3B+y(u%r#oWlTiQeNbJ8G5D1A-x*t$qYnVkcL9I6E3B+y(v%r#oXlTiQfNbK8G5D2A-x*u$qZnVkShPdMaJ7F4C0z)w&s!pYmUjRfOcL9H6E3B+y(u%r#oWlTiQeNbJ8G5D1A-x*t$qYnVkSgPdMaI7F4C0z)v&s!pXmUjRfOcK9H6E2B+y(u%rZoWlThQeNbJ8G4D1A-w*t$qYnVjSgPdLaI7F3C0y)v&s#pXmUiRfNcK9H5E
61、2B+x(u%rZoWkThQeMbJ8G4D1z-w*t!qYnVjSgOdLaI6F3C0y)v%s#pXlUiRfNcK8H5E2A+x(u$rZnWkThPeMbJ7G4C1z-w&t!qYmVjRgOdL9I6F3B0y)v%s#oXlUiQfNcK8H5D-w*t!qYnVjSgOdLaI6F3C0y)v%s#pXlUiRfNcK8H5E2A+x(u$rZnWkThPeMbJ7G4D1z-w&t!qYmVjSK9H5E2B+x(u%rZoWkThQeMbJ8G4D1z-w*t!qYnVjSgOdLaI6F3C0y)v%s#pXlUiRfNcK8H5E2A+x(u$rZoWkThPe
62、MbJ7G4D1z-w&t!qYmVjSgOdL9I6F3B0y)v%s#oXlUiQfNcK8H5D2A+x*u$rZnWkShPeMaJ7G4C1z)w&t!pYmVjRgOdL9I6E3B0y(v%s#oXlTiQfNbK8H5D2A-x*u$qZnWkSdL9I6F3B0y)v%s#oXlUiQfNcK8H5D2A+x*u$rZnWkShPeMaJ7G4C1z-w&t!pYmVjRgOdL9I6E3B0y(v%s#oXlTiQfN第35页/共36页第三十六页,共37页。内容(nirng)总结会计学。result=result+10。printf(%dn, result)。每组中三位,只用其中的两位表示(biosh)是否可读和是否可写。semop(1)函数说明。用shmctl拆除共享内存区(用命令IPC_RMID)。利用信号(signal)截取键盘Ctrl-C信号。pYmVjRgOdL9I6E3B0y(v%s#oXlTiQfN第三十七页,共37页。