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

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

本周学习了有名管道及消息队列相关的知识。

一、有名管道

有名管道在进程间信息通讯方面较之无名管道的诸多限制有着巨大的优势。

1、有名管道&无名管道的区别

无名管道:
  只能用于具有亲缘关系的进程之间,大大地限制了管道灵活使用。
  
有名管道:
  可以使互不相关的两个进程实现彼此通信。该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用较之无名管道更加灵活方便。

2、有名管道相关的操作函数

(一)mkfifo()

(1)功能:创建有名管道
(2)原型:int mkfifo(const char *filename,mode_t mode)
(3)参数:

filename                         要创建的管道路径及名字

mode
    O_RDONLY                     读管道
    O_WRONLY                     写管道
    O_RDWR                       读写管道
    O_NONBLOCK                   非阻塞
    O_CREAT                      如果该文件不存在,那么就创建一个新的文件,并用第三个参数为其设置权限
    O_EXCL                       如果使用O_CREAT 时文件存在,那么可返回错误消息。这一参数可测试文件是否存在

第三个参数                        若第二个参数为 O_CREAT 则用该参数设置新建管道权限
    S_I(R/W/X)(USR/GRP/OTH)     其中R/W/X 分别表示读/写/执行权限USR/GRP/OTH 分别表示文件所有者/文件所属组/其他用户

(4)返回值:
  0:成功
  -1:失败

(二)access()

(1)功能:检查某个文件的存取方式。
(2)原型: int access(const char *filename, int mode)
(3)参数:

filename                要检查的管道路径及名字

mode                    要判断的模式
    R_OK                只判断是否有读权限
    W_OK                只判断是否有写权限
    X_OK                判断是否有执行权限
    F_OK                只判断是否存在

(4)返回值:
  0:指定的存取方式有效
  -1:指定的存取方式无效

(三)open()

(1)功能:以指定方式打开有名管道
(2)原型:int open(const char *filename,mode_t mode)
(3)参数:

filename                         要打开的有名管道的路径及名称

mode                             有名管道打开的方式
    O_RDONLY                     以只读方式打开文件
    O_WRONLY                     以只写方式打开文件
    O_RDWR                       以读写方式打开文件

(4)返回值:
  文件描述符:成功
  -1:失败

(四)write()&read()

(1)功能:
     write():向管道写入数据
     read():从管道读取数据
(2)原型:
     ssize_t write(int fd, void *buf, size_t count)
     ssize_t read(int fd, void *buf, size_t count)
(3)参数:

fd                   文件描述符
buf                  指定存储器写入数据/读出数据的缓冲区
count                指定读出的字节数

(4)返回值:
  write():
    已写入字节数:成功
    -1:失败
  read():
    读到的字节数:成功
    0:已到文件尾
    -1:失败

(5)memset()

(1)原型:void *memset(void *s, int ch, size_t n)
(2)功能:将 s 中当前位置后面的 n 个字节用 ch 替换并返回 s,在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零,可对缓冲区初始化。
(3)参数:

s               可指代某个缓冲区
ch              用来替代的字符
n               替代的字节数

3、有名管道的阻塞&非阻塞

(一)读进程

(1)若该管道是阻塞打开,且当前FIFO 内没有数据,则对读进程而言将一直阻塞到有数据写入。
(2)若该管道是非阻塞打开,则不论FIFO 内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0。

(二)写进程

(1)若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。
(2)若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。
注意&技巧:
  (1)在有名管道实现过程中,需要两个终端,即先在一个终端中运行读管道程序,且处于阻塞状态,而在另一终端中运行写管道程序(在程序名后加字符串【主函数参数】),便可在读管道程序中查看结果。

二、消息队列

消息队列是一些消息的列表,用户可以从消息队列中添加消息和读取消息,它与FIFO管道有些相似,它的优势在于可以实现休息的随机查询,比FIFO管道更加灵活。

1、消息队列相关的函数

(一)msgget()

(1)原型:int msgget(key_t key, int msgflg)
(2)功能:创建或打开消息队列
(3)头文件:sys/types.h、sys/ipc.h、sys/shm.h
(4)参数:

key               消息队列的键值,多个进程可以通过它访问同一个消息队列,其中有个特殊值IPC_PRIVATE。它用于创建当前进程的私有消息队列
msgflg            权限标志位

(5)返回值:
  消息队列 ID:成功
  -1:出错

(二)msgsnd()

(1)原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
(2)功能:向消息队列中添加消息,把消息添加到已打开的消息队列末尾。
(3)头文件:sys/types.h、sys/ipc.h、sys/shm.h
(4)参数:

msqid                         消息队列的队列ID
msgp                          指向消息结构的指针
msgsz                         消息正文的字节数(不包括消息类型指针变量)
msgflg:
    IPC_NOWAIT                若消息无法立即发送(比如:当前消息队列已满),函数会立即返回
    0                         msgsnd 调阻塞直到发送成功为止

(5)返回值:
  0:成功
  -1:出错

(三)msgrcv()

(1)原型:int msgrcv(int msgid, void *msgp, size_t msgsz, long int msgtyp, int msgflg)
(2)功能:读取消息,把任一消息从消息队列中取走。
(3)头文件:sys/types.h、sys/ipc.h、sys/shm.h
(4)参数:

msqid                    消息队列的队列ID
msgp                     消息缓冲区, 同于msgsnd()函数的msgp
msgsz                    消息正文的字节数(不包括消息类型指针变量)
msgtyp
    0                    接收消息队列中第一个消息
    >0                   接收消息队列中第一个类型为 msgtyp 的消息
    <0                   接收消息队列中第一个类型值不小于 msgtyp 绝对值且类型值又最小的消息
msgflg
    MSG_NOERROR          若返回的消息比 msgsz 字节多,则消息就会截短到 msgsz 字节,且不通知消息发送进程
    IPC_NOWAIT           若在消息队列中并没有相应类型的消息可以接收,则函数立即返回
    0                    msgsnd()调用阻塞直到接收一条相应类型的消息为止

(5)返回值:
  0:成功
  -1:出错

(四)msgctl()

(1)原型:int msgctl (int msgqid, int cmd, struct msqid_ds *buf )
(2)功能:控制消息队列,可以完成多项功能。
(3)头文件:sys/types.h、sys/ipc.h、sys/shm.h
(4)参数:

msqid                    消息队列的队列ID
cmd                      命令参数
    IPC_STAT             读取消息队列的数据结构 msqid_ds,并将其存储在 buf 指定的地址中
    IPC_SET              设置消息队列的数据结构 msqid_ds 中的 ipc_perm 域(IPC 操作权限描述结构)值。这个值取自 buf 参数
    IPC_RMID             从系统内核中删除消息队列
buf                      描述消息队列的 msgqid_ds 结构类型变量

(5)返回值:
  0:成功
  -1:出错

三、收获与感悟

(1)理解了无名管道与有名管道的区别,能够实现两种管道的读写编程操作。
(2)理解了信息队列的定义与含义,消息队列较之有名管道更加的灵活预方便。
(3)掌握了操作管道与消息队列的多个函数,另外学会了 sscanf() 输入函数与 memset() 初始化函数的应用。
(4)体验到了阻塞与非阻塞的区别。

四、学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 300/500 2/4 18/38
第三周 500/1000 3/7 22/60
第四周 300/1300 2/9 30/90
第五周 700/2000 3/12 60/150
第六周 700/2700 5/17 70/220
第七周 900/3600 5/22 70/290

五、参考资料

  • 《嵌入式应用程序设计》学习指导
posted @ 2017-06-03 15:16  舲舟聆雨  阅读(145)  评论(0编辑  收藏  举报