|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
8 b/ ?& R" T( ^' jNAME# z& t Z( ]0 `0 s5 f
mq_open - 打开一个消息队列 (REALTIME)
. N% m2 f# Y9 ~2 }& `: ~. K
h4 C1 m# w4 c) j& [2 r5 K1 |' ?" W k# v) w! ~, b8 k4 V
SYNOPSIS9 m" k" D1 A6 |/ D0 ?
3 N i, r7 A& T# t6 A- k- #include <mqueue.h>
- mqd_t mq_open(const char *name, int oflag, ...)
- mqd_t mq_open(const char *name, int oflag, mode_t mode, mq_attr* attr) //O_CREAT6 ^; E; {5 S, L7 _
2 i' Q+ L: d9 t# [& Z: {9 o# j
+ U ~ a# Y, C4 |; y9 r' wDESCRIPTION [+ G/ |, Y$ p3 b; x& G
0 s8 [. f$ o9 l- \$ _: x U. Imq_open() 函数会通过一个消息队列描述符(类型是mqd_t)建立一个进程与一个消息队列的连接.
5 g6 y3 _7 U! G/ W6 l) K" k0 v2 G) W
该函数会创建一个打开的消息队列的描述符, 其他函数就可以通过这个描述符操作消息队列.% [" H% x$ k9 w+ E( s) |* W1 w& c
% J* i! b, p! t- `; F
: w, Y7 t9 P( Q: S
PARAMETERS, C5 D, h2 W7 M0 M1 R8 }
6 N9 E% K( ~% f+ s: k" h, j, u2 U①name1 c$ v) l) s. W; y- W# | o! Q& F& Q
参数 name 是一个指向消息队列名称的指针. 但是名字是否出现在文件系统中,是否对其他以路径名为参数的函数可见是未定义的.
+ u0 W. W* C6 Y* I! K8 m3 \( a9 j4 d% e9 s( p) u/ K
参数 name 的长度限制是由系统实现决定的(如何获取这个限制),不需要遵守路径名的限制 {PATH_MAX} 和 {NAME_MAX}.+ K. D+ A( L" J
% p2 h+ \8 T5 u, h3 P2 l如果 name 参数以"/"字符开头, 只有name没有被删除,所有使用相同name值调用mq_open函数的线程,访问的都是同一个消息队列,
7 u A3 }9 l/ y3 y- I2 m3 @: `7 x, J0 ]( p! ]5 l% G. K3 f
如果 name 参数不是以"/"字符开头,效果是由系统实现决定的.所以name参数一定要以"/"字符开头.
" c* m! Y$ p7 V6 @4 y, Q p* w; g* T2 b; f6 U
- \7 r2 g5 `5 u, f1 C
②oflag
; T# I' S/ e/ H5 h
0 ]1 {9 Z6 W6 F; K/ b* P- C( W参数 oflag 表示想要访问(receive/send)消息队列的方式.
* s( D# o0 n6 Z# h8 n
" A4 t; ? {0 r. L' {6 O参数 oflag 是由下列宏组合计算出来的, 注意必须包含前3个(访问模式) 中的一个:+ G0 E, F- g* B3 `
" C2 ?/ \" O: g2 x* i5 e# PO_RDONLY (只读)
$ ^" [5 P2 h# x: k8 O, O* I8 ]! O( V7 L2 V' e( P! e
打开一个消息队列用来接受消息.
& b$ h7 T' L0 @" ]9 P; T6 @6 n
3 M; J5 z; v$ a- E4 B调用进程可以使用mq_open返回的描述符用于函数 mq_receive(), 但是不能用于函数 mq_send().
1 y) i! i# l3 F' t5 ?8 H0 i, K: \2 ?
3 D( c* W5 o! T2 W0 ?3 ?' @2 s一个消息队列可以在相同或不同的进程中多次打开用来接收消息.
* I3 D1 U) i8 V( s
8 U. {6 b/ z' A6 O. s7 e9 _O_WRONLY (只写)
6 [% s5 G; R) h% t. t3 ?; }& j$ I9 F, _% l% ^
打开一个消息队列用来发送消息.
$ I7 u4 w/ Q. }- k, n" x5 u
* f( o% w; Y/ a调用进程可以使用mq_open返回的描述符用于函数 mq_send(), 但是不能用于函数 mq_receive().
0 N4 b. y) s! c/ U! B0 m. G9 r) [# D% w1 e
一个消息队列可以在相同或不同的进程中多次打开用来发送消息.
) `! n6 f6 P: [3 X8 H/ T7 J
" }/ L' p9 f2 Q% SO_RDWR (读写)0 V, @& i" s/ ]0 E5 W- U5 P1 b
$ d3 m. {4 [7 t' p X! G
打开一个消息队列用即可用来发送消息也可以用来接受消息.1 D% s5 |2 ^! F$ v
7 q6 q1 L5 v/ s0 h& j5 Q P& y调用进程可以使用任何支持O_RDONLY 和O_WRONLY 访问模式的函数.1 h9 E* g! t. S6 {
# K2 }4 j) j. t$ A/ R
一个消息队列可以在相同或不同的进程中多次打开用来发送消息.
: `7 U$ t+ y" B# D
6 F5 i+ p8 x9 w2 f' w9 j ! V4 C J+ t) z! c- t
* y1 W2 }0 B1 y' G0 j- @ S; v, T# }Any combination of the remaining flags may be specified in the value of oflag:
' G8 ^% V& c& P: `2 X# x6 z* I M1 K7 p W2 e- U
3 W0 b& J2 U1 w6 lO_CREAT (创建)
6 o; K, k; h5 ?' ]$ N
: M/ e( i3 _; d9 _9 D4 a1 M创建一个消息队列. 使用这个参数需要追加2个参数: ③mode(类型是mode_t), 和④attr(类型是mq_attr*).. E0 q$ t; t P) }+ j$ d
如果name参数指定的消息队列已经存在, 那么这个参数将不起任何作用, 除非像下面 O_EXCL 中提到的情况;# i: n- y7 k$ r- |5 j
否则, 会创建一个空的消息队列. 消息队列的用户ID会被设置成这个进程的实际的用户ID.6 ?, ]3 P. p8 ?! T* t4 m( z+ ^
消息队列的组ID会被设置成这个进程的实际的组ID; 然而, 如果参数name 指向的消息队列在文件系统中可见, 那么组ID会被设置成包含消息队列的目录的组ID.. W% {" m. Y: Y7 v
如果参数mode中的位与文件权限中位不同,这种情况是未定义的.
, c0 a2 |9 o. y+ H如果 attr 是 NULL, 创建的消息队列是系统实现的默认属性. 如果 attr 不是 NULL 并且调用进程对参数name指定的文件有特定的权限(什么权限),6 K }" H; a4 `0 Q+ b
那么消息队列的属性 mq_maxmsg 和 mq_msgsize 会被设置成 attr 中的属性. 属性 mq_flags 和 mq_curmsgs 会被忽略." ^- |8 r' }+ ?. O
如果 attr 不是 NULL , 并且调用进程对参数name指定的文件没有特定的权限,函数 mq_open() 会返回失败,不会创建消息队列.% C3 A8 Y J7 T" w0 Q
- M: ^ [' y( o# B9 B7 n( I, m* p1 x( z9 g" r' y, p3 B
O_EXCL (既存检查)
! c5 T. E3 j Y
: K; L1 m" P. L" n* B# x3 Z如果 O_EXCL 和O_CREAT同时被设置了, 如果消息队列应经存在,那么函数 mq_open() 会返回失败.
! }( n& b: l- e. u2 |提供了检查消息队列是否存在的方法, 如果设置了 O_EXCL 必须同时设置 O_CREAT 否则结果未定义.
" J2 L3 _( h/ |( e5 R! H3 J+ l9 `; _$ f
O_NONBLOCK (非阻塞)2 q' P7 P* q6 H: w( V) t2 A
& E5 G1 B5 q! A I' w# C
决定函数 mq_send() 和 mq_receive() 在获取当前无法获得的资源或消息时,是一直等待(阻塞), 还是返回失败并将 errno 设置成 [EAGAIN];
" v" F+ Y" `+ @ / U, d) z% w6 L: @
$ O6 @8 J. T3 t7 O D/ h) R1 _. q) s) s
RETURN VALUE
) j2 Y+ o+ s1 }! Z" [7 h5 n6 q1 u2 c. C* m
如果函数执行成功, 函数返回一个描述符2 m. b1 M) e7 I" O
: m+ G4 M1 Q- t( L0 d# b& I' }( Q. u
如果函数执行失败,函数返回 (mqd_t)-1 并且设置errno,errno的种别详见下面的ERRORS一节.
8 y7 |6 P1 ?# i& m8 [' y# s" m' }( t, a( w, D+ e# _- C
, ^3 A5 ^& ^/ _1 ?8 H/ T
' ^% G0 e, @3 G& hERRORS
0 J/ P1 g9 `, P2 d* t7 k; P- n5 b: I; g7 o* g. f
[EACCES]8 B2 u$ Y8 r& y. a
3 E- t( g$ w: }* s1 aThe message queue exists and the permissions specified by oflag are denied, or the message queue does not exist and permission to create the message queue is denied.
; U+ l7 r& K/ h6 y v' @4 O
) u7 q4 P' u. H J* b[EEXIST]
1 W4 P5 {, k5 v( ?+ P( K
0 ?% x- Q) f- S2 ^3 U, e0 S; oO_CREAT and O_EXCL are set and the named message queue already exists.7 q' y# L( f4 M/ T* m- s
. K4 e& d/ w/ v
[EINTR]
: \+ ^2 P; n0 N3 x( x2 _/ F
" d, H' h; V. i6 P3 G. G3 @% |函数 mq_open() 被信号中断.
# N9 M: n3 O7 m7 E0 d! T7 d, J' A. v; j* C3 M8 t
[EINVAL]; O }4 j3 f) {, y% ^$ m
& J" D; ^# i7 M/ k( i* R$ J
函数 mq_open() 不支持参数name指定的路径.
. X( e4 O+ B+ `7 v; l1 w
, ~" C+ [9 q) \ }2 u0 x[EINVAL]
/ p/ T* P9 A0 D; J1 S; H& X
& E) _. b; j( R0 \' R+ T设置了O_CREAT标志, 参数3 attr 不是NULL;并且 mq_maxmsg 或 mq_msgsize 小于等于0.
( r P4 a3 A4 D) o6 B7 M9 c
; H% s# z2 D v/ B" P[EMFILE]
$ z) x2 g, J' U1 I7 ^- b- l7 H D( }- b! V( D% Z
本进程中使用了过多的消息队列描述符 或 文件描述符.# P4 O3 p0 O# r8 y2 m5 d
+ O0 n: x) Y" g
[ENFILE]
n* N m2 H3 g. {0 H$ L+ p+ P" g6 l% P2 O
系统中打开的消息队列数目超过了系统支持的最大数.0 F% a+ _( F/ Z4 i+ O
7 t& i! W1 i$ H% Q( ?! C4 h R- H
[ENOENT]% U I& `4 X% h5 P0 X
/ M0 d) d% w- C2 w; V( \没有设置O_CREAT标志,并且指定的消息队列不存在.$ m+ U0 ~( v- w7 m
" i$ ]4 u6 ~$ Y0 h
[ENOSPC]
1 k# r% ?% P6 X- I5 w; n& k( R, E7 l6 b, L) d, j i
空间不足,无法创建新的消息队列.
9 c4 ~+ h n' c% t, o$ L7 X3 [
1 t1 W& y6 R" K; R) J[ENAMETOOLONG]
3 r. q' \7 Q; O- X$ U( |) G' V1 P
参数 name 的长度超过系统定义的最大长度.
. n% P* f. C, k, [$ J) u4 @- f9 Y
3 O! O4 l# x/ s% ]- P+ _7 \在不支持XSI系统中,name 的长度超过了 {_POSIX_PATH_MAX},在支持XSI系统中,name 的长度超过了 {_XOPEN_PATH_MAX};或者9 |6 J& P7 w, m
6 a4 W; ^" s' O, @5 A在不支持XSI系统中,某一级路径的长度超过了 {_POSIX_NAME_MAX},在支持XSI系统中,某一级路径的长度超过了 {_XOPEN_NAME_MAX};3 N) g# Y, v1 w- S7 F, x
" h" Q0 t" N$ j* C: a @( [* c2 qEXAMPLES
6 I& D! W1 S6 Y# c. e |
|