106Linux操作系统SYSV进程间通信.pptx
linux程序设计课件 第7章-进程间的通信
本章重点
1. 进程通信中信号的概念及信号处理。 2. 进程间的管道通信编程。 3. 进程间的内存共享编程。 4. 进程间队列通信编程。
2
进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区, P1进程把数据从用户空间拷到内核缓冲区,P2进程再从内核缓冲区把 数据读走,如图7.1所示。内核提供的这种机制称为进程间通信(IPC, InterProcess Communication)。
例7.2 下列程序应用函数alarm(10)在运行10秒后发送信号 SIGALARM,程序接收到SIGALARM信号就被终止。
7-2源程序
[root@localhost root]# ./7-2
正在计数中:0 正在计数中:1 ........ 正在计数中:905 闹钟
11
7.2 信 号
例7.3 设计一个程序,要求用户进程创建一个子进程,父进程向子进 程发出SIGKILL信号,子进程收到此信号,结束子进程的运行。
24
7.3.1 无名管道操作
管道允许在进程之间按先进先出的方式传送数据, 是进程间通信的一种常见的方式。 例如: [root@localhost root]# ls | more
无名管道操作时,建立管道用pipe函数。管道操作分以下步骤: 1. 父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端; 2. 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向 同一管道; 3. 父进程关闭管道读取端,子进程关闭管道写入端。父进程可以往管 道里写,子进程可以从管道里读,管道是用环形队列实现的,数据从 写入端流入从读取端流出,这样就实现了进程间通信。
在Linux中,管道是一种特殊的文件,对一个进程来说,管道 的写入和读取与一个普通文件没有区别。
Linux下进程间通信的原理
Linux下进程间通信的原理了解 Linux IPC 相关的概念和原理有助于我们理解 Binder 通信原理。
因此,在介绍 Binder 跨进程通信原理之前,我们先聊聊 Linux 系统下传统的进程间通信是如何实现。
⼀、基本概念Linux 进程间通信的原理图如下图所⽰:可以看出来,Liunx 中跨进程通信涉及到的⼀些基本概念如下:进程隔离进程空间划分:⽤户空间(User Space)/内核空间(Kernel Space)系统调⽤:⽤户态/内核态1. 进程隔离简单的说就是操作系统中,进程与进程间内存是不共享的。
两个进程就像两个平⾏的世界,A 进程没法直接访问 B 进程的数据,这就是进程隔离的通俗解释。
A 进程和B 进程之间要进⾏数据交互就得采⽤特殊的通信机制:进程间通信(IPC)。
2. 进程空间划分操作系统的核⼼是内核,独⽴于普通的应⽤程序,可以访问受保护的内存空间,也可以访问底层硬件设备的权限。
为了保护⽤户进程不能直接操作内核,保证内核的安全,操作系统从逻辑上将虚拟空间划分为⽤户空间(User Space)和内核空间(Kernel Space)。
简单的说就是,内核空间(Kernel)是系统内核运⾏的空间,⽤户空间(User Space)是⽤户程序运⾏的空间。
为了保证安全性,它们之间是隔离的。
3. 系统调⽤:⽤户态与内核态虽然从逻辑上进⾏了⽤户空间和内核空间的划分,但不可避免的⽤户空间需要访问内核资源,⽐如⽂件操作、访问⽹络等等。
为了突破隔离限制,就需要借助系统调⽤来实现。
系统调⽤是⽤户空间访问内核空间的唯⼀⽅式,保证了所有的资源访问都是在内核的控制下进⾏的,避免了⽤户程序对系统资源的越权访问,提升了系统安全性和稳定性。
Linux 使⽤两级保护机制:0 级供系统内核使⽤,3 级供⽤户程序使⽤。
当⼀个任务(进程)执⾏系统调⽤⽽在内核代码中执⾏时,称进程处于内核运⾏态(内核态)。
此时处理器处于特权级最⾼的(0级)内核代码中执⾏。
第五章 System V进程间通信
如果在创建时使用相同的key值将得到同一个IPC对象的ID (即一方创建,另一方获取的是ID),这样就保证了双方可 以获取用于传递数据的IPC机制ID值。
2013-12-18 4
ftok
extern key_t ftok(__const char * __pathname, int __proj_id); 此函数有两个参数,pathname为文件路径名,可以是特殊 文件(例如目录文件),也可以是当前目录“.”,而通常也是 设置此参数为当前目录,因为当前目录一般都是存在的,且不会 被立即删除。第二个参数为一个int型变量。
(但如果使用相同的key值分别创建一个消息队列和一个信号量,
两者没有联系),而文件路径的访问对两个进程来说很容易统一, 因此,便捷的实现了两进程通信机制的确定。
2013-12-18 7
例:ftok函数和参数的关系
#include <sys/ipc.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> main(int argc, char * argv[]){ key_t key; int i;
就像每个文件都有一个打开文件号一样,每个对象也都有唯一
的识别号,进程可以通过系统调用传递的识别号来存取这些对 象。与文件的存取一样,对这些对象的存取也要验证存取权限, System V IPC可以通过系统调用对对象的创建者设置这些对象的 存取权限。
2013-12-18 2
ipcs 命令
Ipcs命令用于显示消息队列、共享内存、信号量的信息。
16
linux进程间通信PPT课件
2
.
linux进程间通信(IPC)由以下几部分发展而来:
早期UNIX进程间通信、基于System V进程间通信、 基于Socket进程间通信和POSIX进程间通信。
UNIX进程间通信方式包括:管道、FIFO、信号。
System V进程间通信方式包括:System V消息队 列、System V信号灯、System V共享内存。
普通的Linux shell都允许重定向,而重定向使用的就是 管道。例如:
ps | grep vsftpd
管道是单向的、先进先出的、无结构的、固定大小的字 节流,它把一个进程的标准输出和另一个进程的标准输入 连接在一起。写进程在管道的尾端写入数据,读进程在管 道的首端读出数据。数据读出后将从管道中移走,其它读 进程都不能再读到这些数据。管道提供了简单的流控制机 制。进程试图读空管道时,在有数据写入管道前,进程将 一直阻塞。同样,管道已经满时,进程再试图写管道,在 其它进程从管道中移走数据之前,写进程将一直阻塞。
if((fp=popen(cmd,"r"))==NULL)
perror("popen");
while((fgets(buf,BUFSIZE,fp))!=NULL)
POSIX进程间通信包括:posix消息队列、posix信 号灯、posix共享内存。
3
.
现在linux使用的进程间通信方式: (1)管道(pipe)和有名管道(FIFO) (2)信号(signal) (3)消息队列 (4)共享内存 (5)信号量 (6)套接字(socket)
4
.
2、管道通信
必须在系统调用fork( )中调用pipe( ),否则子进 程将不会继承文件描述符。
Linux_进程之间的通信
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2184 root 20 0 64220 4812 3908 R 6.7 0.2 0:00.01 top
1 root 20 0 178784 13560 8556 S 0.0 0.7 0:04.24 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp 5 root 20 0 0 0 0 I 0.0 0.0 0:00.69 kworker/0:0-xfs-cil/dm-0 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H-kblockd ...............
//此处的load average就表示负载平均值,这三个值代表最近1、5和15分钟的负载情况。
[root@localhost ~]# top top - 09:26:24 up 23 min, 4 users, load average: 0.00, 0.00, 0.00 Tasks: 219 total, 1 running, 218 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.2 hi, 0.2 si, 0.0 st MiB Mem : 1965.1 total, 1405.6 free, 260.4 used, 299.1 buff/cache MiB Swap: 2096.0 total, 2096.0 free, 0.0 used. 1545.0 avail Mem
linuxC-进程间通信-SystemV消息队列
消息队列不需要初始化,所以在使用的时候不需要判断是谁先创建的 if((msgid = msgget(key,IPC_CREAT|0666)) < 0)这样直接使用。 刚创建的消息队列是空的,没有任何的 fifo。
表 8.24 列举了 msgsnd()函数的语法要点。
表 8.24 msgsnd()函数语法要点
表 8.25 所需头文件 函数原型 函数传入值 msgrcv()函数语法要点 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int msgrcv(int msgid, void *msgp, size_t msgsz, long int msgtyp, int msgflg) msqid:消息队列的队列 ID msgp:消息缓冲区, 同于 msgsnd()函数的 msgp msgsz:消息正文的字节数(不包括消息类型指针变量)
进程间的通信—消息队列
SystemV 的消息队列使用消息队列标识符来标识。任何进程都可以往一个给 定的队列里放消息,也可以冲任何一个队列里读取消息,前提是要有特权。 消息队列是 IPC 对象中的一种。 消息队列可以按照类型来发送和接收消息。 消息队列就是一些消息的列表。用户可以从消息队列中添加消息和读取消 息等。从这点上看,消息队列具有一定的 FIFO 特性,但是它可以实现消息的随 机查询,比 FIFO 具有更大的优势。同时,这些消息又是存在于内核中的,由“队列 ID”来标识。 ◦ 消息队列内核中实现
0:接收消息队列中第一个消息 msgtyp: 大于 0:接收消息队列中第一个类型为 msgtyp 的消息 小于 0:接收消息队列中第一个类型值不小于 msgtyp 绝对值 且类型值又最小的消息 MSG_NOERROR:若返回的消息比 msgsz 字节多,则消息就 会截短到 msgsz 字节,且不通知消息发送进程 函数传入值 msgflg: IPC_NOWAIT 若在消息队列中并没有相应类型的消息可以接 收,则函数立即返回 0:msgsnd()调用阻塞直到接收一条相应类型的消息为止 函数返回值 成功:0 出错:1
Linux的进程和进程间通信 操作系统课件
例子1(续)
} else if(child==0) { int i; printf("I am the child:%ld\n",getpid()); for(i=0;i<1000000;i++) i++; i=5; printf("I exit with %d\n",i); exit(i); } while(((child=wait(&status))==-1)&(errno==EINTR)); }
区分父进程和子进程:
◦ 跟踪fork返回值
失败:-1 否则
父进程fork 返回子进程的ID fork 子进程返回0
可根据这个返回值来区分父子进程
调用系统程序
调用系统程序, 可以使用系统调用exec 族调用。 exec 族调用有着5 个函数:
#include <unistd.h> int execl(const char *path,const char *arg,...); int execlp(const char *file,const char *arg,...); int execle(const char *path,const char *arg,...); int execv(const char *path,char *const argv[]); int execvp(const char *file,char *const argv[]):
10-6Linux操作系统 - SYSV进程间通信PPT精品文档27页
(b)XXXctl() 均提供IPC_SET、IPC_STAT和 IPC_RMID命令。前两者用来设置或得到IPC资源 的状态信息,IPC_RMID用来释放IPC资源。
key 既 可 由 ftok ( ) 函 数 产 生 , 也 可 以 是 IPC_PRIVATE常量,key值是IPC资源的外部表示。
oflag包括读写权限,还可以包含IPC_CREATE和 IPC_EXCL标志位。它们组合的效果如下: (1)指定key为IPC_PRIVATE保证创建一个唯一 的IPC资源。 (2)设置oflag参数的IPC_CREATE标志位但不设 置IPC_EXCL。如果相应key的IPC资源不存在,则 创建一个IPC资源,否则返回已存在的IPC资源。
int sempid;/* 最近对信号量操作进程的pid */
};
信号量的初始值可以调用函数semctl()进行设
置。
•用户可以调用函数semop()对信号量集合中的 一个或多个信号量进行操作。
int semop(int semid, struct sembuf *opsptr, size_t nops);
量用来描述同一类资源的公有数据,三个全局变 量分别是semid_ds,msgid_ds和shmid_ds。
struct ipc_ids { int size; /* entries数组的大小*/ int in_use; /* entries数组已使用的元素个数*/ int max_id; unsigned short seq; unsigned short seq_max; truct semaphore sem; /*控制对ipc_ids结构的访问*/ spinlock_t ary;/*自旋锁控制对数组entries的访问*/ struct ipc_id* entries; }; struct ipc_id {
linux 进程间通信ppt
内核 管道
父子进程之间的管道通信(2)
父子进程分别拥有自己的读写通道,为了实现父子进程之 间的读写,只需把无关的读端或写端的文件描述符关闭即 可。此时,父子进程之间就建立起了一条“子进程写入父 进程读取”的通道。
父进程 fd[0] fd[1] 子进程 fd[0] fd[1]
最初UNIX的进程间通信 System V 进程间通信 Socket进程间通信 POSIX进程间通信
Linux 进程间 通信
进程间通信方式的种类(1)
(1)管道(Pipe)及有名管道(named pipe):管道可用于具 有亲缘关系进程间的通信,有名管道,除具有管道所具有的 功能外,它还允许无亲缘关系进程间的通信。 (2)信号(Signal):信号是在软件层次上对中断机制的一种 模拟,它是比较复杂的通信方式,用于通知进程有某事件发 生,一个进程收到一个信号与处理器收到一个中断请求效果 上可以说是一样的。 (3)消息队列(Messge Queue):消息队列是消息的链接表, 包括Posix消息队列SystemV消息队列。它克服了前两种通信 方式中信息量有限的缺点,具有写权限的进程可以按照一定 的规则向消息队列中添加新消息;对消息队列有读权限的进 程则可以从消息队列中读取消息。
13
示例
阅读并运行示例8-2-2。
标准流管道 (1)
与Linux的文件操作中有基于文件流的标准I/O操作一样,管道 的操作也支持基于文件流的模式。这种基于文件流的管道主 要是用来创建一个连接到另一个进程的管道,这里的“另一 个进程”也就是一个可以进行一定操作的可执行文件,例如, 用户执行“ls -l”或者自己编写的程序“./pipe”等。由于这一类 操作很常用,因此标准流管道就将一系列的创建过程合并到 一个函数popen()中完成。它所完成的工作有以下几步。
第4章 System V的进程间通信
struct ipc_ids ipcid[n-1] ipcid[0] …… ipcid[n]{ struct kern_ipc_perm* }
struct msg_queue
struct kern_ipc_perm time_t q_stime …… …… struct list_head q_senders
实验内容
12
消息队列
是一个格式化的可变长信息单位 消息机制允许一个进程向任何其他进程发送一个消 息 当一个进程收到多个消息时,可将它们排成一个消 息队列
13
消息队列全局数据结构
struct ipc_ids msg_ids
int size …… …… …… struct ipc_id*
函数原型
参数说明
返回值
说明
IPC_CREAT一般由服务器程序创建消息队列时使用 如果是客户程序,必须打开现有的消息队列,不使用IPC_CREAT
20
消息队列的基本操作—msgrcv()
功能
消息队列中读取一个消息 ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t size, long type, int flag); msgid:消息队列描述字 msgp:/消息存储位置 size:消息内容的长度 type:请求读取的消息类型 flag:规定队列无消息时内核应做的操作
8
IPC键的创建
创建函数
key_t ftok( char * filename, int id);
功能说明
将一个已存在的文件名(该文件必须是存在而且可以访问 的)和一个整数标识符id转换成一个key_t值 在Linux系统实现中,调用该函数时,系统将文件的索引 节点号取出,并在前面加上子序号,从而得到key_t的返 回值
09第09章 System V进程间通信
2020/6/5
24
第9章 System V进程间通信
1
System V IPC基础
2
消息队列
3
信号量通信机制
4
共享内存
共享内存IPC原理
P 进程1
共享内存空间
P 进程2
2020/6/5
26
共享内存属性
2020/6/5
27
共享内存与管道对比
2020/6/5
28
创建共享内存
2020/6/5
29
21
2020/6/5
22
信号量操作
2020/6/5
23
使用信号量实现生产消费问题
• 生产消费问题是一个经典的数学问题,要求生产者-消费者在固定的仓库空间 条件下,生产者每生产一个产品将占用一个仓库空间,生产者生产的产品库存 不能越过仓库的存储量,消费者每消费一个产品将增加一个仓库空间,消费者 在仓库产品为0时不能再消费。
型小置息
…….
msg 消息
msg 消息
msg 消息
消消消下 息息息一 类大位消 型小置息
msg
消息
2020/6/5
7
消息队列属性
2020/6/5
8
消息struct msg结构体
2020/6/5
9
创建消息队列
2020/6/5
10
消息队列属性控制
2020/6/5
11
发送信息到消息队列
2020/6/5
共享内存控制
2020/6/5
30
共享内存应用示例
• 共享内存的权限管理示例
• 共享内存处理应用示例
• 代码见教材。
2020/6/5
零点起飞学Linux C之进程间通信56页PPT
21、要知道对好事的称颂过于夸大,也会招来人们的反感轻蔑和嫉妒。——培根 22、业精于勤,荒于嬉;行成于思,毁于随。——韩愈
23、一切节省,归根到底都归结为时间的节省。——马克思 24、意志பைடு நூலகம்运往往背道而驰,决心到最后会全部推倒。——莎士比亚
25、学习是劳动,是充满思想的劳动。——乌申斯基
谢谢!
零点起飞学Linux C之进程间通信
1、战鼓一响,法律无声。——英国 2、任何法律的根本;不,不成文法本 身就是 讲道理 ……法 律,也 ----即 明示道 理。— —爱·科 克
3、法律是最保险的头盔。——爱·科 克 4、一个国家如果纲纪不正,其国风一 定颓败 。—— 塞内加 5、法律不能使人人平等,但是在法律 面前人 人是平 等的。 ——波 洛克
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
key 既 可 由 ftok ( ) 函 数 产 生 , 也 可 以 是 IPC_PRIVATE常量,key值是IPC资源的外部表 示。
oflag包括读写权限,还可以包含IPC_CREATE和 IPC_EXCL标志位。它们组合的效果如下: (1)指定key为IPC_PRIVATE保证创建一个唯 一的IPC资源。 (2)设置oflag参数的IPC_CREATE标志位但不 设置IPC_EXCL。如果相应key的IPC资源不存在, 则创建一个IPC资源,否则返回已存在的IPC资源。
struct kern_ipc_perm* p;};
数组entries的每一项指向一个kern_ipc_perm 结构,kern_ipc_perm结构表示每一个IPC资源的 属性,用来控制操作权限。
struct kern_ipc_perm{ key_t key;/*用户提供的键值,为XXXget()所用*/ uid_t uid; /*创建者用户ID*/ gid_t gid; /*创建者组ID*/ uid_t cuid; /*所有者用户ID*/ gid_t cgid; /*所有者组ID*/ mode_t mode; /*操作权限,包括读、写等*/ unsigned long seq; };
(3)oflag参数的IPC_CREATE和IPC_EXCL同 时设置。如果相应key的IPC资源不存在,则创 建一个IPC资源。否则返回一个错误信息。
(b)XXXctl() 均提供IPC_SET、IPC_STAT和 IPC_RMID命令。前两者用来设置或得到IPC资源 的状态信息,IPC_RMID用来释放IPC资源。
IPC资源ID = SEQ_MULTIPLIER * seq + index
SEQ_MULTIPLIER是可用资源的最大数目,seq 是ipc_ids结构中的seq。每当分配一个IPC资源 时,ipc_ids结构中的seq就增一。 (2)当知道IPC资源ID时,可通过
IPC资源ID % SEQ_MULTIPLIER 得到 其 在 entries 数组 中 的 index ,从 而找到相应的 IPC资源。 (3)why 保证在一段时期内IPC资源ID的唯一性
semid : IPC资源ID opsptr: 操作的集合 nops: 数组opsptr的大小
因 为 每 个 IPC 资 源 描 述 符 的 第 一 个 成 员 就 是 kern_ipc_perm结构。因此,我们可以认为数组 entries 的每一非空项均指向一个IPC资源。
IPC资源ID与entries数组下标的联系 (1)当创建一个IPC资源时, •调 用 函 数 ipc_addid() 从 相 应 ipc_ids 结 构 的 entries数组中找出第一个未使用的项然后返回其 下标index。 •返回IPC资源ID
struct ipc_ids { int size; /* entries数组的大小*/ int in_use; /* entries数组已使用的元素个数*/ int max_id; unsigned short seq; unsigned short seq_max; truct semaphore sem; /*控制对ipc_ids结构的访问*/ spinlock_t ary;/*自旋锁控制对数组entries的访问*/ struct ipc_id* entries; }; struct ipc_id {
struct sem_queue **sem_pending_last;
struct sem_undo *undo;
unsigned long sem_nsems;/*信号量的个数*/
};
信 号 量 集 合 中 的 每 一 个 信 号 用 结 构 sem 表 示 ,
struct sem {
int semval;/* 信号量的当前值 */
10.6 SYS V 进程间通信
内容 • 信号量 • 消息队列 • 共享内存
10.6.1 三者共有的特性 IPC资源 表示单独的消息队列、共享内存或是 信号量集合
三 者 均 有 XXXget ( ) 及 XXXctl ( ) 函 数 (XXX代表msg、sem、shm三者之一)
(a) XXXget()函数
int sempid;/* 最近对信号量操作进emctl()进行设
置。
•用户可以调用函数semop()对信号量集合中 的一个或多个信号量进行操作。
int semop(int semid, struct sembuf *opsptr, size_t nops);
10.6.2 信号量 •信号量是具有整数值的对象,它支持P、V原语。 进程可以利用信号量实现同步和互斥 •SYSV支持的信号量实质上是一个信号量集合,由 多个单独的信号量组成。我们称SYSV信号量为 信号量集合,而单个的信号量直接称为信号量。 •信号量集合在内核中用结构sem_array表示
struct sem_array {
struct kern_ipc_perm sem_perm;
time_t sem_otime;
/* 最近一次操作时间 */
time_t sem_ctime;
/* 最近一次的改变时间 */
struct sem *sem_base; /*指向第一个信号量 */
struct sem_queue *sem_pending;/* 挂起操作队列*/
共同的操作模式
•都是先通过XXXget()创建一个IPC资源,返回 值是该IPC资源ID。在以后的操作中,均以IPC资 源ID为参数以对相应的IPC资源进行操作。
•别的进程可以通过XXXget()取得已有的IPC资 源ID(权限允许的话)到并对其操作,从而进程 间通信成为可能。
共同的数据结构
每一类IPC资源都有一个ipc_ids结构的全局变 量用来描述同一类资源的公有数据,三个全局变 量分别是semid_ds,msgid_ds和shmid_ds。