SYSTEM V IPC(Inter-Process Communication,进程间通信)

System V提供的IPC机制主要有消息队列、信号量和共享内存3中机制。IPC在使用前必须先创建,每种IPC都有特定的生产者、所有者和访问权限。使用ipcs命令可以查看当前系统正在使用的IPC工具。
一个IPC工具至少包含key值、ID值、拥有者、权限、和使用的大小等关键信息。

1、key值和ID值

Linux系统为每个IPC机制都分配唯一的ID,所有针对该IPC机制的操作都使用该ID值。因此,通信的双方都需要通过某个办法来获得ID值。创建者根据创建函数的返回值可获取该值。
IPC在实现时约定使用key值作为参数创建,如果在创建时使用相同的key值将得到同一个IPC对象的ID(即一方创建,另一方获取的是 ID),这样就保证了双方可以获取用于传递数据的IPC机制ID值。
Linux提供ftok()来创建key值,
extern key_t ftok(__const char *pathname,int __proj_id)
参数:pathname为文件路径名,可以是特殊文件(例如目录文件,也可以是当前目录".")
  __proj_id为一个int型变量。
如果使用相同的文件路径及整数(第2个参数),得到的key值是唯一的,唯一的key值创建某类IPC机制将得到同一个IPC机制(但如果使用相同的key值分辨创建一个消息队列和一个信号量,两者没有联系),而文件路径的访问对两个进程来说很容易统一,因此便捷地实现了两进程通信机制ID的确定。
要访问任何一个IPC工具需要对该IPC工具拥有相应的权限,一个IPC工具所具有的IPC访问权限在/usr/include/bits/ipc.h文件 中被定义为struct ipc_perm。

2、消息队列

msqid_ds消息队列数据结构:描述整个消息队列的属性,主要包括整个消息队列的权限,拥有者、两个重要的指针分别指向消息队列中的第一个消息和最后一个消息。
msg消息队列数据结构:整个消息队列的主体,一个消息队列有若干个消息,每个消息数据结构的基本成员包括消息类型、消息大小、消息内容指针和下一个消息数据结构位置。
默认情况改下,整个系统中最多允许有16个消息队列
每个消息队列最大为16384字节
消息队列中的每个消息最大为8192字节
这些内容在/usr/include/linux/msg.h文件中进行了定义
Linux消息队列管理

(1)创建消息队列

在使用一个消息队列前,需要使用msgget函数创建该消息队列
extern int msgget (key_t __key,int __msgflg);
参数:key为ftok创建的key值
  msgflg的低位用来确定消息队列的访问权限,其最终权限为当前京城的umask值与设置值perm类似于  open函数,即最终值为perm&~umask

(2)消息队列属性控制

创建消息队列后,可以对该消息队列的基本属性进行控制(修改),控制消息队列属性的函数为msgctl
extern int msgctl (int __msgqid,int __cmd,struct msqid_ds *__buf);
参数:msqid为消息队列标识符,该值为使用msgget函数创建消息队列的返回值
cmd为执行的控制命令,即要执行的操作。包括以下选项
IPC_STAT:读取消息队列属性
IPC_SET:设置消息队列属性
IPC_RMID:删除消息队列
IPC_INFO:读取消息队列基本情况
buf为一个临时的msqid_ds结构体类型的变量。用于存储读取的消息队列属性或者需要修改的消息队列属性

(3)发送消息到消息队列

msgsnd()函数将新的消息添加到消息队列尾端
extern int msgsnd (int __msqid,__const void *__msgp,size_t __msgsz,int __msgflg)
参数:msqid为指定的消息队列标识符(由msgget生成的消息队列标识符),即将消息添加到哪个消息队列中
msgp指向的用户定义缓冲区,下面是用户定义缓冲区结构
struct msgbuf {
long mtype;//消息类型
char mtext[1];//消息内容,在使用时自己重新定义此结构
}
mtype是一个正整数,表示消息的类型,因此,接收进程可以用来进行消息选择(消息队列在存储消息时是按发送的先后顺序放置的)
mtext存储消息内容,在使用时自己重新定义此结构
msgsz为结构消息的大小,其数据类型为size_t,其大小为0到系统对消息队列的限制值
msgflg用来指定在到达系统为消息队列设定的界限(如达到字数限制)时应采取的操作。设置为IPC_NOWAIT,如果需要等待,则不发送消息并且调用进程立即返回错误信息EAGAIN。如果设置为0,则阻塞调用进程。

(4)从消息队列接收信息

