Linux内核与编程.ppt

上传人:小飞机 文档编号:5437923 上传时间:2023-07-07 格式:PPT 页数:36 大小:236.99KB
返回 下载 相关 举报
Linux内核与编程.ppt_第1页
第1页 / 共36页
Linux内核与编程.ppt_第2页
第2页 / 共36页
Linux内核与编程.ppt_第3页
第3页 / 共36页
Linux内核与编程.ppt_第4页
第4页 / 共36页
Linux内核与编程.ppt_第5页
第5页 / 共36页
点击查看更多>>
资源描述

《Linux内核与编程.ppt》由会员分享,可在线阅读,更多相关《Linux内核与编程.ppt(36页珍藏版)》请在三一办公上搜索。

1、实验三使用Linux高级IPC,陈毅东,提纲,结束,进程间通信概述目标问题哲学家进餐问题问题描述错误与不好的解法并行度较高的解法Linux高级IPC机制概述System V信号灯System V共享内存区实现的其他问题实习题,进程间通信概述(1):引子,#include#include int result;main()pid_t pid;result=0;pid=fork();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

2、);result=result+10;exit(0);while(wait(int*)0)!=-1);printf(%dn,result);exit(0);,输出结果是什么?,进程间通信概述(2),进程是相互独立的,进程间的通信需要专门的机制。进程之间的通信可以经由文件系统,但实际使用较为复杂(例如,需要锁机制)。UNIX IPC(InterProcess Communication)机制是各种进程通信方式的统称。Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。,进程间通信概述(3),对于UNIX的发展,贝尔实验室和BSD在进程间通信方面的侧重点有所不同:贝尔实验室

3、对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“System V IPC”,通信进程局限在单个计算机内;BSD则主要考虑跨计算机的进程间通信,形成了基于套接口(socket)的进程间通信机制。,进程间通信概述(4),返回,最初的Unix IPC:信号、管道、FIFO;System V IPC:消息队列、信号量、共享内存区;POSIX IPC:消息队列、信号量、共享内存区。,哲学家进餐问题的描述,五个哲学家围坐在一张圆桌周围,每个哲学家面前都有一碗米饭,相邻的两碗之间有一支筷子(如图)。哲学家的生活包含两种活动:即吃饭和思考。当一个哲学家觉得饿时,他就试图分两次去取他左边和右边的筷

4、子,每次拿起一支,但不分次序。如果成功地获得了一双筷子,他就开始吃饭,吃完以后放下筷子继续思考。这样,问题就是,为每个哲学家写一段程序来描述其行为,要求不死锁。,返回,错误与不好的解法(1),解法一:可能进入“死锁”状态,#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);,错误与不好的解法(2),#define N 5void philosopher(int i)whi

5、le(TRUE)think();do take-chopstick(i);if(can-take-chopstick(i+1)%N)break;else put-chopstick(i);while(TRUE);eat();put-chopstick(i);put-chopstick(i+1)%N);,解法二:可能进入“饥饿”状态,这种解法可能会造成下面情况:哲学家们不断地重复“拿起各自左边的筷子又放下”的动作,谁也不能进餐。注意:这时和解法一的状态不同,这时进程都没有阻塞。,错误与不好的解法(3),#define N 5typedef int semaphore;semaphore mute

6、x=1;void philosopher(int i)while(TRUE)think();down(mutex);take-chopstick(i);take-chopstick(i+1)%N);eat();put-chopstick(i);put-chopstick(i+1)%N);up(mutex);,返回,解法三:可行但效率低下,本解法从理论上可行,但从实际角来看,有一局限性:同一时刻只能有一位哲学家进餐。而这里有五支筷子,实际上应能允许两位哲学家同时进餐。,并行度较高的解法(1),#define N 5#define LEFT(i+N-1)%N#define RIGHT(i+1)%N

7、#define THINKING 0#define HUNGRY 1#define EATING 2typedef int semaphore;int stateN;semaphore mutex=1;semaphore sN;,void philosopher(int i)while(TRUE)think();take-chopsticks(i);eat();put-chopsticks(i);,并行度较高的解法(2),返回,void put-chopsticks(int i)down(,void test(i)if(statei=HUNGRY,void take-chopsticks(in

