Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1255438
  • 博文数量: 261
  • 博客积分: 4196
  • 博客等级: 上校
  • 技术积分: 3410
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-17 17:05
文章分类

全部博文(261)

文章存档

2018年(1)

2017年(22)

2016年(2)

2015年(8)

2014年(27)

2013年(40)

2012年(161)

分类: LINUX

2012-04-28 10:43:13

 System V IPC

       IPC objects

       消息队列 (message queue)

       旗语 (信号量)(semaphore set)

       共享内存 (shared memory)

       shell 命令

       ipcs, ipcrm

 

创建 System V IPC 时访问授权

S_I RUSR

用户读

S_I WUSR

用户写

S_I RGRP

组读

S_I WGRP

组写

S_I ROTH

其它人读

S_I WOTH

其它人写

创建 System V IPC 时指令

IPC_CREAT

key 不存在则创建

IPC_ EXCL

key 存在则失败

IPC_NOWAIT

请求的 IPC 须等待则出错

 

       #include

       key_t ftok(char * fname, int id)

       系统建立 IPC 通信必须指定一个 ID 值。通常情况下,该 id 值通过 ftok 函数得到。

       fname 为指定的文件名 ( 该文件必须是存在而且可以访问的 ), id是子序号,虽 然为 int ,但是只有 8 个比特被使用 (0- 2 55) 。当成功执行的时候,一个 key_t 值将会被返回,否则返回 -1

       在一般 UNI X 实现中,是将文件的索引节点号取出,前面加上子序号得到 key_t 的返回值。如指定文件的索引节点号为    65538 ,换算成 16 进制为 0x0 10002 ,而你指定的 ID 值为 3 8 ,换算成 16 进制为 0x26 ,则最后的 key_t 返回值为 0x26010002

       查询文件索引节点号的方法是:ls -i

 

设置 System V IPC 时的控制命令

IPC_RMID

删除标识符指示的 IPC

IPC_SET

设置选项

IPC_STAT

读取选项

       ipc_perm 结构

struct ipc-perm

{

       Uid_t uid;       //Owner’s user ID

       Gid_t gid;       // Owner’s group ID

       Uid_t cuid;      //Creator’s user ID

       Gid_t cgid;     //Creator’s group ID

       Mode_t mode; //read/write permission

       Key_t key ;

       Unsigned short seq ;

}

System V IPC 函数概览                                        

消息队列

信号量

共享内存

分配一个IPC对象,获得对 IPC 的访问

msgget

semget

shmget

IPC操作:发送/接收消息,信号量操作,连接/释放共享内存

msgsnd/msgrcv

semop

shmat/shmdt

IPC控制:获得/修改状态信息,取消IPC

msgctl

semctl

shmctl

 

消息队列 IPC

 

       消息队列就是消息的一个链表,它允许一个或多个进程向它写消息,一个或多个进程从中读消息。这些消息存在于内核中,由队列ID” 来标识。

       消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作

 

       #include

       #include

       #include

              int msgget(key_t key, int msgflg) ;

       功能:创建一个新的消息队列 , 或者希望获取一个已经存在的消息队列 (msgflg = 0)

       返回值:成功返回消息队列标识符;失败返回 -1

       参数:

                     key :消息队列键值 / 名字。

                     msgflg :指令和访问权限标志,包括:IPC_CREAT 如果内核中没有此队列 , 则创建它。IPC_ EXCL 当和 IPC_CREAT 一起使用时, 如果队列已经存在, 则失败。打开权限类似 open(), 相当于文件的访问权限。

 

#include

       #include

       #include

       int msgsnd ( int msgid, struct msg buf *msgp, int msgsz, int msgflg ) ;

       能:往队列中发送一条消息

       返回值 :成功返回 0 ,错误返回 -1

       数:

                     msgid :是消息队列标识符 , 它是由系统调用 msgget 返回的 .

                     msgp :是指向消息缓冲区的指针 .

                     msgsz :中包含的是消息的字节大小, 但不包括消息类型的长度 (4个字节).

                     msgflg :可以设置为0(此时为忽略此参数), 或者使用 IPC_NOWAIT.

              如果消息队列已满,那么此消息则不会写入到消息队列中, 控制将返回到调用进程中.如果没有指明, 调用进程将会挂起, 直到消息可以写入到队列中

 

#include

#include

#include

int msgrc v (int msgid, struct msg buf *msgp, int msgsz, long mtype, int msgflg) ;

能:读取消息,从消息队列中取走消息。

返回值 :成功返回 0 ,错误返回 -1

数:

msgid :用来指定将要读取消息的队列

msgp :代表要存储消息 的消息缓冲区的地址 .

msgsz :是消息缓冲区的长度,不包括 mtype 的长度,它可以按照如下的方法计算:msgsz = sizeof(struct mymsgbuf)- sizeof(long) ;

mtype :是要从消息队列中读取的消息的类型. 如果此参数的值为0, 那么队列中最长时间的一条消息将返回, 而不论其类型是什么 .

msgflg :没有消息可接收时,如果该参数中IPC_NOWAIT 被设置,那么立刻返回-1IPC_NOWAIT 被清除则挂起。

 

       #include

       #include

       #include

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

       能:对消息队列的操作。

       返回值 :成功返回 0 ,错误返回 -1

       数:

                     msgid: 消息队列 ID .

                     cmd: IPC_RMID 从系统内核中移走消息队列, IPC_STAT 读取消息队列当前设置, IPC_SET 修改消息队列的设置。

                     buf : 队列状态数据结构。

 

