进程间通信2

一、消息队列

定义:unix早期通信机制之一的信号能够传送的信息量有限,管道则只能传送无格式的字节流,这无疑会给应用程序开发带来不便。消息队列(也叫做报文队列)则克服了这些缺点。

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式。进程可以向中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。

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

#include <sys/types.h>
#include <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 :标志位。
返回值:与健值 key 相对应的消息队列描述字。

msgflg的取值:

(1)IPC_CREAT
创建新的消息队列
(2)IPC_EXCL
与 IPC_CREAT 一同使用,表示如果要创建的消息队列已经存在,则返回错误。
(3)IPC_NOWAIT
读写消息队列要求无法得到满足时,不阻塞 。

在以下两种情况下,将创建一个新的消息队列:
(1)如果没有与健值 key 相对应的消息队列,并且 msgflg 中包含了 IPC_CREAT 标志位。
(2)key 参数为 IPC_PRIVATE 。

发送消息:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg)
功能:向消息队列中发送一条消息。

msqid:已打开的消息队列id
msgp:存放消息的结构
msgsz:消息数据长度(注意:是数据的长度)
msgflg:发送标志,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。

struct msgbuf
{
long mtype;/* 消息类型 > 0 */
char mtext[1]; /* 消息数据的首地址 */
};

接收消息:

#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类型的消息,并把消息存储在msgp指向的msgbuf结构中。在成功地读取了一条消息以后,队列中的这条消息将被删除。(注意:读取之后会删除,同有名管道。)

msgsz:消息的大小。
msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息。
msgtyp大于0,则返回其类型为mtype的第一个消息。
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
#include<string.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>

struct msg_buf
    {
        int mtype;
        char data[255];
    };
 
int main()
{
        key_t key;
        int msgid;
        int ret;
        struct msg_buf msgbuf;
 
        key=ftok("/tmp/2",'a');
        printf("key =[%x]\n",key);
        msgid=msgget(key,IPC_CREAT|0666); /*通过文件对应*/

        if(msgid==-1)
        {
                printf("create error\n");
                return -1;
        }
 
        msgbuf.mtype = getpid();
        strcpy(msgbuf.data,"test haha");
        ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);
        if(ret==-1)
        {
                printf("send message err\n");
                return -1;
        }
 
        memset(&msgbuf,0,sizeof(msgbuf));
        ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);
        if(ret==-1)
        {
                printf("recv message err\n");
                return -1;
        }
        printf("recv msg =[%s]\n",msgbuf.data);
 
}



二、信号量
信号量(又名:信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源。进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。
分类:
(1)二值信号灯:信号灯的值只能取0或1,类似于互斥锁。 但两者有不同:信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值;互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。
(2)计数信号灯:信号灯的值可以取任意非负值。
创建/打开:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg)
key:键值,由ftok获得
nsems:指定打开或者新创建的信号灯集中将包含信号灯的数目
semflg:标识,同消息队列。
操作:
int semop(int semid, struct sembuf *sops, unsigned nsops)
功能:对信号量进行控制。
semid :信号量集的 ID
sops :是一个操作数组,表明要进行什么操作
nsops : sops 所指向的数组的元素个数。
struct sembuf {
unsigned short sem_num; /* semaphore index in array */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
sem_num:要操作的信号量在信号量集中的编号,第一个信号的编号是0。
sem_op:如果其值为正数,该值会加到现有的信号量值中,通常用于释放信号量;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值,通常用于获取信号量;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。
Sem_flg:信号操作标志,可能的选择有两种:
(1)IPC_NOWAIT:对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。
(2)SEM_UNDO:程序结束时(不论正常或不正常)释放信号量,这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值