1mq_notify(3) Library Functions Manual mq_notify(3)
2
3
4
6 mq_notify - register for notification when a message is available
7
9 Real-time library (librt, -lrt)
10
12 #include <mqueue.h>
13 #include <signal.h> /* Definition of SIGEV_* constants */
14
15 int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
16
18 mq_notify() allows the calling process to register or unregister for
19 delivery of an asynchronous notification when a new message arrives on
20 the empty message queue referred to by the message queue descriptor
21 mqdes.
22
23 The sevp argument is a pointer to a sigevent structure. For the defi‐
24 nition and general details of this structure, see sigevent(7).
25
26 If sevp is a non-null pointer, then mq_notify() registers the calling
27 process to receive message notification. The sigev_notify field of the
28 sigevent structure to which sevp points specifies how notification is
29 to be performed. This field has one of the following values:
30
31 SIGEV_NONE
32 A "null" notification: the calling process is registered as the
33 target for notification, but when a message arrives, no notifi‐
34 cation is sent.
35
36 SIGEV_SIGNAL
37 Notify the process by sending the signal specified in
38 sigev_signo. See sigevent(7) for general details. The si_code
39 field of the siginfo_t structure will be set to SI_MESGQ. In
40 addition, si_pid will be set to the PID of the process that sent
41 the message, and si_uid will be set to the real user ID of the
42 sending process.
43
44 SIGEV_THREAD
45 Upon message delivery, invoke sigev_notify_function as if it
46 were the start function of a new thread. See sigevent(7) for
47 details.
48
49 Only one process can be registered to receive notification from a mes‐
50 sage queue.
51
52 If sevp is NULL, and the calling process is currently registered to re‐
53 ceive notifications for this message queue, then the registration is
54 removed; another process can then register to receive a message notifi‐
55 cation for this queue.
56
57 Message notification occurs only when a new message arrives and the
58 queue was previously empty. If the queue was not empty at the time
59 mq_notify() was called, then a notification will occur only after the
60 queue is emptied and a new message arrives.
61
62 If another process or thread is waiting to read a message from an empty
63 queue using mq_receive(3), then any message notification registration
64 is ignored: the message is delivered to the process or thread calling
65 mq_receive(3), and the message notification registration remains in ef‐
66 fect.
67
68 Notification occurs once: after a notification is delivered, the noti‐
69 fication registration is removed, and another process can register for
70 message notification. If the notified process wishes to receive the
71 next notification, it can use mq_notify() to request a further notifi‐
72 cation. This should be done before emptying all unread messages from
73 the queue. (Placing the queue in nonblocking mode is useful for empty‐
74 ing the queue of messages without blocking once it is empty.)
75
77 On success mq_notify() returns 0; on error, -1 is returned, with errno
78 set to indicate the error.
79
81 EBADF The message queue descriptor specified in mqdes is invalid.
82
83 EBUSY Another process has already registered to receive notification
84 for this message queue.
85
86 EINVAL sevp->sigev_notify is not one of the permitted values; or
87 sevp->sigev_notify is SIGEV_SIGNAL and sevp->sigev_signo is not
88 a valid signal number.
89
90 ENOMEM Insufficient memory.
91
92 POSIX.1-2008 says that an implementation may generate an EINVAL error
93 if sevp is NULL, and the caller is not currently registered to receive
94 notifications for the queue mqdes.
95
97 For an explanation of the terms used in this section, see at‐
98 tributes(7).
99
100 ┌────────────────────────────────────────────┬───────────────┬─────────┐
101 │Interface │ Attribute │ Value │
102 ├────────────────────────────────────────────┼───────────────┼─────────┤
103 │mq_notify() │ Thread safety │ MT-Safe │
104 └────────────────────────────────────────────┴───────────────┴─────────┘
105
107 C library/kernel differences
108 In the glibc implementation, the mq_notify() library function is imple‐
109 mented on top of the system call of the same name. When sevp is NULL,
110 or specifies a notification mechanism other than SIGEV_THREAD, the li‐
111 brary function directly invokes the system call. For SIGEV_THREAD,
112 much of the implementation resides within the library, rather than the
113 kernel. (This is necessarily so, since the thread involved in handling
114 the notification is one that must be managed by the C library POSIX
115 threads implementation.) The implementation involves the use of a raw
116 netlink(7) socket and creates a new thread for each notification that
117 is delivered to the process.
118
120 POSIX.1-2008.
121
123 POSIX.1-2001.
124
126 The following program registers a notification request for the message
127 queue named in its command-line argument. Notification is performed by
128 creating a thread. The thread executes a function which reads one mes‐
129 sage from the queue and then terminates the process.
130
131 Program source
132 #include <mqueue.h>
133 #include <pthread.h>
134 #include <signal.h>
135 #include <stdio.h>
136 #include <stdlib.h>
137 #include <unistd.h>
138
139 #define handle_error(msg) \
140 do { perror(msg); exit(EXIT_FAILURE); } while (0)
141
142 static void /* Thread start function */
143 tfunc(union sigval sv)
144 {
145 struct mq_attr attr;
146 ssize_t nr;
147 void *buf;
148 mqd_t mqdes = *((mqd_t *) sv.sival_ptr);
149
150 /* Determine max. msg size; allocate buffer to receive msg */
151
152 if (mq_getattr(mqdes, &attr) == -1)
153 handle_error("mq_getattr");
154 buf = malloc(attr.mq_msgsize);
155 if (buf == NULL)
156 handle_error("malloc");
157
158 nr = mq_receive(mqdes, buf, attr.mq_msgsize, NULL);
159 if (nr == -1)
160 handle_error("mq_receive");
161
162 printf("Read %zd bytes from MQ\n", nr);
163 free(buf);
164 exit(EXIT_SUCCESS); /* Terminate the process */
165 }
166
167 int
168 main(int argc, char *argv[])
169 {
170 mqd_t mqdes;
171 struct sigevent sev;
172
173 if (argc != 2) {
174 fprintf(stderr, "Usage: %s <mq-name>\n", argv[0]);
175 exit(EXIT_FAILURE);
176 }
177
178 mqdes = mq_open(argv[1], O_RDONLY);
179 if (mqdes == (mqd_t) -1)
180 handle_error("mq_open");
181
182 sev.sigev_notify = SIGEV_THREAD;
183 sev.sigev_notify_function = tfunc;
184 sev.sigev_notify_attributes = NULL;
185 sev.sigev_value.sival_ptr = &mqdes; /* Arg. to thread func. */
186 if (mq_notify(mqdes, &sev) == -1)
187 handle_error("mq_notify");
188
189 pause(); /* Process will be terminated by thread function */
190 }
191
193 mq_close(3), mq_getattr(3), mq_open(3), mq_receive(3), mq_send(3),
194 mq_unlink(3), mq_overview(7), sigevent(7)
195
196
197
198Linux man-pages 6.04 2023-03-30 mq_notify(3)