Linux系统编程—消息队列

Linux系统编程—消息队列,第1张

消息队列本质上是位于内核空间的链表,链表的每个节点都是一条消息。每一条消息都有自己的消息类型,消息类型用整数来表示,而且必须大于 0。每种类型的消息都被对应的链表所维护:

其中数字 1 表示类型为 1 的消息,数字2、3、4 类似。彩色块表示消息数据,它们被挂在对应类型的链表上。

值得注意的是,刚刚说过没有消息类型为 0 的消息,实际上,消息类型为 0 的链表记录了所有消息加入队列的顺序,其中红色箭头表示消息加入的顺序。

无论你是发送还是接收消息,消息的格式都必须按照规范来。简单的说,它一般长成下面这个样子:

所以,只要你保证首4字节(32 位 linux 下的 long)是一个整数就行了。

举个例子:

从上面可以看出,正文部分是什么数据类型都没关系,因为消息队列传递的是 2 进制数据,不一定非得是文本。

msgsnd 函数用于将数据发送到消息队列。如果该函数被信号打断,会设置 errno 为 EINTR。

参数 msqid:ipc 内核对象 id

参数 msgp:消息数据地址

参数 msgsz:消息正文部分的大小(不包含消息类型)

参数 msgflg:可选项

该值为 0:如果消息队列空间不够,msgsnd 会阻塞。

IPC_NOWAIT:直接返回,如果空间不够,会设置 errno 为 EAGIN.

返回值:0 表示成功,-1 失败并设置 errno。

msgrcv 函数从消息队列取出消息后,并将其从消息队列里删除。

参数 msqid:ipc 内核对象 id

参数 msgp:用来接收消息数据地址

参数 msgsz:消息正文部分的大小(不包含消息类型)

参数 msgtyp:指定获取哪种类型的消息

msgtyp = 0:获取消息队列中的第一条消息

msgtyp >0:获取类型为 msgtyp 的第一条消息,除非指定了 msgflg 为MSG_EXCEPT,这表示获取除了 msgtyp 类型以外的第一条消息。

msgtyp <0:获取类型 ≤|msgtyp|≤|msgtyp| 的第一条消息。

参数 msgflg:可选项。

如果为 0 表示没有消息就阻塞。

IPC_NOWAIT:如果指定类型的消息不存在就立即返回,同时设置 errno 为 ENOMSG

MSG_EXCEPT:仅用于 msgtyp >0 的情况。表示获取类型不为 msgtyp 的消息

MSG_NOERROR:如果消息数据正文内容大于 msgsz,就将消息数据截断为 msgsz

程序 msg_send 和 msg_recv 分别用于向消息队列发送数据和接收数据。

msg_send 程序定义了一个结构体 Msg,消息正文部分是结构体 Person。该程序向消息队列发送了 10 条消息。

msg_send.c

程序 msg_send 第一次运行完后,内核中的消息队列大概像下面这样:

msg_recv 程序接收一个参数,表示接收哪种类型的消息。比如./msg_recv 4 表示接收类型为 4 的消息,并打印在屏幕。

先运行 msg_send,再运行 msg_recv。

接收所有消息

接收类型为 4 的消息

获取和设置消息队列的属性

msqid:消息队列标识符

cmd:控制指令

IPC_STAT:获得msgid的消息队列头数据到buf中

IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes

buf:消息队列管理结构体。

返回值:

成功:0

出错:-1,错误原因存于error中

EACCESS:参数cmd为IPC_STAT,确无权限读取该消息队列

EFAULT:参数buf指向无效的内存地址

EIDRM:标识符为msqid的消息队列已被删除

EINVAL:无效的参数cmd或msqid

EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

一、基本思想

Linux的基本思想有两点:

第一,一切都是文件

第二,每个软件都有确定的用途。

其中第一条详细来讲就是系统中的所有都归结为一个文件,包括命令、硬件和软件设备、 *** 作系统、进程等等对于 *** 作系统内核而言,都被视为拥有各自特性或类型的文件。

二、完全免费

Linux是一款免费的 *** 作系统,用户可以通过网络或其他途径免费获得,并可以任意修改其源代码。这是其他的 *** 作系统所做不到的。正是由于这一点,来自全世界的无数程序员参与了Linux的修改、编写工作,程序员可以根据自己的兴趣和灵感对其进行改变,这让Linux吸收了无数程序员的精华,不断壮大。

三、多用户、多任务

Linux支持多用户,各个用户对于自己的文件设备有自己特殊的权利,保证了各用户之间互不影响。多任务则是现在电脑最主要的一个特点,Linux可以使多个程序同时并独立地运行。

