2014025674(16) 《嵌入式系统程序设计》第七周学习总结

本周学习了第八章的主要内容主要包括两大部分分别为:

一、有名管道FIFO

1.有名管道说明

  • 定义:有名管道的出现突破了只能用于具有亲缘关系的进程之间,这就大大地限制了管道的使用限制,它可以使互不相关的两个进程实现彼此通信。该管道可以通过路径名来指出, 并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作, 使用非常方便。
  • 注意:FIFO 是严格地遵循先进先出规则的,对管道及 FIFO 的读总是从开始 处返回数据,对它们的写则把数据添加到末尾,它们不支持如 lseek()等文件定位操作。 有名管道的创建可以使用函数 mkfifo(),该函数类似文件中的 open()操作,可以指定管道的路径和打开的模式。
  • 对阻塞打开和非阻 塞打开的读写进行讨论:

(1)对于读进程。

若该管道是阻塞打开,且当前 FIFO 内没有数据,则对读进程而言将一直阻塞到有数据写入。

若该管道是非阻塞打开,则不论 FIFO 内是否有数据,读进程都会立即执行读操作。即如果 FIFO 内没有数据,则读函数将立刻返回 0。

(2)对于写进程。

若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。

若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。

2.mkfifo()函数格式

  • mkfifo()函数语法要点

  • FIFO 相关的出错信息

3.使用实例

  • 以下是写管道的程序:
/* fifo_write.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MYFIFO "/tmp/myfifo" /* 有名管道文件名*/
#define MAX_BUFFER_SIZE PIPE_BUF /*定义在于 limits.h 中*/
int main(int argc, char * argv[]) /*参数为即将写入的字符串*/
{
 int fd;
 char buff[MAX_BUFFER_SIZE];
 int nwrite;

 if(argc <= 1)
 {
 printf("Usage: ./fifo_write string\n");
 exit(1);
 }
 sscanf(argv[1], "%s", buff);

 /* 以只写阻塞方式打开 FIFO 管道 */
 fd = open(MYFIFO, O_WRONLY);
 if (fd == -1)
 {
 printf("Open fifo file error\n");
 exit(1);
 }
 /*向管道中写入字符串*/
 if ((nwrite = write(fd, buff, MAX_BUFFER_SIZE)) > 0)
 {
 printf("Write ‘%s‘ to FIFO\n", buff);
 }
 close(fd);
 exit(0);
}

 

  • 以下是读管道程序:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define MYFIFO "/tmp/myfifo" /* 有名管道文件名*/
#define MAX_BUFFER_SIZE PIPE_BUF /*定义在于 limits.h 中*/
int main()
{
 char buff[MAX_BUFFER_SIZE];
 int fd;
 int nread;
 /* 判断有名管道是否已存在,若尚未创建,则以相应的权限创建*/
 if (access(MYFIFO, F_OK) == -1)
 {
 if ((mkfifo(MYFIFO, 0666) < 0) && (errno != EEXIST))
 {
 printf("Cannot create fifo file\n");
 exit(1);
 }
 }
 /* 以只读阻塞方式打开有名管道 */
 fd = open(MYFIFO, O_RDONLY);
 if (fd == -1)
 {
 printf("Open fifo file error\n");
 exit(1);
 }

 while (1)
 {
 memset(buff, 0, sizeof(buff));
 if ((nread = read(fd, buff, MAX_BUFFER_SIZE)) > 0)
 {
 printf("Read ‘%s‘ from FIFO\n", buff);
 }
 }
 close(fd);
 exit(0);
}

  

二、消息队列

1. 消息队列概述

  • 顾名思义,消息队列就是一些消息的列表。用户可以从消息队列中添加消息和读取消息等。从这点上看, 消息队列具有一定的 FIFO 特性,但是它可以实现消息的随机查询,比 FIFO 具有更大的优势。同时,这些消息又是存在于内核中的,由“队列 ID”来标识。

2. 消息队列的应用

(1)函数说明

