您的位置:首页 > 其它

国嵌视频学习第五天-进程通信2

2012-04-09 20:32 239 查看
消息队列

发展

消息队列就是一个消息的链表。可以把消息看做一个记录,具有特定的格式。进程可以向中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。(这一点有些类似于管道,数据读走了就不再在管道中了)

 

一个消息队列从实质上讲就是一个文件

分类

目前主要有两种类型的消息队列:

POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用。

持续性

系统V消息队列是随内核而持续的,只有在内核重启或者人工删除时,该消息队列才会被删除,否则将一直存在

键值

消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值(文件描述符等都是描述字)

#include <sys/types.h>

#incldue <sys/ipc.h>

key_t ftok(char* pathname, char proj)

功能:返回文件名对应的键值。

---pathname:文件名

---proj:项目名(不为0即可)

打开/创建

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgget(key_t key, int msgflg)

---key:键值,由ftok获得

---msgflg:标志位,可取:

IPC_CREAT:创建新的消息队列

IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误

IPC_NOWAIT:读写消息队列要求无法得到满足时,不阻塞。例如,某个进程向消息队列中取数据时,如果消息队列没有数据,那么该进程也不会发生阻塞

返回值:与键值key相对应的消息队列描述字

创建

在以下两种情况下,将创建一个新的消息队列:

---如果没有与键值key相对应的消息队列,并且msgflg中包含了IPC_CREAT标志位

---key参数为IPC_PRIVATE。(即只需要填一个参数)

int open_queue(key_t keyval)

{

int qid;

if((qid = msgget(keyval,IPC_CREAT)) == -1)

{return(-1);}

    return(qid);

}

发送消息

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgsnd(int msqid, struct msgbuf* msgp, int msgsz, int msgflg)

功能:向消息队列中发送一条消息(发送消息的格式是struct msgbuf。这与管道的发送是不同的,管道那里对发送的数据格式无要求)

---msqid:已打开的消息队列id

---msgp:存放消息的结构

---msgsz:消息数据长度

---msgflg:发送标志,有意义的msgflg标志位IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待(不等待)。

返回值为-1表示发送消息失败

 

消息格式

struct msgbuf

{

long mtype;//消息类型 > 0

char mtext[1];//消息数据的首地址

};

一个消息队列中可以有多种类型的消息,这些类型由mtype的取值决定,比如说1是一种类型,2又是另外一种类型。但是作为一个struct的定义,mtype的类型必须是整型

消息队列中,一个1类型的消息发出,那么想要接收该数据,则必须也指明接收的是1类型的消息(参见msgrcv函数)

接收消息

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgrcv(int msqid, struct msgbuf* msgp, int msgsz, long msgtyp, int msgflg)

功能:从msqid代表的消息队列中读取一个msgtyp类型(即是struct msgbuf结构中定义的mtype)的消息,并把消息存储在msgp指向的msgbuf结构中。在成功地读取了一条消息以后,队列中的这条消息将被删除。

返回值为-1表示接收失败

int read_message(int qid, long type, struct mymsgbuf* qbuf)

{

int result, length;

  length = sizeof(struct mymsgbuf) - sizeof(long);

if(result = msgrcv(qid, qbuf, length, type, 0) == -1)

return(-1);

return(result);

}

例msg.c

信号量

信号量(信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源(主要用于进程间的控制,如控制进程的同步、互斥等;而之前介绍的IPC主要是用于信号的传递)。进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。

 

信号量的实质是一个整数。(进程通过对信号量值的检测来判定是否能够访问共享资源。为0的时候便是不能访问该资源,进程挂起)

对该信号量-1的操作是占据该资源,对该信号量+1的操作是释放资源

 

分类

---二值信号灯:信号灯的值只能取0或1(为1表示这种资源在某一时刻最多只能由1个进程访问),类似于互斥锁。但两者有不同:信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值;互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。

---计数信号灯:信号灯的值可以取任意非负值(可以多个进程同时访问;每次自减1直至0)

 

释放信号量的时候系统自动唤醒等待访问共享资源的进程。

 

创建/打开

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

       intsemget(key_t key, int nsems, int semflg)

---key:键值,有ftok获得

---nsems:指定打开或者新创建的信号灯集中将包含信号灯的数目

---semflg:标识,同消息队列

 

操作

int semop(int semid, struct sembuf* sops. Unsignednsops )

功能:对信号量进行控制

---semid:信号量集的ID

---sops:是一个操作数组,表明要进行什么操作

---nsops:sops所指向的数组的元素个数

 

Struct sembuf{

       unsignedshort sem_num;//sem_num决定了要获取或者释放的信号量,信号量集合中的第几个(从0开始)

       shortsem_op;//要获取还是释放该信号量,如sem_op=1,则是释放该信号量

       shortsem_flg;//信号操作标志,可能的选择有两种:

                            ---IPC_NOWAIT:对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。

                            ---IPC_UNDO:程序结束时(不论正常或不正常)释放信号量,这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  struct 存储