四、良好的界面

Linux同时具有字符界面和图形界面。在字符界面用户可以通过键盘输入相应的指令来进行 *** 作。它同时也提供了类似Windows图形界面的X-Window系统,用户可以使用鼠标对其进行 *** 作。在X-Window环境中就和在Windows中相似,可以说是一个Linux版的Windows。

五、支持多种平台

Linux可以运行在多种硬件平台上,如具有x86、680x0、SPARC、Alpha等处理器的平台。此外Linux还是一种嵌入式 *** 作系统,可以运行在掌上电脑、机顶盒或游戏机上。2001年1月份发布的Linux 2.4版内核已经能够完全支持Intel 64位芯片架构。同时Linux也支持多处理器技术。多个处理器同时工作,使系统性能大大提高。

六、结构特点

①采用阶层式目录结构,文件归类清楚、容易管理

② 支持多种文件系统,如Ext2FS,ISOFS以及Windows的文件系统FAT16,FAT32,NTFS等

③具有可移植性,系统核心只有小于10%的源代码采用汇编语言编写,其余均是采用C语言编写,因此具备高度移植性

④可与其它的 *** 作系统如Windows98/2000/XP等并存于同一台计算机上

七、四个重要部分

内核、Shell、文件系统和应用程序。

①Linux内核:内核是系统的“心脏”,是运行程序和管理磁盘、打印机等硬件设备的核心程序。

附:Linux内核

Linux是最受欢迎的自由电脑 *** 作系统内核。它是一个用C语言写成,符合POSIX标准的类Unix *** 作系统。 技术上说Linux是一个内核。“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。一个内核不是一套完整的 *** 作系统。一套基于Linux内核的完整 *** 作系统叫作Linux *** 作系统,或是GNU/Linux。

Linux是一个一体化内核系统。设备驱动程序可以完全访问硬件。Linux内的设备驱动程序可以方便地以模块化的形式设置,并在系统运行期间可直接装载或卸载。

②Linux Shell:Shell是系统的用户界面,提供了用户与内核进行交互 *** 作的一种接口。它接受用户输入的命令,并对其进行解释,最后送入内核去执行,实际上就是一个命令解释器。人们也可以使用Shell编程语言编写Shell程序,这些Shell程序与用其他程序设计语言编写的应用程序具有相同的效果。

③Linux 文件系统:文件系统是文件存放在磁盘等存储设备上的组织方法。Linux的文件系统呈树型结构,同时它也能支持目前流行的文件系统,如:EXT2、EXT3、FAT、VFAT、NFS、SMB等。

④Linux 应用程序:同Windows *** 作系统一样,标准的Linux也提供了一套满足人们上网、办公等需求的程序集即应用程序,包括文本编辑器、X Windows、办公套件、Internet工具、数据库等。

make命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接程序。

首先,我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有8个C文件,和3个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是:

1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。

2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。

3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。

一、Makefile的规则

在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。

target ... : prerequisites ...

command

...

...

target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。(任意的Shell命令)

是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说

白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是

Makefile的规则。也就是Makefile中最核心的内容。

说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。呵呵。还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。:)

二、一个示例

正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。

edit : main.o kbd.o command.o display.o /

insert.o search.o files.o utils.o

cc -o edit main.o kbd.o command.o display.o /

insert.o search.o files.o utils.o

main.o : main.c defs.h

cc -c main.c

kbd.o : kbd.c defs.h command.h

cc -c kbd.c

command.o : command.c defs.h command.h

cc -c command.c

display.o : display.c defs.h buffer.h

cc -c display.c

insert.o : insert.c defs.h buffer.h

cc -c insert.c

search.o : search.c defs.h buffer.h

cc -c search.c

files.o : files.c defs.h buffer.h command.h

cc -c files.c

utils.o : utils.c defs.h

cc -c utils.c

clean :

rm edit main.o kbd.o command.o display.o /

insert.o search.o files.o utils.o

斜杠(/)是换行符的意思。这样比较便于Makefile的易读。我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,

然后在该目录下直接输入命令“make”就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make

clean”就可以了。

在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件

(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件

edit 的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。

在定义好依赖关系

后,后续的那一行定义了如何生成目标文件的 *** 作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命

令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的

日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。

这里要说明一点的是,clean不是一个文件,它只不过

是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。

要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编

译无关的命令,比如程序的打包,程序的备份,等等。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7127062.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-01
下一篇 2023-04-01

发表评论

登录后才能评论

评论列表(0条)

保存