消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列这 4 种操作。其中创建 或打开消息队列使用的函数是 msgget(),这里创建的消息队列的数量会受到系统消息队列数量的限制; 添加消息使用的函数是 msgsnd()函数,它把消息添加到已打开的消息队列末尾;读取消息使用的函数是 msgrcv(),它把消息从消息队列中取走,与 FIFO 不同的是,这里可以指定取走某一条消息;最后控制消息队列使用的函数是 msgctl(),它可以完成多项功能。

(2)函数格式

  • msgget()函数的语法要点。

  • msgsnd()函数的语法要点。

3.使用实例

  • 消息队列发送端的代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 512
struct message
{
 long msg_type;
 char msg_text[BUFFER_SIZE];
};
int main()
{
 int qid;
 key_t key;
 struct message msg;

 /*根据不同的路径和关键字产生标准的 key*/
 if ((key = ftok(".", ‘a‘)) == -1)
 {
 perror("ftok");
 exit(1);
 }

 /*创建消息队列*/
 if ((qid = msgget(key, IPC_CREAT|0666)) == -1)
 {
 perror("msgget");
 exit(1);
 }
 printf("Open queue %d\n",qid);

 while(1)
 {
 printf("Enter some message to the queue:");
 if ((fgets(msg.msg_text, BUFFER_SIZE, stdin)) == NULL)
 {
 puts("no message");
 exit(1);
 }

 msg.msg_type = getpid();

 /*添加消息到消息队列*/
 if ((msgsnd(qid, &msg, strlen(msg.msg_text), 0)) < 0)
 {
 perror("message posted");
 exit(1);
 }

 if (strncmp(msg.msg_text, "quit", 4) == 0)
 {
 break;
 }
 }
 exit(0);
}
  • 以下是消息队列接收端
#include <sys/types.h>#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 512
struct message
{
 long msg_type;
 char msg_text[BUFFER_SIZE];
};
int main()
{
 int qid;
 key_t key;
 struct message msg;

 /*根据不同的路径和关键字产生标准的 key*/
 if ((key = ftok(".", ‘a‘)) == -1)
 {
 perror("ftok");
 exit(1);
 }

 /*创建消息队列*/
 if ((qid = msgget(key, IPC_CREAT|0666)) == -1)
 {
 perror("msgget");
 exit(1);
 }
 printf("Open queue %d\n", qid);

 do
 {
 /*读取消息队列*/
 memset(msg.msg_text, 0, BUFFER_SIZE);
 if (msgrcv(qid, (void*)&msg, BUFFER_SIZE, 0, 0) < 0)
 {
 perror("msgrcv");
 exit(1);
 }
 printf("The message from process %d : %s", msg.msg_type, msg.msg_text);

 } while(strncmp(msg.msg_text, "quit", 4));

 /*从系统内核中移走消息队列 */
 if ((msgctl(qid, IPC_RMID, NULL)) < 0)
 {
 perror("msgctl");
 exit(1);
 }

 exit(0);
}
时间: 2024-10-13 03:09:31

2014025674(16) 《嵌入式系统程序设计》第七周学习总结的相关文章

2014025670(12)《嵌入式系统程序设计》第二周学习总结

这周学习了gcc和gdb的使用还有makefile. 教材学习内容总结 教材内容开始看的有些吃力,很多地方都不太懂,网上查询和询问同学和老师之后,了解了很多,但是具体操作和实现方面还是比较难. 教材学习中问题和解决过程 对于gcc的操作在实验楼的学习中还是比较顺利,gdb的操作感觉有些村存在问题-----gdb的调试方面有些吃力,应该是自己没努力的结果,打算把问题汇总一下,再试试实验. 课后作业中的问题和解决过程 应用实验楼的第二周,第一周的内容感觉简单,消化很快,没想到第二周就感觉有些吃力,不

2014025663(05)《嵌入式系统程序设计》第二周学习总结

教材学习内容总结 在这一周里我通过课上与课下熟悉了VI编辑器的各种操作.gcc的有效应用,通过gcc来编译C语言程序!其主要分为4大步分为预处理.编译.汇编和链接. 也学会了Makefile的使用! 教材学习中的问题和解决过程 本周的出现的主要问题在于 GCC前不能加除Tab外任何东西,否则会影响到文件的编译! 代码调试中的问题和解决过程 代码暂时没有什么问题! 课后作业中的问题和解决过程 我在多次使用与试用!成功了解博客园 实验楼 网站! 其他(感悟.思考等,可选) 我们要对学校这门课有足够的

