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

管道创建与关闭说明
创建管道可以通过调用pipe()来实现
管道关闭时只需将这文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符。
管道读写说明
使用管道进行父子进程间通信的步骤:
创建管道:父进程调用pipe()函数创建一个管道
此时,管道的读端和写端都在一个进程之中,这种管道是没有多大用的。
父进程通过fork()函数创建一子进程
子进程会继承父进程所创建的管道,这时,父子进程中管道的文件描述符对应关系如图8.4所示。
确定管道的传输方向:在父、子进程中根据需要的传输方向关闭无关的读端或写端文件描述符
通信:在写进程中调用write()函数,在读进程中调用read()函数
关闭管道:调用close()关闭管道相关的文件描述符。
一 无名管道
1 无名管道的特点
1)只能用于具有亲缘关系的进程之间,父子进程,兄弟进程之间通信,因为只有子进程才能继续父进程的文件描述符。
2)半双共通信(同一时刻只能对管道进行一种操作(读操作或者写操作)),具有读端口和写端口。
3)管道是一种特殊的文件,可以使用文件io函数(read,write...)来操作,但不能使用lseek函数来定位操作。
4)管道是在内存中,不用我们主动区删除。
5)管道是基于队列实现的,有大小限制。

2 pipe函数
int pipe(int pipefd[2]);

pipe函数创建了一个单向数据通道,这个通道可以用来在进程之间通信。
pipefd: pipefd数组用来返回两个文件描述符,这两个文件描述符代表了通道的两端。pipefd[0]代表通道的读取端,pipefd[1]代表了通道的写入段。在读取端读取数据,在输写入端口写入数据。

返回值
函数调用成功返回0
调用失败返回-1,这时errno存储错误码。

错误码
EFAULT pipefd数组地址不合法
EMFILE 进程使用了太多的文件描述符(文件描述符使用达到上限)
ENFILE 系统已无文件描述符可用
注意:
1)不要使用pipefd[0]来写数据,也不要使用pipefd[1]来读取数据,否则其行为是未定义的。
2)在用pipefd[0]来读数据时,要先关闭pipefd[1];在用pipefd[1]来写入数据时,要关闭pipefd[0]。
名管道mkfifo:

int mkfifo(const char *pathname, mode_t mode)

pathname: FIFO文件名

mode: 属性

一旦创建了了FIFO,就可open去打开它,可以使用open,read,close等去操作FIFO

当打开FIFO时,非阻塞标志(O_NONBLOCK)将会对读写产生如下影响:

1、没有使用O_NONBLOCK:访问要求无法满足时进程将阻塞。如试图读取空的FIFO,将导致进程阻塞;

2、使用O_NONBLOCK:访问要求无法满足时不阻塞,立即出错返回,errno是ENXIO;
什么是消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。

1、创建或者使用消息队列:msgget函数
该函数用来创建和访问一个消息队列。它的原型为:
[cpp] view plain copy

int msgget(key_t, key, int msgflg);  

与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。

在程序中若要使用消息队列,必须要能知道消息队列key,因为应用进程无法直接访问内核消息队列中的数据结构,因此需要一个消息队列的标识,让应用进程知道当前操作的是哪个消息队列,同时也要保证每个消息队列key值的唯一性。

申请一块内存,创建一个新的消息队列(数据结构msqid_ds),将其初始化后加入到msgque向量表中的某个空位置处,返回标示符。或者在msgque向量表中找键值为key的消息队列。

posted @ 2017-06-13 16:02  杨金晨(24)  阅读(173)  评论(1编辑  收藏  举报