晚上在FC4下调试出了第一个linux程序,成功地运行,有点成就感,虽然这个程序是抄过来.

本程序的功能是利用系统V(Sys V)消息队列来实现进程间的通信(IPC).

简单地介绍程序:

用到的一个数据结构-------消息,用一个结构体来表示:

struct msgbuf

{

long

mtype;

//

消息的类型

char

mtext[

1

];

//

消息的内容,并不是表示只存一个字符

}

;

几个API:

key_t ftok (char*pathname, char proj);

它返回与路径pathname相对应的一个键值。该函数不直接对消息队列操作,但在调用msgget()来获得消息队列描述字前,往往要调用该函数。典型用法   key=ftok('.', 'a');

int msgget(key_t key, int msgflg)     参数key是一个键值,由ftok获得;msgflg参数是一些标志位。该调用返回与健值key相对应的消息队列描述字。

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

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

key参数为IPC_PRIVATE;

参数msgflg可以为以下:IPC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或结果。

调用返回:成功返回消息队列描述字,否则返回-1。

int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);该系统调用从msgid代表的消息队列中读取一个消息,并把消息存储在msgp指向的msgbuf结构中。

msqid为消息队列描述字;消息返回后存储在msgp指向的地址,msgsz指定msgbuf的mtext成员的长度(即消息内容的长度),msgtyp为请求读取的消息类型;读消息标志msgflg可以为以下几个常值的或:

IPC_NOWAIT 如果没有满足条件的消息,调用立即返回,此时,errno=ENOMSG

IPC_EXCEPT 与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息

IPC_NOERROR 如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。

msgrcv手册中详细给出了消息类型取不同值时(>0; <0; =0),调用将返回消息队列中的哪个消息。

msgrcv()解除阻塞的条件有三个:

消息队列中有了满足条件的消息;

msqid代表的消息队列被删除;

调用msgrcv()的进程被信号中断;

调用返回:成功返回读出消息的实际字节数,否则返回-1。

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

向msgid代表的消息队列发送一个消息,即将发送的消息存储在msgp指向的msgbuf结构中,消息的大小由msgze指定。

对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。造成msgsnd()等待的条件有两种:

当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量;

当前消息队列的消息数(单位"个")不小于消息队列的总容量(单位"字节数"),此时,虽然消息队列中的消息数目很多,但基本上都只有一个字节。

msgsnd()解除阻塞的条件有三个:

不满足上述两个条件,即消息队列中有容纳该消息的空间;

msqid代表的消息队列被删除;

调用msgsnd()的进程被信号中断;

调用返回:成功返回0,否则返回-1。

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

该系统调用对由msqid标识的消息队列执行cmd操作,共有三种cmd操作:IPC_STAT、IPC_SET 、IPC_RMID。

IPC_STAT:该命令用来获取消息队列信息,返回的信息存贮在buf指向的msqid结构中;

IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf指向的msqid结构中;可设置属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同时,也影响msg_ctime成员。

IPC_RMID:删除msqid标识的消息队列;

调用返回:成功返回0,否则返回-1。

#include

<

stdio.h

>

#include

<

stdlib.h

>

#include

<

ctype.h

>

#include

<

sys

/

ipc.h

>

#include

<

sys

/

types.h

>

#include

<

sys

/

msg.h

>

#define

MAX_SEND_SIZE 80

struct

mymsgbuf

{

long

mtype;

char

mtext[MAX_SEND_SIZE];

}

;

void

send_message(

int

qid,

struct

mymsgbuf

*

qbuf,

long

type,

char

*

text);

void

read_message(

int

qid,

struct

mymsgbuf

*

qbuf,

long

type);

void

remove_queue(

int

qid);

void

change_queue_mode(

int

qid,

char

*

mode);

void

usage(

void

);

int

main(

int

argc,

char

*

argv[])

