Linux ipc------System V

System V IPC指的是AT&T在System V.2发行版中引入的三种进程间通信工具:

(1)信号量,用来管理对共享资源的访问;

(2)共享内存,用来高效地实现进程间的数据共享;

(3)消息队列,用来实现进程间数据的传递。

我们把这三种工具统称为System V
IPC对象,每个对象都具有一个唯一的IPC标识符(identifier)。

IPC key

如何让多个进程都访问某一个特定的IPC对象,需要一个IPC关键字(IPC key),每一个IPC对象都与一个IPC关键字(IPC
key)相关联。这样就解决了多进程在一个IPC对象上汇合的问题。创建一个IPC对象时需要指定一个键值,类型为key_t。内核负责把IPC关键字转换成IPC标识符。在linux内核中定义了一个结构体:

<span style="font-weight: normal;"><span style="font-size:14px;">struct ipc_perm
{
key_t key; 关键字
uid_t uid; /*共享内存所有者的有效用户ID */
gid_t gid; /* 共享内存所有者所属组的有效组ID*/
uid_t cuid; /* 共享内存创建 者的有效用户ID*/
gid_t cgid; /* 共享内存创建者所属组的有效组ID*/
unsigned short mode; /* Permissions + SHM_DEST和SHM_LOCKED标志*/
unsignedshort seq; /* 序列号*/
};</span></span>

key_t key就是IPC key,是识别这个共享通道的钥匙。也叫做键。

1.、IPC键(IPC key)

key_t这个数据类型在<sys/types.h>有定义,通常是一个至少32位的整数。我们通常使用ftok()函数(可以如此记忆:file
to key)把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键。选择IPC关键字,可以使用如下三种方式:

a)IPC_PRIVATE。由内核负责选择一个关键字然后生成一个IPC对象并把IPC标识符直接传递给另一个进程。

b)直接选择一个关键字。

c)使用ftok()函数生成一个关键字。

2、ftok原型如下:

key_t ftok( char * fname, int id )

头文件:

#include <sys/types.h>
#include <sys/ipc.h>  

参数:

fname就时你指定的文件名(该文件必须是存在而且可以访问的),id是子序号,虽然为int,但是只有8个比特被使用(0-255)。

返回值:

当成功执行的时候,一个key_t值将会被返回,否则 -1 被返回。

System V IPC对象总结

1、信号量(Semaphores)

System V的信号量集表示的是一个或多个信号量的集合。内核为每个信号量集维护一个semid_ds数据结构,而信号量集中的每个信号量使用一个无名结构体表示,这个结构体至少包含以下成员:

struct{

unsigned short semval;//信号量值,总是>=0

pid_t sempid; //上一次操作的pid

};

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

(1)创建或访问信号量

* int semget(key_t key,int nsems,int flag);

nsems指定信号量集中信号量的个数,如果只是获取信号量集的标识符(而非新建),那么nsems可以为0。flag的低9位作为信号量的访问权限位,类似于文件的访问权限;如果flag中同时指定了IPC_CREAT和IPC_EXCL,那么如果key已与现存IPC对象想关联的话,函数将会返回EEXIST错误。例如,flag可以为IPC_CREAT|0666。

(2)控制信号量集

* int semctl(int semid,int semnum,int cmd,union semun arg);

对semid信号量集合执行cmd操作;cmd常用的两个值是:SETVAL初始化第semnum个信号量的值为arg.val;IPC_RMID删除信号量。

(3)对一个或多个信号量进行操作

* int semop(int semid,struct sembuf *sops,unsigned nsops);

* struct sembuf{

unsigned short sem_num; //信号量索引

short sem_op; //对信号量进行的操作,常用的两个值为-1和+1,分别代表P、V操作

short sem_flag; //比较重要的值是SEM_UNDO:当进程结束时,相应的操作将被取消;同时,如果进程结束时没有释放资源的话,系统会自动释放

};

2、共享内存

共享内存允许两个或多个进程共享一定的存储区,因为不需要拷贝数据,所以这是最快的一种IPC。

#include <sys/ipc.h>

#include <sys/shm.h>

(1)创建或访问共享内存

* int shmget(key_t key,size_t size,int shmflg);

(2)附加共享内存到进程的地址空间

* void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常为NULL,由系统选择共享内存附加的地址;shmflg可以为SHM_RDONLY

(3)从进程的地址空间分离共享内存

* int shmdt(const void *shmaddr); //shmaddr是shmat()函数的返回值

(4)控制共享内存

* int shmctl(int shmid,int cmd,struct shmid_ds *buf);

* struct shmid_ds{

struct ipc_perm shm_perm;

};

cmd的常用取值有:(a)IPC_STAT获取当前共享内存的shmid_ds结构并保存在buf中(2)IPC_SET使用buf中的值设置当前共享内存的shmid_ds结构(3)IPC_RMID删除当前共享内存

3、消息队列

消息队列保存在内核中,是一个由消息组成的链表。

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

(1)创建或访问消息队列

* int msgget(key_t key,int msgflg);

(2)操作消息队列

* int msgsnd(int msqid,const void *msg,size_t nbytes,int msgflg);

