当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 学习笔记 > 嵌入式学习笔记:linux进程间通信-消息队列、信号集

嵌入式学习笔记:linux进程间通信-消息队列、信号集 时间:2018-09-26      来源:未知

消息队列

概述

$消息队列是消息的链接表,包括Posix 消息队列systemV 消息队列。系统V消息队列是随内核持续的,只有在内核重起或人工删除时,该消息队列才会被删除。目前被大量使

用。

$用户可以从消息队列中添加和读取消息。具有一定的FIFO特性,但可以实现消息的随机查询

$这些消息存在于内核中,由“队列ID”来标识

¨消息队列的实现

$消息队列的实现包括创建和打开消息队列、添加消息、读取消息和控制消息队列

$创建或打开消息队列:msgget。这里创建的消息队列的数量会受到消息队列数量的

限制

$添加消息:msgsnd函数,它把消息添加到已打开的消息队列末尾

$读取消息:msgrcv,它把消息从队列中取走,与FIFO不同的是,这里可以指定取走

某一条消息

$控制消息队列:msgctl

有关的数据结构:

Øipc_perm:IPC对象的访问权限

Ømsgbuf:消息的数据类型

Ømsg:消息链表的节点结构

Ømsgqid_ds:消息队列对象的结构

消息队列相关函数: *****

#include

#include

#include

int msgget(key_t key, int flg);

入参: key:和消息队列关联的key值

flg:消息队列的访问权限

IPC_CREAT、创建新的消息队列

IPC_EXCL,与IPC_CREAT一起使用;如果要创建的消息队列已经存在,则返

回错误

IPC_NOWAIT读写消息队列要求无法得到满足时,不阻塞。

返回值: 成功 返回消息队列 ID

失败 -1

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

功能:向消息队列发送消息

入参: msqid:消息队列的ID 即msgget的返回值

msgp:指向消息的指针。常用消息结构msgbuf如下:

struct msgbuf

{

long mtype;

//消息类型

char mtext[N]

//消息正文

};

msgsz:发送的消息正文的字节数

msgflg: IPC_NOWAIT 消息没发送完立即返回

0 消息发送完成函数才会返回

返回值:

成功 0

失败 -1

int msgrcv(int msgid, void* msgp, size_t size, long msgtype, int flag); 功能: 从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中。在成功读取了一条消息以后,队列中的这条消息将被删除入参: msqid:消息队列的ID

msgp:接收消息的缓冲区

size:要接收的消息的正文字节数

msgtype: 0 :接收消息队列中第一个消息

>0: 接收mtype为msgtype第一个消息

<0: 接收消息队列中mtype不小于msgtype的绝对值,

且mtype最小的消息

flag: 0: 没有收到消息就会一直阻塞

IPC_NOWAIT :没有收到消息会立即返回

返回值: 成功:接收到的消息的长度

失败:-1

int msgctl ( int msgqid, int cmd, struct msqid_ds *buf ); 入参: msqid:消息队列的队列ID

cmd: IPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓

冲区中。

IPC_SET:设置消息队列的属性。这个值取自buf参数

IPC_RMID:从系统中删除消息队列。,buf 填NULL

buf:消息队列缓冲区

返回值: 成功 0

失败 -1

信号灯集(signal set):由一个或多个信号量构成的集合

#include

#include

#include

int semget(key_t key, int nsems, int semflg);//创建信号量入参: key ftok获取的key值

nsems 信号灯集中包含的信号灯数目

semflg:同消息队列

返回值: 成功:信号灯集的ID号(IPC标识符)

失败 -1

int semop ( int semid, struct sembuf *opsptr, size_t nops); 入参: semid semget的返回值,ID号

opsptr :结构体指针,指明对哪个信号灯进行操作 nops: 要操作的信号灯的个数

struct sembuf

{

short

sem_num;

//

要操作的信号灯的编号

short

sem_op;

0 :

等待,直到信号灯的值变成0

1 : 释放资源,V操作

short

sem_flg;

// 0,

-1 : 分配资源,P操作

IPC_NOWAIT, SEM_UNDO

};

返回值:

成功 0

失败 -1

int semctl ( int semid, int semnum, int cmd…/*union semun arg*/); 入参: semid: 信号灯集的ID号

semnum: 要修改的信号灯编号

cmd: GETVAL:获取信号灯的值

SETVAL:设置信号灯的值

IPC_RMID:从系统中删除信号灯集合

注意:semctl是可变参数函数:cmd为GETVAL或SETVAL时,需要传递第四个参数。参数类型为union semun

成功: 0 失败 : -1

union semun

{

int val; /* value for SETVAL */

structsemid_ds *buf;/* buffer for IPC_STAT & IPC_SET */

unsigned short*array;/* array for GETALL & SETALL */

structseminfo*__buf;/* buffer for IPC_INFO */

void *__pad;

};

头文件中的#ifndef

千万不要忽略了头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。

还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

#ifndef <标识>

#define <标识>

......

......

#endif

上一篇:嵌入式学习笔记: c语言入门自学知识点

下一篇:嵌入式学习笔记:linux进程通信之信号函数

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部