8、t i)down(,概述,System V IPC包含了三种机制,在实现“哲学家进餐问题”时,我们只使用信号灯机制和共享存储区机制。主要的函数如下:信号灯共享内存区头文件创建或打开IPCsemgetshmget控制IPC操作semctlshmctlIPC操作函数semopshmat,shmdtSystem V IPC对象以key_t类型的值作为其名字。System V IPC对象以一定的存取权限来控制其访问。,返回,System V IPC的名字,System V IPC是有名的,这样可以支持无亲缘关系的进程访问同一的IPC对象。其名字的类型为key_t,可以由ftok函数赋予或直接取值IPC

9、_PRIVATE。ftok函数原型:#include#include key_t ftok(const char*pathname,int id);功能:把已存在的路径名和一整数标识符转换成一个key_t值,称为IPC键。返回值:成功时返回IPC键,出错返回-1。说明:1、ftok产生的键值不会是IPC_PRIVATE;2、不能保证ftok生成的键值唯一;3、用于产生键的文件不能在该IPC对象存活其内删除。,返回,System V IPC对象的存取权限,为防止共享的IPC对象被非法访问,必须为IPC对象设置存取权限。System V IPC对象的存取权限和文件系统中文件的存取权限类似,也用9位

10、分3组表示,三组分别代表属主、组成员和其他用户对该IPC对象的存取权限;每组中三位,只用其中的两位表示是否可读和是否可写。一般为了安全,在创建IPC对象时应该设置存取权限制为0600,表示仅仅对属主是可读,可写的。,返回,System V信号灯,semgetsemctlsemopdown和up的实现,返回,semget(1)函数说明,原型:#include#include#include int semget(key_t key,int nsems,int oflag);功能:创建或打开信号灯集合。返回值:成功返回非负信号灯标识符,出错返回-1。说明:1、key是欲创建或打开的信号灯集合的名字

11、;2、nsems指明信号灯集合中包含的信号灯数;3、oflag是一个位信息标志,含两部分信息,即存取权限和控制字段。低9位表示存取权限,控制字段中IPC_CREAT位和IPC_EXCL位的设置情况与参数key共同决定了本调用的操作。,semget(2)工作流程,if(key=IPC_PRIVATE)创建新信号灯集并返回其id;else if(与key相关的信号灯集合存在)if(oflag,返回,semctl(1)函数说明,原型:#include#include#include int semctl(int semid,int semnum,int cmd,union semun arg);功能

12、:对semid标识的信号灯集合进行控制。返回值:成功返回非负值,出错返回-1。说明:1、cmd是对信号灯集的控制命令,有GETVAL,SETVAL,GETALL,SETALL,IPC_RMID 等,我们只用最后的两个。2、semnum标识该信号灯集中某成员(以0为第 一个),仅用于GETVAL,SETVAL等命令。3、arg是可选的,取决于参数cmd,GETALL或 SETALL等命令就要用到参数arg。,semctl(2)union semun,union semun的定义为:union semun int val;/仅用于SETVAL命令 struct semid_ds*buf;/用于IP

13、C_SET等命令 ushort*array;/用于SETALL等命令注意,本联合未在出现在任何系统头文件中,因此必须由应用程序声明。,返回,semop(1)函数说明,原型:#include#include#include int semop(int semid,struct sembuf*opsptr,size_t nops);功能:对semid标识的信号灯集合中信号灯进行操作。返回值:成功返回0,出错返回-1。说明:1、opsptr是指向结构struct sembuf的指针,可 以是这种类型的结构数组的头指针。数组的每 个元素包含对信号灯集合中一个信号的的操作 的信息,从而可实现同时对多信号

14、灯的操作。2、nops指出opsptr指向的结构数组中元素数。,semop(2)struct sembuf,struct sembuf的定义为:struct sembuf short sem_num;/信号灯号:0,1,nsems-1 short sem_op;/信号灯操作:0 short sem_flg;/操作标识:这里我们只要置0sem_op不同值对应的操作(设信号灯当前值为sv):sem-op=abs(sem_op)sv=sv-abs(sem_op);else sleep;goto start;sem_op0:sv=sv+sem_op;唤醒所有阻塞于该信号量的进程;sem_op=0:测试

15、sv是否为0。,返回,down和up的实现,void down(int sid,int sn)struct sembuf op;op.sem_num=sn;op.sem_op=-1;op.sem_flg=0;semop(sid,void up(int sid,int sn)struct sembuf op;op.sem_num=sn;op.sem_op=1;op.sem_flg=0;semop(sid,返回,System V共享内存区,shmgetshmctlshmat和shmdt使用共享内存区的一般流程,返回,shmget,原型:#include#include#include int sh

16、mget(key_t key,size_t size,int oflag);功能:创建或打开共享内存区。返回值:成功返回非负内存区标识符,出错返回-1。说明:1、size指明共享内存区大小(字节为单位);2、key和oflag的说明基本和semget相同;3、打开或创建一个共享内存区,并没提供调用进 程访问该内存区的手段。必须调用shmat。,返回,shmctl,原型:#include#include#include int shmctl(int shmid,int cmd,struct shmid_ds*buff);功能:对shmid标识的共享内存区进行控制。返回值:成功返回0,出错返回-1

17、。说明:1、参数cmd是对共享内存区的控制命令,可以是 IPC_RMID,IPC_SET或IPC_STAT,我们仅 用第一个;2、buff主要用于命令IPC_SET和IPC_STAT,命 令为IPC_RMID时可直接提供NULL;,返回,shmat和shmdt,原型:#include#include#include void*shmat(int shmid,const void*shmaddr,int flag);int shmdt(const void*shmaddr);功能:shmat用于将一个打开的共享内存区附接到调用进程的地址空间。shmdt用于切断这个内存区域。返回值:出错返回-1,

18、shmat成功返回映射区的起始地址而shmdt成功时候返回0。说明:shmat中shmaddr和flag可用来影响映射区起始地址的选取。一般应该分别提供NULL和0。,返回,使用共享内存区的一般流程,使用System V共享内存区时的一般流程:用shmget创建或打开一个共享内存区用shmat将打开的共享内存区附接到进程地址空间对共享内存区进行操作用shmdt切断共享内存区与本进程地址空间的联系用shmctl拆除共享内存区(用命令IPC_RMID),返回,实现的其他问题,如何创建多个进程创建一个进程链创建一个进程扇创建一个进程树程序的结束程序失败后如何释放资源,返回,创建一个进程链,#defi

19、ne N 4#include#include#include main()int i;for(i=1;iN;+i)if(fork()break;fprintf(stderr,#%d is process%ld with parent%ldn,i,(long)getpid(),(long)getppid();注意:本程序未考虑fork失败的情况。,返回,创建一个进程扇,#define N 4#include#include#include main()int i;for(i=1;iN;+i)if(fork()=0)break;fprintf(stderr,#%d is process%ld wi

20、th parent%ldn,i,(long)getpid(),(long)getppid();注意:本程序未考虑fork失败的情况。,返回,创建一个进程树,#define N 4#include#include#include main()int i,id=0;for(i=1;iN;+i)if(fork()=0)id=i;fprintf(stderr,#%d is process%ld with parent%ldn,id,(long)getpid(),(long)getppid();注意:本程序未考虑fork失败的情况。,返回,程序的结束,在什么时机结束程序以某个外部文件的存在与否来决定:每个哲学家在“吃”完后都检测某个特定的文件(例如:/quit)是否已经被创建。若是则结束程序。利用信号(signal)截取键盘Ctrl-C信号。程序结束时候要记得回收IPC资源,返回,程序失败后如何释放资源,杀掉垃圾进程使用ps ax查看所有进程使用killall name进行删除删除垃圾IPC资源使用ipcs-a查看所有IPC资源使用ipcrm shm|sem id进行删除,返回,实习题,理解实现进程通信的难点练习创建多个进程的方法解决哲学家进餐问题实现不好的或有错误的算法,观察运行情况实现正确的算法(需要检查)也实现其他方法,返回,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号