linux 消息队列

管道:没有数据的类型,数据遵守“先进先出”的原则。  
消息队列:加强型的管道,他可以指定存放的数据类型,与取走的数据类型,方便不同进程取数据。

消息队列,共享内存,信号量:属于system V(5) 版本的进程通信,也叫ipc通信对象,除了system V进程间的通信外,我们还有POSIX版本的。

查看system V (5)版本的通信对象命令:  
查看消息队列:  ipcs -q  
查看共享内存:  ipcs -m
查看信号量:     ipcs -s  

查看全部:ipcs -a

删除消息队列: 
ipcrm  -q   (对象ID)
ipcrm  -Q    (键值)

消息队列的信息
--------- 消息队列 -----------
键        msqid      		拥有者  权限     已用字节数 消息      
(KEY值)(消息队列通信对象)

//如何创建消息队列  
1.创建KEY值 
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);//proj_id ->不能超过255
							                
2.获取消息队列通信对象ID
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
参数一:键值key  
参数二:权限  
	  IPC_CREAT 创建
	  IPC_EXCL  检查是否存在
	  mode      0666
	  返回值:成功 返回 对象ID 
	  失败 返回 -1
					
3.进行数据的交互 
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>	  
//发送
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数一:需要发送的消息队列ID
参数二:数据缓存区  
参数三:数据的大小 
参数四: 是否阻塞  
		0   阻塞  
		IPC_NOWAIT   不阻塞
		返回值: 成功返回 0  
		失败返回 -1
					 		
PS,PS,PS 注意!!!! 
数据的缓冲区必须要定义为如下结构体: 
struct msgbuf {
      long mtype;       /*数据类型必须大于0, must be > 0 */
      char mtext[1];    /*数据,该数组的长度任意定义*/
};

//读取   
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
//参数一:对象ID  
//参数二:数据的缓存区  
//参数三:需要获取的数据大小  
//参数四:数据的类型  
参数五:是否阻塞  
	  0   阻塞  
	  IPC_NOWAIT   不阻塞
	  返回值: 成功返回  读到的数据大小 
	  失败返回 -1
			 
4.销毁消息队列  
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>			
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数一:对象ID
参数二:控制命令     	IPC_RMID  -》删除  
参数三:设置 获取的时候使用 
	   返回值:成功 0 
	   失败 -1
			        
---------------------------------信号量---------------------------------------------------------------
信号量的作用: 保护共享资源防止进程之间的竞争。  
信号量的版本分为两种:1.SYSTEM V  2.POSIX  (有名 无名)
posix :有名信号量用于不同进程之间的数据保护 
posix : 无名信号量用于不同线程之间的数据保护

POSIX版本的有名信号量的使用:   记得添加 posix的库文件   	-lpthread
							
1. 创建信号量对象 
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);  //直接打开信号量
//参数一:创建的信号量路径   (路径只能是 /目录下的 例如:/sem  /sem1)
//参数二:权限 
		 O_CREAT  -》创建 
		 O_EXCL   -》检查是否存在
//返回值:成功返回   信号地址
		 打开失败  SEM_FAILED
						
//带创建打开并赋值			
sem_t *sem_open(const char *name, int oflag,	  //直接打开信号量并赋值
                mode_t mode, unsigned int value);
                       
2.对信号量进行P  V 操作  
p操作申请资源   -1 -> sem_wait(3), 等待申请
v操作释放资源   +1 -> sem_post(3), 释放
		
int sem_wait(sem_t *sem);  //当申请的资源值为0时,函数阻塞!!
int sem_post(sem_t *sem);  
参数一:需要操作的信号量指针
返回值:成功0 
	  失败-1
			   
获取信号量的值: 
#include <semaphore.h>
int sem_getvalue(sem_t *sem, int *sval);
参数一:需要获取的信号量指针
参数二:获取后的值保存的地方
返回值:成功 0 
	  失败 -1
							   
关闭信号量
#include <semaphore.h>
int sem_close(sem_t *sem);
		 
销毁信号量
int sem_unlink(const char *name);
//msg_send.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h> //错误宏
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

struct msgbuf 
{
   long mtype; 
   char mtext[1024];
};

int main()
{
	//创建一个对象的KEY值 
    key_t key=ftok("/home/gec",66);
	if(key < 0)
	{
		perror("");
		exit(0);
	}

		
	int msgid=0;
label:	 
	//获取消息队列的对象ID 
	msgid=msgget(key,IPC_CREAT|IPC_EXCL|0666);
	if(msgid < 0)
	{
		//perror("creat fail\n");
		//处理错误信息 
		if(errno == EEXIST)
		{
			//printf("对象ID已经存在啦!\n");
			//删除
			char del[1024]={0};
			sprintf(del,"ipcrm  -Q %d",key);
			system(del);
			
			goto label;
		}
	}
	else 
	{
		printf("创建消息队列成功\n");
	}
	struct msgbuf  date;  
	date.mtype = 123; //设置类型 
	//date.mtext = "hello world";
	
	while(1)
	{
		//数据的发送
		scanf("%s",date.mtext);
		msgsnd(msgid,&date,strlen(date.mtext),0);
	}
	
	//销毁消息队列  
	msgctl(msgid,IPC_RMID,NULL);
	return 0;
}
//msg_recv.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h> //错误宏
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

struct msgbuf 
{
   long mtype; 
   char mtext[1024];
};

int main(int argc,char *argv[])
{
	//创建一个对象的KEY值 
    key_t key=ftok("/home/gec",66);
	if(key < 0)
	{
		perror("");
		exit(0);
	}

	//获取消息队列的对象ID 
	int msgid=msgget(key,IPC_CREAT|0666);
	if(msgid < 0)
	{
		perror("creat fail\n");
	}
	else 
	{
		printf("创建消息队列成功\n");
	}
		
	//读取消息队列中的数据
	while(1)
	{	
		struct msgbuf  date;
		bzero(&date,sizeof(date));		
		msgrcv(msgid,&date,sizeof(date),123,0);
		printf("date = %s\n",date.mtext);
	}
		
	//销毁消息队列  
	msgctl(msgid,IPC_RMID,NULL);
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值