msg指向的结构体必须以一个long int成员开头,作为msgrcv()的消息类型,必须大于0。nbytes指的是msg指向结构体的大小,但不包括long int部分的大小

* ssize_t msgrcv(int msqid,void *msg,size_t nbytes,long msgtype,int msgflg);

如果msgtype是0,就返回消息队列中的第一个消息;如果是正整数,就返回队列中的第一个该类型的消息;如果是负数,就返回队列中具有最小值的第一个消息,并且该最小值要小于等于msgtype的绝对值。

(3)控制消息队列

* int msgctl(int msqid,int cmd,struct msqid_ds *buf);

* struct msqid_ds{

struct ipc_perm msg_perm;

};

4、总结

(1)使用semget()/shmget()/msgget()函数根据IPC关键字key和一个标志flag创建或访问IPC对象。如果key是IPC_PRIVATE;或者key尚未与已经
   存在的IPC对象相关联且flag中包含IPC_CREAT标志,那么就会创建一个全新的IPC对象。

(2)使用semctl()/shmctl()/msgctl()函数修改IPC对象的属性。

(3)使用semctl()/shmctl()/msgctl()函数和IPC_RMID标志销毁IPC实例。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-21 20:49:53

Linux ipc------System V的相关文章

LINUX学习:System V消息队列

介绍: 1.消息队列提供了一个从一个进程向另外一个进程发送数据块的方法 2.每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 3.消息队列也有管道一样的不足,就是每个消息最大的长度是有上限的(MSGMAX),每个消息队列 的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也是有一个上限的.   每个IPC对象都在内核维护着一个数据结构, 消息不同于刘模式,消息是有边界的,消息都是被打包在一个一个的数据包里的. 那么我们看下消息队列结构:       消息队列有4

进程间同步---system v ipc 对象信号灯集

一.信号灯简介 Linux支持System V的信号灯(semaphore),是一种进程间通信的方式,只不过它和管道.FIFO或者共享内存不一样,信号灯主要用于同步或者互斥对共享资源的访问,它的发明来源于火车运行系统中的"信号灯",利用信号灯可以实现"PV"操作这种进程间同步进制.P操作时获得资源,将信号灯的值减1,如果结果不为负则执行完毕,进程获得资源,否则进程睡眠以等待的进程释放;V操作则是释放资源,给信号灯的值加1, 唤醒一个因执行P操作而等待的进程. 二.信

进程间通信---mmap详解(与system V ipc通信对照)

目前,进程间通信主要集中在管道和共享内存上使用,共享内存是总所周知的直接对内存映射操作,速度最快的通信方式,缺点,可能就是数据同步没有提供同步机制 共享存储映射 存储映射I/O  存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射.于是当从缓冲区中取数据,就相当于读文件中的相应字节.于此类似,将数据存入缓冲区,则相应的字节就自动写入文件.这样,就可在不使用read和write函数的情况下,使用地址(指针)完成I/O操作. 使用这种方法,首先应通知

UNIX 进程间通讯(IPC)概念(Posix,System V IPC)

 IPC(Inter-Process Communication,进程间通讯)可以有三种信息共享方式(随文件系统,随内核,随共享内存).(当然这里虽然说是进程间通讯,其实也是可以和线程相通的). 相对的IPC的持续性(Persistence of IPC Object)也有三种: 随进程持续的(Process-Persistent IPC) IPC对象一直存在,直到最后拥有他的进程被关闭为止,典型的IPC有pipes(管道)和FIFOs(先进先出对象) 随内核持续的(Kernel-persist

System V IPC相关函数

System V IPC 将一个已保存的路径名和一个整数标识符转换成一个key_t值,称为IPC键key_t:System V IPC(System V消息队列.System V信号量.System V共享内存区)将key_t作为它们的名字 #include <sys/ipc.h> key_t ftok(const char *pathname, int id); ipc_perm结构: 内核给每个IPC对象维护一个信息结构 #include <sys/ipc.h> struct

system v信号量的深入剖析

最近看了linux的SYSTEM V信号量的部分,同时对于信号量的数据结构以及系统调用函数的具体实现进行了分析,现将这部分资料进行一个整理,以便于自己理清思路,同时便于以后的查看,若里面有写的不当之处,还望大家指教. 需要说明的是本报告是基于linux-2.6.11版本 第一部分  信号量的数据结构 1.信号量的分类: (1)内核级信号量,及内核函数采用的信号量. (2)用户级信号量(只是用户态使用)可分为POSIX信号量和SYSTEM V信号量 2.本文只对system v信号量进行分析 为了

linux进程间通讯-System V IPC 信号量

进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在

Linux IPC实践(11) --System V信号量(1)

信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); int semctl(int semid, int semnum, int cmd, ...); int semop(int semid, struct sembuf *sops, unsigned nsops); semget int

Linux IPC实践(9) --System V共享内存

共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf); //

细说linux IPC(五):system V共享内存

system V共享内存和posix共享内存类似,system V共享内存是调用shmget函数和shamat函数.           shmget函数创建共享内存区,或者访问一个存在的内存区,类似系统调用共享内存的open和posix共享内存shm_open函数.shmget函数原型为: #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); key: 函