msgrcv用于从队列中取消息。
extern int msgrcv (int __msqid, void *__msgp,size_t __msgsz,long int __msgtyp,int __msgflg)
此函数从msqid指定的消息队列中读取消息,并将其放置到由msgp指向的内存空间中。
参数:msqid为读的对象,即从哪个消息队列获得消息
msgp为一个临时消息数据结构,用来保存读取的消息
msgsz用于指定mtext的大小
msgtyp用于指定请求的消息类型
msgtyp=0:接收队列中的第一条消息,任意类型
msgtyp>0:接收第一条msgtyp类型的消息。
msgtyp<0:接收第一条最低类型(小于或等于msgtyp的绝对值)的消息。
msgflg用于指定所需类型消息不在队列上时将要采取的操作。如果设置为IPC_NOWAIT,如果现在没有消息,调用进程立即返回,同时返回-1。如果未设置IPC_NOWAIT,则阻塞调用进程。
信号量通信机制

3、信号量通信机制

信号量通信机制主要用来实现进程间同步,避免并发访问共享资源。信号量值可以表示系统可用的资源的个数。通常所说的创建一个信号量实际上是创建了一个信号量集合,在这个信号量集合中,可能有多个信号量。整个信号量集合由以下部分组成。
信号量集合数据结构:在此数据结构中定义了整个信号量集合的基本属性,如访问权限。
信号量:信号量集合使用指针指向一个由数组组成的信号量单元,在此信号量单元中存储了各信号量的值。
Linux信号量管理操作

(1)创建信号量集合

创建一个信号量集合的函数为semget
extern int semget (key_t __key, int __nsems, int __semflg);
参数:key,一般由ftok函数产生
nsems为创建的信号量个数,以数组的方式存储
semflg用来表示信号量集合的权限

(2)控制信号量集合、信号量

在Linux操作系统中,可使用semctl函数对一个信号量集合以及信号量集合中的某个或某几个信号量进行操作。
extern int semctl (int __semid, int __semnum, int  __cmd,...)
参数:semid为要操作的信号量集合标识符,一般由semget函数返回
semnum为集合中信号量的编号。如果标识某个信号量,此值为该信号量的下标(从0到n-1);如果操作整个信号量集合,此参数无意义
cmd为要执行的操作
第四个参数根据第三个参数的具体操作设置。

(3)信号量操作

semop系统调用来操作信号量集合
extern int semop (int __semid,struct sembuf *__sops,size_t __nsops);
参数:semid为要操作的信号量集合ID
sops为struct sembuf结构的变量
struct sembuf {
unsigned short sem_num;//信号量下标
short sem_op;//信号量操作,正数表示增加的信号量的值,负数表示减小信号量的值
short sem_flg;//操作标识
}
sem_flg为操作标识
IPC_NOWAIT:在对信号量集合的操作不能执行的情况下,调用立即返回,对某信号量操作,即使其中一个操作失败,也不会导致修改集合中的其他信号量。
SEM_UNDO:当进程推退出后,该进程对sem进行的操作将被撤销。

4、共享内存

共享内存进程间通信机制主要用于实现进程间大量数据的传输。共享内存是在内存中单独开辟的一段内存空间,这段内存空间有自己特有的数据结构,包括访问权限、大小和最近访问的时间等。
两个进程在使用此空想内存空间之前,需要在进程地址空间与共享内存空间之间建立联系,即将共享内存空间挂载到进程中。
在使用共享内存进行数据存取时,有必要使用二元信号量来同步两个进程以实现对共享内存的写操作。
Linux共享内存管理

(1)创建共享内存

创建共享内存的系统调用shmget函数申明如下:
extern int shmget (key_t __key, size_t __size, it __shmflg);
参数:key一般由ftok函数产生
size为欲创建的共享内存段大小
shmflg用来表示共享内存段的创建标识
IPC_CREAT如果不存在就创建
IPC_EXCL如果存在就返回失败
IPC_NOWAIT不等待直接返回

(2)共享内存控制

Linux系统使用shmctl函数来实现共享内存空间的控制,包括读取状态、设置状态和删除操作
extern int shmctl (int __shmid, int __cmd,struct shmids *__buf);
参数:shmid为要操作的共享内存标识符,该值一般由shmget函数返回。
cmd为要执行的操作
buf为struct shmid_ds结构的临时共享内存变量信息

(3)映射共享内存对象

在进程使用一段共享内存空间前,需要将该共享内存与当前进程建立联系,即将该共享内存映射(挂接)到当前进程。系统调用shma()实现将一个共享内存段映射到调用进程的数据段中,并返回该内存空间首地址。
extern void *shmat (int __shmid, __const void *__shmaddr, int __shmflg);
如果执行成功,将返回共享内存标识符
参数:shmid为要操作的共享内存标识符,该值一般由shmget函数返回
shmaddr指定共享内存的映射地址。如果该值为非0,则将用此值作为映射共享内存的地址,如果此值为0,则由系统来选择映射的地址。一般都将此值设置为0。

(4)分离共享内存对象

在使用完毕共享内存空间后,需要使用shmdt函数调用将其与当前进程分离。
extern int shmdt(__const void *__shmaddr);
此函数只有一个参数,即与当前进程分离的共享内存表示ID。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值