message_queue |
A message queue is a System V IPC
facility that sends raw data between processes on the same machine. By default,
2048 bytes is the maximum size of a written message. This limit is built into
the kernel, so the kernel must be rebuilt to change the limit. If an attempt is
made to write a message exceeding this limit, an os_unix_toolkit_error
is generated.
Each message has both a numeric
type and data. The type is a positive long value.
This type must be the first long in the data buffer
passed to write and is the first long in the data
buffer returned from read.
This section discusses the following methods of constructing a message queue.
Also included in this section are discussions of filtering a message queue and obtaining the status of a message queue.
In the first example that follows, the parent process constructs a message queue with a specific key and writes a string to the key. The child process opens the queue using the same key, reads the string, and removes the queue.
#include <iostream>
#include <ospace/unix.h>
// Message structure.
struct message
{
long type; // Type of message.
char str[ 10 ]; // Contents of message.
};
int
reader()
{
// Open existing message queue with key 10.
os_message_queue queue( os_key( 10 ) );
cout << "Reader key = " << queue.key() << endl;
cout << "Message on queue = " << queue.messages_on_queue() << endl;
message m;
queue.read( &m, sizeof( m ) ); // Read a message.
cout << "Read " << m.str << ", type " << m.type << endl;
queue.remove(); // Delete message queue.
return 0;
}
int
main()
{
os_unix_toolkit initialize;
// Create message queue with key 10 and mode 0644.
os_message_queue queue( os_key( 10 ), O_CREAT, 0644 );
cout << "Writer key = " << queue.key() << endl;
message m;
m.type = 1001;
strcpy( m.str, "ToolKit" );
cout << "Write " << m.str << ", type " << m.type << endl;
queue.write( &m, sizeof( m ) ); // Write a message.
os_process child( reader ); // Spawn child to read from queue.
return 0;
}
Writer key = os_key( 10 )
Write ToolKit, type 1001
Reader key = os_key( 10 )
Message on queue = 1
Read ToolKit, type 1001
The following example is similar to the previous example, except the key is constructed from two arguments: a path name and an integer. This approach to allocating keys is useful when two or more projects are using System V IPC. As long as each project has its own unique path name, the keys that the projects allocate are different.
#include <iostream>
#include <ospace/unix.h>
// Message structure.
struct message
{
long type; // Type of message.
char str[ 10 ]; // Contents of message.
};
int
reader()
{
// Open existing message queue with key based on /usr/tmp.
os_message_queue queue( os_key( "/usr/tmp", 50 ) );
cout << "Reader key = " << queue.key() << endl;
cout << "Message on queue = " << queue.messages_on_queue() << endl;
message m;
queue.read( &m, sizeof( m ) ); // Read a message.
cout << "Read " << m.str << ", type " << m.type << endl;
queue.remove(); // Delete message queue.
return 0;
}
int
main()
{
os_unix_toolkit initialize;
// Create message queue with key based on /usr/tmp and mode 0644.
os_message_queue queue( os_key( "/usr/tmp", 50 ), O_CREAT, 0644 );
cout << "Writer key = " << queue.key() << endl;
message m;
m.type = 1001;
strcpy( m.str, "ToolKit" );
cout << "Write " << m.str << ", type " << m.type << endl;
queue.write( &m, sizeof( m ) ); // Write a message.
os_process child( reader ); // Spawn child to read from queue.
return 0;
}
Writer key = os_key( 847659553 )
Write ToolKit, type 1001
Reader key = os_key( 847659553 )
Message on queue = 1
Read ToolKit, type 1001
The following example creates a message queue without a key. To permit the client process to access the queue, the server uses a binary stream to write the queue ID to a file. This example has two pieces of code: a server and a client. In the server code example, the message queue and the binary stream are created. The queue ID is then written to the stream. In the client code example, the ID of the binary stream is read. This ID opens the message queue with a matching ID. The message queue is then deleted.
#include <iostream>
#include <ospace/file.h>
#include <ospace/stream.h>
#include <ospace/unix.h>
// Message structure.
struct message
{
long type; // Type of message.
char str[ 10 ]; // Contents of message.
};
int
main()
{
os_file_toolkit init_file;
os_streaming_toolkit init_stream;
os_unix_toolkit init_unix;
// Create message queue with key 10 and mode 0644.
os_message_queue queue( 0644, os_message_queue::default_io_control );
cout << "Writer key = " << queue.key() << endl;
// Create file to hold message queue id.
os_file file( "server.bin", O_CREAT | O_TRUNC, O_WRONLY );
os_bstream stream( file ); // Create binary stream on file.
stream << queue.id(); // Write id to binary stream.
message m;
m.type = 1001;
strcpy( m.str, "ToolKit" );
cout << "Write " << m.str << ", type " << m.type << endl;
queue.write( &m, sizeof( m ) ); // Write a message.
return 0;
}
Writer key = os_key( 0 )
Write ToolKit, type 1001
#include <iostream>
#include <ospace/file.h>
#include <ospace/stream.h>
#include <ospace/unix.h>
// Message structure.
struct message
{
long type; // Type of message.
char str[ 10 ]; // Contents of message.
};
int
main()
{
os_file_toolkit init_file;
os_streaming_toolkit init_stream;
os_unix_toolkit init_unix;
// Create file to hold message queue id.
os_file file( "server.bin" );
os_vid_t id;
os_bstream stream( file ); // Create binary stream on file.
stream >> id; // Read id from binary stream.
// Open message queue with existing id.
os_message_queue queue( id );
cout << "Reader key = " << queue.key() << endl;
cout << "Message on queue = " << queue.messages_on_queue() << endl;
message m;
queue.read( &m, sizeof( m ) ); // Read a message.
cout << "Read " << m.str << ", type " << m.type << endl;
queue.remove(); // Delete message queue.
return 0;
}
Reader key = os_key( 0 )
Message on queue = 1
Read ToolKit, type 1001
By default, reading a message queue returns the first message available. You can filter messages in a queue in one of these ways.
read_type()read_type_equal_to_or_less_than()read_any_type()Messages that do not match the specified criteria are not discarded; they are left in the queue. The following example demonstrates message filtering.
#include <iostream>
#include <ospace/unix.h>
struct message
{
long type;
long value;
};
void
write( long type, long value , os_message_queue& queue )
{
message x;
x.type = type;
x.value = value;
queue.write( &x, sizeof( x ) );
}
struct message
read( os_message_queue& queue )
{
message x;
queue.read( &x, sizeof( x ) );
return x;
}
int
main()
{
os_unix_toolkit initialize;
os_message_queue queue( os_key( 10 ), O_CREAT, 0600 );
write( 200, 2, queue );
write( 100, 1, queue );
write( 400, 4, queue );
write( 300, 3, queue );
struct message x;
queue.read_type( 400 );
x = read( queue );
cout << "Read type: " << x.type << " value: " << x.value << endl;
queue.read_type_equal_to_or_less_than( 200 );
x = read( queue );
cout << "Read type: " << x.type << " value: " << x.value << endl;
x = read( queue );
cout << "Read type: " << x.type << " value: " << x.value << endl;
queue.read_any_type();
x = read( queue );
cout << "Read type: " << x.type << " value: " << x.value << endl;
queue.remove(); // Delete message queue.
return 0;
}
Read type: 400 value: 4
Read type: 100 value: 1
Read type: 200 value: 2
Read type: 300 value: 3
There are a variety of functions
in os_message_queue that can determine
information about the queue status. The following example illustrates many of
these functions.
#include <iostream>
#include <ospace/security.h>
#include <ospace/unix.h>
int
main()
{
os_security_toolkit init_security;
os_unix_toolkit init_unix;
os_message_queue queue( os_key( 10 ), O_CREAT, 0600 );
cout << queue << endl;
cout << " bytes_on_queue: " << queue.bytes_on_queue() << endl;
cout << " messages_on_queue: " << queue.messages_on_queue()
<< endl;
cout << " max_bytes_on_queue: " << queue.max_bytes_on_queue();
cout << endl;
cout << " last_receive_process:" << queue.last_receive_process();
cout << endl;
cout << " last_receive_time: " << queue.last_receive_time()
<< endl;
cout << " last_change_time: " << queue.last_change_time() << endl;
cout << " creator_user: ";
cout << os_user( queue.creator_user() ) << endl;
cout << " creator_group: ";
cout << os_group( queue.creator_group() ) << endl;
cout << " owner_user: ";
cout << os_user( queue.owner_user() ) << endl;
cout << " owner_group: ";
cout << os_group( queue.owner_group() ) << endl;
cout << " mode: " << os_mode( queue.mode() ) << endl;
cout << " key: " << queue.key() << endl;
queue.remove(); // Remove the message queue.
return 0;
}
os_message_queue( 200 )
bytes_on_queue: 0
messages_on_queue: 0
max_bytes_on_queue: 2048
last_receive_process:0
last_receive_time: 12/31/69 18:00:00
last_change_time: 10/30/95 11:17:31
creator_user: os_user( osi, 103 )
creator_group: os_group( cavemen, 21 )
owner_user: os_user( osi, 103 )
owner_group: os_group( cavemen, 21 )
mode: -rw-------
key: os_key( 10 )
Copyright©1994-2026 Recursion
Software LLC
All Rights Reserved - For use by licensed users only.