《Linux内核与编程.ppt》由会员分享,可在线阅读,更多相关《Linux内核与编程.ppt(35页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Linux内核与编程内核与编程 厦门大学软件学院厦门大学软件学院实验三实验三使用使用Linux高级高级IPC陈毅东陈毅东Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院提纲提纲结束进程间通信概述进程间通信概述目标问题目标问题哲学家进餐问题哲学家进餐问题问题描述问题描述错误与不好的解法错误与不好的解法并行度较高的解法并行度较高的解法Linux高级高级IPC机制机制概述概述System V信号灯信号灯System V共享内存区共享内存区实现的其他问题实现的其他问题实习题实习题Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院进程间通信概述(进程间通信概述(1):引子):引
2、子#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);result=result+10;exit(0);while(wait(int*)0)!=-1);printf(%dn,result);exit(0);输出结果是什么?输出结果是什么?Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院进程间
3、通信概述(进程间通信概述(2)进程是相互独立的,进程间的通信需要专进程是相互独立的,进程间的通信需要专门的机制。门的机制。进程之间的通信可以经由文件系统,但实进程之间的通信可以经由文件系统,但实际使用较为复杂(例如,需要锁机制)。际使用较为复杂(例如,需要锁机制)。UNIX IPC(InterProcess Communication)机制是各种进程通信方式机制是各种进程通信方式的统称。的统称。Linux下的进程通信手段基本上是从下的进程通信手段基本上是从Unix平平台上的进程通信手段继承而来的。台上的进程通信手段继承而来的。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院进程间
4、通信概述(进程间通信概述(3)对于对于UNIX的发展,贝尔实验室和的发展,贝尔实验室和BSD在进在进程间通信方面的侧重点有所不同:程间通信方面的侧重点有所不同:贝尔实验室对贝尔实验室对Unix早期的进程间通信手段进行早期的进程间通信手段进行了系统的改进和扩充,形成了了系统的改进和扩充,形成了“System V IPC”,通信进程局限在单个计算机内;,通信进程局限在单个计算机内;BSD则主要考虑跨计算机的进程间通信,形成则主要考虑跨计算机的进程间通信,形成了基于套接口(了基于套接口(socket)的进程间通信机制。)的进程间通信机制。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院
5、进程间通信概述(进程间通信概述(4)返回最初的最初的UNIX IPCSystem V IPC基于基于Socket的的IPCLinux IPCPOSIX IPC最初的最初的Unix IPC:信号、管道、信号、管道、FIFO;System V IPC:消息队列、信号量、共享内存区消息队列、信号量、共享内存区;POSIX IPC:消息队列、信号量、共享内存区。:消息队列、信号量、共享内存区。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院哲学家进餐问题的描述哲学家进餐问题的描述五个哲学家围坐在一张圆桌周围,每五个哲学家围坐在一张圆桌周围,每个哲学家面前都有一碗米饭,相邻的个哲学家面前都
6、有一碗米饭,相邻的两碗之间有一支筷子(如图)。两碗之间有一支筷子(如图)。哲学家的生活包含两种活动:即吃饭哲学家的生活包含两种活动:即吃饭和思考。当一个哲学家觉和思考。当一个哲学家觉得饿时,他得饿时,他就试图分两次去取他左边和右边的筷就试图分两次去取他左边和右边的筷子,每次拿起一支,但不分次序。如子,每次拿起一支,但不分次序。如果成功地获得了一双筷子,他就开始果成功地获得了一双筷子,他就开始吃饭,吃完以后放下筷子继续思考。吃饭,吃完以后放下筷子继续思考。这样,问题就是,为每个哲学家写一这样,问题就是,为每个哲学家写一段程序来描述其行为,要求不死锁。段程序来描述其行为,要求不死锁。返回Linux
7、内核与编程内核与编程厦厦门门大大学学软软件件学学院院错误与不好的解法(错误与不好的解法(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);若每个哲学家进程若每个哲学家进程都运行到此句后发都运行到此句后发生进程切换,则进生进程切换,则进入死锁。入死锁。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院错误
8、与不好的解法(错误与不好的解法(2)#define N 5void philosopher(int i)while(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);解法二:可能进入解法二:可能进入“饥饿饥饿”状态状态不妨假设此函数能做不妨假设此函数能做到到“测试且设置测试且设置”。这种解法可能会造成下面情这种解法可能会造成下面情况:哲学家们不断地重复
9、况:哲学家们不断地重复“拿起拿起各自左边的筷子又放下各自左边的筷子又放下”的动作,的动作,谁也不能进餐。注意:这时和解谁也不能进餐。注意:这时和解法一的状态不同,这时进程都没法一的状态不同,这时进程都没有阻塞。有阻塞。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院错误与不好的解法(错误与不好的解法(3)#define N 5typedef int semaphore;semaphore mutex=1;void philosopher(int i)while(TRUE)think();down(mutex);take-chopstick(i);take-chopstick(i+
10、1)%N);eat();put-chopstick(i);put-chopstick(i+1)%N);up(mutex);返回解法三:可行但效率低下解法三:可行但效率低下本解法从理论上可行,本解法从理论上可行,但从实际角来看,有一局限但从实际角来看,有一局限性:同一时刻只能有一位哲性:同一时刻只能有一位哲学家进餐。而这里有五支筷学家进餐。而这里有五支筷子,实际上应能允许两位哲子,实际上应能允许两位哲学家同时进餐。学家同时进餐。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院并行度较高的解法(并行度较高的解法(1)#define N 5#define LEFT(i+N-1)%N#d
11、efine RIGHT (i+1)%N#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);Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院并行度较高的解法(并行度较高的解法(2)返回void put-chopsticks(int i)dow
12、n(&mutex);statei=THINKING;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);Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院概述概述System V IPC包含了三种机制,在实现包含了三种机制,在实现
13、“哲学家进餐问哲学家进餐问题题”时,我们只使用信号灯机制和共享存储区机制。主要时,我们只使用信号灯机制和共享存储区机制。主要的函数如下:的函数如下:信号灯信号灯共享内存区共享内存区头文件头文件创建或打开创建或打开IPCsemgetshmget控制控制IPC操作操作semctlshmctlIPC操作函数操作函数semopshmat,shmdtSystem V IPC对象以对象以key_t类型的值作为其名字。类型的值作为其名字。System V IPC对象以一定的存取权限来控制其访问。对象以一定的存取权限来控制其访问。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院System
14、V IPC的名字的名字System V IPC是有名的,是有名的,这样可以支持无亲缘关系的进这样可以支持无亲缘关系的进程访问同一的程访问同一的IPC对象。其名字的类型为对象。其名字的类型为key_t,可以由,可以由ftok函数赋予或直接取值函数赋予或直接取值IPC_PRIVATE。ftok函数函数原型:原型:#include#include key_t ftok(const char*pathname,int id);功能:把已存在的路径名和一整数标识符转换成一个功能:把已存在的路径名和一整数标识符转换成一个key_t值,称为值,称为IPC键。键。返回值:成功时返回返回值:成功时返回IPC键,
15、出错返回键,出错返回-1。说明:说明:1、ftok产生的键值不会是产生的键值不会是IPC_PRIVATE;2、不能保证、不能保证ftok生成的键值唯一;生成的键值唯一;3、用于产生键的文件不能在该、用于产生键的文件不能在该IPC对象存活其对象存活其内删除。内删除。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院System V IPC对象的存取权限对象的存取权限为防止共享的为防止共享的IPC对象被非法访问,必须为对象被非法访问,必须为IPC对对象设置存取权限象设置存取权限。System V IPC对象的存取权限和文件系统中文件对象的存取权限和文件系统中文件的存取权限类似,也用
16、的存取权限类似,也用9位分位分3组表示,三组分别组表示,三组分别代表属主、组成员和其他用户对该代表属主、组成员和其他用户对该IPC对象的存取对象的存取权限;每组中三位,只用其中的两位表示是否可权限;每组中三位,只用其中的两位表示是否可读和是否可写。一般为了安全,在创建读和是否可写。一般为了安全,在创建IPC对象时对象时应该设置存取权限制为应该设置存取权限制为0600,表示仅仅对属主是,表示仅仅对属主是可读,可写的。可读,可写的。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院System V信号灯信号灯semgetsemctlsemopdown和和up的实现的实现返回Linu
17、x内核与编程内核与编程厦厦门门大大学学软软件件学学院院semget(1)函数说明函数说明原型:原型:#include#include#include int semget(key_t key,int nsems,int oflag);功能:创建或打开信号灯集合。功能:创建或打开信号灯集合。返回值:成功返回非负信号灯标识符,出错返回返回值:成功返回非负信号灯标识符,出错返回-1。说明:说明:1、key是欲创建或打开的信号灯集合的是欲创建或打开的信号灯集合的名字名字;2、nsems指明信号灯集合中包含的信号灯数;指明信号灯集合中包含的信号灯数;3、oflag是一个是一个位信息标志,含两部分信息,即
18、位信息标志,含两部分信息,即存存取权限取权限和控制字段。低和控制字段。低9位表示位表示存取权限,存取权限,控控制字段中制字段中IPC_CREAT位位和和IPC_EXCL位的设位的设置情况与参数置情况与参数key共同决定了本调用的操作。共同决定了本调用的操作。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院semget(2)工作流程工作流程if(key=IPC_PRIVATE)创建新信号灯集并返回其创建新信号灯集并返回其id;else if(与与key相关的信号灯集合存在相关的信号灯集合存在)if(oflag&IPC_CREAT)&(oflag&IPC_EXCL)返回返回-1;el
19、se if(访问权限允许访问权限允许)返回与返回与key相关的信号灯集相关的信号灯集id;else 返回返回-1;else if(oflag&IPC_CREAT)创建新信号灯集并返回其创建新信号灯集并返回其id;else 返回返回-1;返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院semctl(1)函数说明函数说明原型:原型:#include#include#include int semctl(int semid,int semnum,int cmd,union semun arg);功能:对功能:对semid标识的信号灯集合进行控制。标识的信号灯集合进行控制。返回值:成
20、功返回非负返回值:成功返回非负值值,出错返回,出错返回-1。说明:说明:1、cmd是对信号灯集的控制命令,有是对信号灯集的控制命令,有GETVAL,SETVAL,GETALL,SETALL,IPC_RMID 等,我们只用最后的两个。等,我们只用最后的两个。2、semnum标识该信号灯集中某成员(以标识该信号灯集中某成员(以0为第为第 一个),仅用于一个),仅用于GETVAL,SETVAL等命令。等命令。3、arg是可选的,取决于参数是可选的,取决于参数cmd,GETALL或或 SETALL等命令就要用到参数等命令就要用到参数arg。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院
21、semctl(2)union semununion semun的定义为:的定义为:union semun int val;/仅用于仅用于SETVAL命令命令 struct semid_ds*buf;/用于用于IPC_SET等命令等命令 ushort*array;/用于用于SETALL等命等命令令注意,本联合未在出现在任何系统头文件中,因此必须由注意,本联合未在出现在任何系统头文件中,因此必须由应用程序声明。应用程序声明。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院semop(1)函数说明函数说明原型:原型:#include#include#include int semo
22、p(int semid,struct sembuf*opsptr,size_t nops);功能:对功能:对semid标识的信号灯集合中信号灯进行操作。标识的信号灯集合中信号灯进行操作。返回值:成功返回返回值:成功返回0,出错返回,出错返回-1。说明:说明:1、opsptr是指向结构是指向结构struct sembuf的指针,可的指针,可 以是这种类型的结构数组的头指针。数组的每以是这种类型的结构数组的头指针。数组的每 个元素包含对信号灯集合中一个信号的的操作个元素包含对信号灯集合中一个信号的的操作 的信息,从而可实现同时对多信号灯的操作。的信息,从而可实现同时对多信号灯的操作。2、nops指
23、出指出opsptr指向的结构数组中元素数。指向的结构数组中元素数。Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院semop(2)struct sembufstruct 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
24、(sem_op);else sleep;goto start;sem_op0:sv=sv+sem_op;唤醒所有阻塞于该信号量的进程唤醒所有阻塞于该信号量的进程;sem_op=0:测试测试sv是否为是否为0。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院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,&op,1);void up(int sid,int sn)struct sembuf op;op.sem_num
25、=sn;op.sem_op=1;op.sem_flg=0;semop(sid,&op,1);返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院System V共享内存区共享内存区shmgetshmctlshmat和和shmdt使用共享内存区的一般流程使用共享内存区的一般流程返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院shmget原型:原型:#include#include#include int shmget(key_t key,size_t size,int oflag);功能:创建或打开功能:创建或打开共享内存区共享内存区。返回值:成功返回非负内存区标
26、识符,出错返回返回值:成功返回非负内存区标识符,出错返回-1。说明:说明:1、size指明共享内存区大小(字节为单位);指明共享内存区大小(字节为单位);2、key和和oflag的说明基本和的说明基本和semget相同;相同;3、打开或创建一个共享内存区,并没提供调用进、打开或创建一个共享内存区,并没提供调用进 程访问该内存区的手段。必须调用程访问该内存区的手段。必须调用shmat。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院shmctl原型:原型:#include#include#include int shmctl(int shmid,int cmd,struct s
27、hmid_ds*buff);功能:对功能:对shmid标识的共享内存区进行控制。标识的共享内存区进行控制。返回值:成功返回返回值:成功返回0,出错返回,出错返回-1。说明:说明:1、参数、参数cmd是对共享内存区的控制命令,可以是是对共享内存区的控制命令,可以是 IPC_RMID,IPC_SET或或IPC_STAT,我们仅,我们仅 用第一个;用第一个;2、buff主要用于命令主要用于命令IPC_SET和和IPC_STAT,命,命 令为令为IPC_RMID时可直接提供时可直接提供NULL;返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院shmat和和shmdt原型:原型:#in
28、clude#include#include void*shmat(int shmid,const void*shmaddr,int flag);int shmdt(const void*shmaddr);功能:功能:shmat用于将一个打开的共享内存区附接到调用进用于将一个打开的共享内存区附接到调用进程的地址空间程的地址空间。shmdt用于切断这个内存区域。用于切断这个内存区域。返回值:出错返回返回值:出错返回-1,shmat成功返回映射区的起始地址成功返回映射区的起始地址而而shmdt成功时候返回成功时候返回0。说明:说明:shmat中中shmaddr和和flag可用来影响映射区起始地可用来
29、影响映射区起始地址的选取。一般应该分别提供址的选取。一般应该分别提供NULL和和0。返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院使用共享内存区的一般流程使用共享内存区的一般流程使用使用System V共享内存区时的一般流程:共享内存区时的一般流程:用用shmget创建或打开一个共享内存区创建或打开一个共享内存区用用shmat将打开的共享内存区附接到进程地址空间将打开的共享内存区附接到进程地址空间对共享内存区进行操作对共享内存区进行操作用用shmdt切断共享内存区与本进程地址空间的联系切断共享内存区与本进程地址空间的联系用用shmctl拆除共享内存区(用命令拆除共享内存区(
30、用命令IPC_RMID)返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院实现的其他问题实现的其他问题如何创建多个进程如何创建多个进程创建一个进程链创建一个进程链创建一个进程扇创建一个进程扇创建一个进程树创建一个进程树程序的结束程序的结束程序失败后如何释放资源程序失败后如何释放资源返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院创建一个进程链创建一个进程链#define N 4#include#include#include main()int i;for(i=1;iN;+i)if(fork()break;fprintf(stderr,#%d is proce
31、ss%ld with parent%ldn,i,(long)getpid(),(long)getppid();注意:本程序未考虑注意:本程序未考虑fork失败的情况。失败的情况。1234返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院创建一个进程扇创建一个进程扇#define N 4#include#include#include main()int i;for(i=1;iN;+i)if(fork()=0)break;fprintf(stderr,#%d is process%ld with parent%ldn,i,(long)getpid(),(long)getppid(
32、);注意:本程序未考虑注意:本程序未考虑fork失败的情况。失败的情况。1234返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院创建一个进程树创建一个进程树#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失败的情况。失败的情况。02a13a3b3c3d
33、2b返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院程序的结束程序的结束在什么时机结束程序在什么时机结束程序以某个外部文件的存在与否来决定:每个哲学以某个外部文件的存在与否来决定:每个哲学家在家在“吃吃”完后都检测某个特定的文件(例如:完后都检测某个特定的文件(例如:/quit)是否已经被创建。若是则结束程序。是否已经被创建。若是则结束程序。利用信号(利用信号(signal)截取键盘截取键盘Ctrl-C信号。信号。程序结束时候要记得回收程序结束时候要记得回收IPC资源资源返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院程序失败后如何释放资源程序失败后如何释放
34、资源杀掉杀掉垃圾进程垃圾进程使用使用ps ax查看所有进程查看所有进程使用使用killall name进行删除进行删除删除垃圾删除垃圾IPC资源资源使用使用ipcs-a查看所有查看所有IPC资源资源使用使用ipcrm shm|sem id进行删除进行删除返回Linux内核与编程内核与编程厦厦门门大大学学软软件件学学院院实习题实习题理解实现进程通信的难点理解实现进程通信的难点练习创建多个进程的方法练习创建多个进程的方法解决哲学家进餐问题解决哲学家进餐问题实现不好的或有错误的算法,观察运行情况实现不好的或有错误的算法,观察运行情况实现正确的算法(需要检查)实现正确的算法(需要检查)也实现其他方法也实现其他方法返回