在linux下的多个进程间的通信机制叫做IPC(Inter-Process Communication)
进程间通信可以有多种方式
- 管道 (PIPE)
- 命名管道 (FIFO)
- 消息队列 (Message queues)
- 信号 (signal)
- 信号量 (Semaphore)
- 共享内存 (Share Memory)
- 内存映射文件 (Memory Map)
- 套接字(socket)
每种方式各有利弊,比如管道(PIPE)只能在父子进程中使用,并且仅限半双工模式。
本节主要介绍比较灵活的 消息队列mqueue
主要函数:
mqd_t mq_open (const char *__name, int __oflag, ...);
name:"/mq_test" ,创建消息队列的名字
oflag:文件属性,和open函数的类似。有必须的选项:O_RDONLY,O_WRONLY,O_RDWR,还有可选的选项:O_NONBLOCK,O_CREAT,O_EXCL。
…:附加参数,主要用户创建时候,描述队列的大小以及允许的个数。也可以为空,系统则采用默参数
int mq_close (mqd_t __mqdes);
int mq_unlink (const char *__name);
mq_close :关闭消息队列文件描述,但不能删除
mq_unlink :删除消息队列文件
ssize_t mq_receive (mqd_t __mqdes, char *__msg_ptr, size_t __msg_len,
unsigned int *__msg_prio);
int mq_send (mqd_t __mqdes, const char *__msg_ptr, size_t __msg_len,
unsigned int __msg_prio);
__msg_prio:消息优先级,数据越大,优先级越大!
mq_receive :如果open设置了O_NONBLOCK参数,则读取失败后,会立即返回-1,不会阻塞。
消息队列是以文件的形式存在
当新建了一个消息队列后,mq_open("/mq_test", O_CREAT|O_RDWR, FILE_MODE);
可以在系统中查看,该消息队列对应的文件
eric@eric-PC:/dev/mqueue$ ls -l
总用量 0
-rw-r--r-- 1 eric eric 80 5月 7 14:47 mq_test
发送程序
send.c
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
// send 线程
void thread_send(void *arg)
{
int i,ret;
char buf[128];
printf("%s,PID=%d\n",__func__,getpid());
struct mq_attr attr, new_attr, old_attr;
attr.mq_maxmsg = 10; //最大消息10个
attr.mq_msgsize = 128; //每个消息限制大小128字节
attr.mq_flags = 0;
mqd_t mqd = mq_open("/mq_test", O_CREAT|O_RDWR, FILE_MODE, &attr);
if(-1 == mqd)
{
perror("mq_open error");
return 0;
}
//测试:发送8次数据
for ( i=0; i<8; i++)
{
printf("Thread working...! %d \n",i);
sprintf(buf,"send-%d",i);
ret = mq_send(mqd, buf, strlen(buf), 2);
if(ret == -1)
{
perror("mq_send error");
}
sleep(2);
}
mq_close(mqd);
printf("[%s]end\n",__func__);
exit(0);
}
int main(void)
{
pthread_t mythread1,mythread2;
if ( pthread_create( &mythread1, NULL, thread_send, &mqd) )
{
printf("error creating thread.");
abort();
}
if ( pthread_join ( mythread1, NULL ) )
{
printf("error join thread.");
abort();
}
printf("thread done! \n");
exit(0);
}
接收程序
receive.c
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
// receive线程
void thread_receive(void *arg)
{
int i,ret;
char buf[128];
int prio=0;
printf("%s,PID=%d\n",__func__,getpid());
struct mq_attr attr, new_attr, old_attr;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 128;
attr.mq_flags = 0;
mqd_t mqd = mq_open("/mq_test", O_CREAT|O_RDWR|O_NONBLOCK, FILE_MODE, &attr);
if(-1 == mqd)
{
perror("mq_open error");
return 0;
}
do
{
memset(buf,0,sizeof(buf));
ret = mq_receive(mqd, buf, sizeof(buf), &prio);
if (ret !=-1)
{
printf("ret=%d\n",ret);
printf("read:%s\n",buf);
}
} while (ret);
mq_close(mqd);
printf("[%s]end\n",__func__);
}
int main(void)
{
pthread_t mythread1,mythread2;
if ( pthread_create( &mythread2, NULL, thread_receive, &mqd) )
{
printf("error creating thread.");
abort();
}
if ( pthread_join ( mythread2, NULL ) )
{
printf("error join thread.");
abort();
}
printf("thread done! \n");
exit(0);
}
测试现象
发送:
eric@eric-PC:~/Documents/work/linux-c/mq/mq_send$ ./main
thread_send,PID=14976
Thread working...! 0
Thread working...! 1
Thread working...! 2
Thread working...! 3
Thread working...! 4
Thread working...! 5
Thread working...! 6
Thread working...! 7
[thread_send]end
接收:
eric@eric-PC:~/Documents/work/linux-c/mq/mq_receive$ ./main
thread_receive,PID=14972
ret=6
read:send-0
ret=6
read:send-1
ret=6
read:send-2
ret=6
read:send-3
ret=6
read:send-4
ret=6
read:send-5
ret=6
read:send-6
ret=6
read:send-7
^C
----------------------------------------------------仅此记录------------------------------------------------