旗语同步

 

       旗语是一个受保护的变量,它可以提供对两个以上进程共享资源限制访问的方法。旗语允许两个操作,称为获取与释放。获取操作允许进程取得旗语,如果旗语已被其它进程获取,则阻塞直到旗语可用为止,进程使用完旗语后需释放旗语,以使其它进程可获取它。释放旗语会自动唤醒下一个等待获取旗语的进程。

       旗语由 Edsger Di j kstra T.H.E. 操作系统引入的。最初被定义为PV P 是荷兰语 proberen( 尝试 ), V verhogen( 增加 )

              旗语分为两种基本类型。第一种是二进制旗语,二进制旗语代表单个资源;第二种是计数旗语,用来代表数量大于一的共享资源。

 

       #include

       int semget(key_t key, int nsems, int semflg) ;

       功能:创建一个新的旗语或取得一个已有的旗语。

       返回值:成功返回旗语标识符,失败返回 -1

       参数:

       key:系统范围内的唯一标识符,其它进程访问旗语的依据。

              IPC_P RIVA T E 告诉 semget 自己生成标识符,所以其它进程 无法访

              问该旗语。使用 ftok() 函数获得唯一标识。

       nsems :旗语个数,为 1 时表示单个旗语,大于 1 表示旗语数组

       ,用来获取已有旗语时设为 0

       semflg :指令和访问权限标志,

              IPC_C REAT 创建新的旗语 IPC_C REAT|IPC_EXCL 如果旗语

              在则失败 errno 设为 EEXIST

              semflg =0 用来获取一个 已有的旗语。

打开权限类似 open(), 相当于文件的访问权限。

 

       #include

       int semop(int semid, struct sem buf *sops, size_t nsops);

       功能:提供获取和释放旗语或旗语数组的方法。

       返回值:成功返回 0 ,否则 -1

       参数:

              semid :旗语描述符。

              sops :旗语结构( 数组 )指针,包含了具体操作。

                     struct sembuf {

                     unsigned short sem_num ; // 对应旗语数组中的旗语, 0对应第一个旗语

short sem_op ;          // 旗语的当前值记录相应资源目前可用数目;sem_op >0 进程要释放 sem_op 数目的共享资源; sem_op=0 用于对共享资源是否已用完的测试 ( 调用进程将调用 sleep() ,直到信号量的值为 0) sem_op <0 进程要申请 -sem_op 个共享资源

short sem_flg ; //IPC_NOWAIT:无旗语可用则失败,SEM_UNDO:在进程结束时,相应的操作将被取消,如果设置了该标志位,在进程没有释放共享资源就退出时,内核将代为释放。

};

#include

int semctl(int semid, int semnum, int cmd, …);

功能:控制旗语信息。

返回值:成功返回0(或要获取的值),否则 -1

参数:

semid:旗语标识符。

semnum:旗语编号。

cmd:要进行的操作。

第四个参数,是 union semun 的实例,具体值依赖 cmd

union semun {

int val;

struct semid_ds *buf ;

unsigned short *array;

} arg;

cmd 命令(设第四个参数为 arg) :

IPC_STAT  获取旗语信息,信息由 arg.buf 返回;

IPC_SET  设置旗语信息,待设置信息保存在 arg.buf 中;

IPC_RMID  删除旗语或旗语数组 ;

GETALL  返回所有旗语的值,结果保存在arg .array中,参数sennum 被忽略;

GETNCNT  返回等待 semnum 所代表旗语的值增加的进程数,相当于目前有多少进程在等待 semnum 代表的旗语所代表的共享资源;

GETPID  返回最后一个对semnum所代表旗语执行semop 操作的进程 ID

GETV A L  返回 semnum 所代表旗语的值;

GET ZCNT  返回等待 semnum 所代表旗语的值变成 0 的进程数;

SETA LL  通过 arg.array 更新所有旗语的值;同时更新与本旗语集相关的 semid_ds 结构的 sem_ctime 成员;

SETVA L  设置 semnum 所代表旗语的值为 arg.val

共享内存编程

 

共享内存区域是被多个进程共享的一部分物理内存。如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信。

共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。

不提供任何同步功能

#include

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

功能:创建共享内存或获取一个已经存在的共享内存(shmflg =0)

返回值:成功返回共享内存标识符,失败返回 -1

参数:

key: 标识共享内存的键值。(IPC_PRIVATE, ftok())

siz e: 要建立共享内存的长度(打开已有共享内存时置 0) (n* P AG E_SI ZE)

shmflg: 指令和访问权限标志。

IPC_C REAT 如果共享内存不存在,则创建一个共享内存,否则打开操作。

IPC_EX CL 只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。

打开权限类似 open(), 相当于文件的访问权限。

 

#include

int *shmat(int shmid, const void *shmaddr, int shmflg) ;

功能:允许进程访问一块共享内存 ( 共享内存刚创建时不能使用)

返回值:成功返回共享内存的起始地址,失败返回 -1

参数:

shmid:共享内存的标识符。

shmaddr:共享内存的起始地址

shmflag:本进程对该内存的操作模式。如果是SHM_ RDONLY的话,就是只读模式。

#include

int shmdt(const v oid *shmaddr) ;

功能:释放共享内存。

返回值:成功时返回 0 。失败时返回 -1

参数:

shmaddr 是共享内存的起始地址。

 

#include

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

功能:共享内存控制函数。

返回值:成功返回0 ,失败返回-1

参数:

shmid:共享内存的ID

cmd:允许的操作, 最常用的包括:

IPC_ RMID 删除共享内存段。

buf:保存内存模式状态和访问权限的数据结构,通常为 0

 

阅读(2883) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~