{

    key_t key;

int

msgqueue_id;

struct

mymsgbuf qbuf;

if

(

1

==

argc)

        usage();

    key

=

ftok(

"

.

"

,

'

m

'

);

if

((msgqueue_id

=

msgget(key,IPC_CREAT

|

0660

))

==-

1

)

{

        perror(

"

msgget

"

);

        exit(

1

);

    }

switch

(tolower(argv[

1

][

0

]))

{

case

'

s

'

:send_message(msgqueue_id,(

struct

mymsgbuf

*

)

&

qbuf,

                    atol(argv[

2

]),argv[

3

]);

break

;

case

'

r

'

:read_message(msgqueue_id,

&

qbuf,atol(argv[

2

]));

break

;

case

'

d

'

:remove_queue(msgqueue_id);

break

;

case

'

m

'

:change_queue_mode(msgqueue_id,argv[

2

]);

break

;

default

:usage();

    }

return

0

;

}

void

send_message(

int

qid,

struct

mymsgbuf

*

qbuf,

long

type,

char

*

text)

{

    printf(

"

send a message

\n

"

);

    qbuf

->

mtype

=

type;

    strcpy(qbuf

->

mtext,text);

if

((msgsnd(qid,(

struct

msgbuf

*

)qbuf,strlen(qbuf

->

mtext)

+

1

,

0

))

==-

1

)

{

        perror(

"

msgsnd

"

);

        exit(

1

);

    }

}

void

read_message(

int

qid,

struct

mymsgbuf

*

qbuf,

long

type)

{

    printf(

"

reading a message

.\n

"

);

    qbuf

->

mtype

=

type;

    msgrcv(qid,(

struct

msgbuf

*

)qbuf,MAX_SEND_SIZE,type,

0

);

    printf(

"

Type: %1d Text: %s\n

"

,qbuf

->

mtype,qbuf

->

mtext);

}

void

remove_queue(

int

qid)

{

    msgctl(qid,IPC_RMID,

0

);

}

void

change_queue_mode(

int

qid,

char

*

mode)

{

struct

msqid_ds myqueue_ds;

    msgctl(qid,IPC_STAT,

&

myqueue_ds);

    sscanf(mode,

"

%ho

"

,

&

myqueue_ds.msg_perm.mode);

    msgctl(qid,IPC_SET,

&

myqueue_ds);

}

void

usage(

void

)

{

    fprintf(stderr,

"

msgtool -A utility for tinkering with msg queue\n

"

);

    fprintf(stderr,

"

\nUSAGE:msgtool (s)end  \n

"

);

    fprintf(stderr,

"

(r)ecv\n

"

);

    fprintf(stderr,

"

(d)elete\n

"

);

    fprintf(stderr,

"

(m)ode\n

"

);

    exit(

1

);

}

以上程序编译能通过,只是出现了两个warning

warning:内建函数strcpy不兼容的隐式声明

warning:内建函数strlen不兼容的隐式声明

不知是什么原因?是不是gcc版本问题?

还有在写Makefile后,make时出现一个错误提示:

commands commence before first target

解决方法:去掉target的空格(tab键)

程序来是http://tldp.org/LDP/lpg/node45.html#SECTION00742640000000000000

API解释来自http://www.52wg.org/computer/chengxu/200511/computer_98386.html