2014025660《嵌入式系统程序设计》第二周学习总结

本周学习过程中,学习运用gcc和gdb的编程,在实验过程中,编辑c文件,对文件类型进行转换,由于实验过程中,代码出现了错误,浪费了大量的时间查找代码的错误. 在Makefile的实验过程中,运用vi分别编辑hello.c文件hello.h,以及Makefile文件,最后运应用make -f makefile1显示 make hello是最新的.

2014025658《嵌入式系统程序设计》第二周学习总结

本周所学内容如下: 1.学会使用gcc编译器: 2.学会使用GDB调试器: 3.学会C程序的编写(包括系统调用和函数调用) 4.学会Makefile基本规则: 5.学会make命令的使用方法: 6.学会使用Makefile程序的编写. 7.使用gcc编译器编译C语言程序文件生成可执行文件的过程,是要经历四个相互关联的步骤:预处理.编译.汇编和链接. 8.gdb是GNU开源组织开发的一个强大的Linux下的程序调试工具,它主要完成:启动被调试程序,按照要求运行程序.让被调试的程序在指定的位置停住.

2014025644 嵌入式程序设计 第七周学习总结

嵌入式程序设计 第七周 有名管道 有名管道和无名管道的区别 (1) 无名管道:管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道:只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程). 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出.写入的内容每次都添加在管道缓冲区的末尾,并且每次都是

2014025689 嵌入式程序设计 第七周学习总结

嵌入式程序设计 第七周   第七周课程主要学习了有名管道和消息队列的传输和接收.   一丶有名管道   有名管道和无名管道的区别: 1.  有名管道定义:可以使互不相关的两个进程实现彼此通信的管道就是有名管道.有名管道可以通过路径名来指出,并且在文件系统中是可见的.在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便.不过值得注意的是,FIFO 是严格地遵循先进先出规则的,对管道及 FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如 lsee

嵌入式系统程序设计第三周实验总结

第三周是我相对于前两周收获的最多的一周,我开始认真听课,老师上课让跟着打的程序也能很好的跟上,不再说都不会不听了或者怎么样的 实验楼第二次做还是有点不太熟悉但是一些基本的东西都能操作 本次实验楼的程序结果如下

2014025689 《嵌入式系统程序设计》第五周学习总结

<嵌入式系统程序设计>第五周学习总结 一.6.5(标准I/O编程)主要涉及的函数及知识点 标准的I/O的三种缓冲存储:全缓冲.行缓冲.不带缓冲. 1. 全缓存:当填满标准I/O缓存后才进行实际的I/O操作 2. 行缓存:当输入或输出中遇到行结束符时,标准I/O库执行I/O操作 3. 不带缓存:标准I/O库不对字符进行缓冲 打开文件的三个标准函数:  fopen().fdopen()和 freopen(). -fopen()可以指定打开文件的路径和模式 函数原型:FILE * fopen(con

2014025688 《嵌入式程序设计》第七周学习总结

2014025688(30) <嵌入式程序设计>第七周学习总结 有名管道 FIFO也称为有名管道,它是一种文件类型.FIFO简单理解,就是它能把两个不相关的进程联系起来,FIFO就像一个公共通道,解决了不同进程之间的"代沟".普通的无名管道只能让相关的进程进行沟通(比如父shell和子shell之间).FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾.它们不支持诸如lseek()等文件定

2014025665《嵌入式系统程序设计》第三、四周学习总结

第三周1.我们在带三周的嵌入式程序设计中学到了如何搭建嵌入式Linux交叉开发环境.其实主要是解决64位系统下如何安装32位程序的问题.①若联网:Syum install Id-Linux.so.2②若不联网:Srpm-ivhg libc.rpm nss.rpm还有测试arm-Linux-gcc是否编译等问题.第二节课学的是如何配置PATH将工具链加入到PATH中:方法一:$export PATH=$PATH;/usr/local/arm/gcc-3.4.6-glibc-2.3.6/bin方法二