本周学习了管道及消息队列相关的知识。
一、管道
1、有名管道&无名管道
有名管道(named pipe):
管道可用于具有亲缘关系进程间的通信,有名管道,除具 有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
无名管道:
只能用于具有亲缘关系的进程之间,大大地限制了管道灵活使用。
2、有名管道相关的操作函数
(一)mkfifo()
(二)access()
(1)功能:检查某个文件的存取方式。
(2)原型: int access(const char *filename, int mode)
(三)open()
(四)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)若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。
二、消息队列
消息队列是一些消息的列表,用户可以从消息队列中添加消息和读取消息,它与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 接收消息队列中第一个消息
若msgtyp>0 接收消息队列中第一个类型为 msgtyp 的消息
若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:出错
三、收获与感悟
学到了管道的定义,明白了了无名管道与有名管道的区别,还有实现两种管道的读写编程操作。学到了信息队列的定义与含义,消息队列较之有名管道之间的运用:操作管道与消息队列的多个函数。阻塞与非阻塞的运用方法。