java linux 消息队列_我的第一个Linux程序----利用消息队列来实现IPC相关推荐

  1. 在Linux环境下用C语言编写一个乘法程序mult,从命令行接收两个数字,然后输出其乘积;再用C语言编写一个exec1程序,在程序中使用execvp调用mult程序计算5与10的乘积。

    在Linux环境下用C语言编写一个乘法程序mult,从命令行接收两个数字,然后输出其乘积:再用C语言编写一个exec1程序,在程序中使用execvp调用mult程序计算5与10的乘积. 1.mult. ...

  2. java 头尾 队列_源码|jdk源码之栈、队列及ArrayDeque分析

    栈.队列.双端队列都是非常经典的数据结构.和链表.数组不同,这三种数据结构的抽象层次更高.它只描述了数据结构有哪些行为,而并不关心数据结构内部用何种思路.方式去组织. 本篇博文重点关注这三种数据结构在 ...

  3. fseek linux 大文件_一文搞懂Linux系统开发

    文章目录 Linux系统开发会用到什么? C语言基础 shell脚本 慢慢学会使用Makefile 常规Linux系统编程知识都有什么?哪些常用?哪些不常用? 常规Linux编程知识 文件IO 文件与 ...

  4. java推送微信消息换行_5行代码实现微信小程序模版消息推送 (含推送后台和小程序源码)...

    我们在做小程序开发时,消息推送是不可避免的.今天就来教大家如何实现小程序消息推送的后台和前台开发.源码会在文章末尾贴出来. 其实我之前有写过一篇:<springboot实现微信消息推送,java ...

  5. kali linux超级用户_如何优雅的在Linux上使用Powershell]

    点击上方"蓝字"关注我们吧! 译文声明 本文是翻译文章,文章原作者 TJ Null 文章来源:https://www.offensive-security.com 原文地址: ht ...

  6. 假设以带头结点的循环链表表示队列_真香!20张图揭开「队列」的迷雾,一目了然...

    https://mp.weixin.qq.com/s/GYQrxBOasKpvF4uZsMdOSw​mp.weixin.qq.com 队列的概念 首先我们联想一下链表,在单链表中,我们只能对他的链表表 ...

  7. linux dns 刷新_如何为Windows和Linux操作系统刷新DNS?

    linux dns 刷新 Operating systems like Windows, Linux, BSD runs some mechanisms to cache DNS records in ...

  8. linux 线程迁移_迁移线程如何在Linux内核内部工作

    linux 线程迁移 Abstract In computer systems, resources have to be balanced so that the performance will ...

  9. linux 版本号 笔记本_在笔记本电脑上安装Linux完全版

    当前,笔记本电脑越来越多地成为工程师.技术人员的标准 办公配置.随着Linux操作系统影响的逐步深入,许许多多的Linux使用者希望能够在自己的笔记本电脑上运行Linux操作系统,以便随时随地地使用. ...

  10. linux 版本号 笔记本_观点|2018 年度最佳 Linux 笔记本电脑:来自一位 RHCE 的选购指南...

    如果你不具备相关的知识和经验,挑选出最适合 Linux 的笔记本电脑,可能是件很困难的事.并且,看上去你买了一台配置.功能.性能都很棒的电脑,但是,却疲于处理各种 Linux 的问题,太难堪了!因此, ...

最新文章

  1. java语言解析XML
  2. Java 集合系列(3): fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)...
  3. 【机器学习】太赞了!几行代码实现30多种时序模型预测
  4. 二. linux基础命令
  5. curviloft插件怎么用_完结篇——你想要的逆天插件系列这里都有
  6. html5 video标签兼容性与自定义控件
  7. 软件类配置(四)【ubuntu16.04安装pycahrm】
  8. java被oracle收购,sun被oracle收购了,openoffice和virtualbox会不会死?
  9. Jenkins + Docker 简单部署 node.js 项目
  10. mysql python用法_python-mysql基本用法
  11. 【mitmproxy手机端App抓包】
  12. python中一元二次方程的判别式_【Python算法作业】解一元二次方程
  13. html和jQuery实现一个开心小农场游戏
  14. atomic原子类实现机制_atomic实现原理
  15. VMC(VMware on AWS)分析
  16. 计算机专业相关的组名和口号,课堂小组霸气组名和口号大全
  17. 以太坊系列(二)---Ubuntu20.04安装以太坊开发环境并建立私有链
  18. Android Q访问公共外部存储受限
  19. 转载 PVE 防火墙
  20. BACnet安全连接(BACnet/SC) 介绍

热门文章

  1. Xcode12.5 iPhone 模拟器无法直接安装Charles证书
  2. 准备给ubuntu18.04安装杀毒软件
  3. ctf解密图片得到flag_图片隐藏flag怎么找
  4. 20年前的网文:我彷徨在唯物主义和唯心主义之间
  5. windows聚焦壁纸不更新_如何解决Win10聚焦锁屏壁纸不自动更新的问题
  6. ERP系统成本计算方法大揭秘?
  7. 开发APP需要准备哪些工作
  8. 速记JVM内存模型和垃圾回收策略
  9. dos模拟器即时存档工具_DOS模拟器app
  10. DDOS防火墙新一代操作思路与进阶应用方法浅析