What key to put on the receiver side of Linux message queues? - c

I have created a message queue and the sender part successfully creates and sends the message to the message queue.
I have used IPC_PRIVATE as key in msgget() on the sender side.
Now my question is, what key to use in msgget() on the receiver side ?
Using IPC_PRIVATE on the receiver side as key in msgget() does not receive message and fails.
I should also mention that msgsnd() in the sender part indicates an error (returns -1), but when printing with perror(), the output is Success and the message is sent to the message queue successfully and can be seen using ipcs -q command at the terminal. I don't know why this happens.
if(msgsnd(msqid,&msgp,88,IPC_NOWAIT) == 0)
{
perror("\nsend : msgsnd FAIL");
msgctl(msqid,IPC_RMID,buf);
return 1;
}
Output :
send : msgsnd FAIL: Success

You are going to have to use a common key value between your two independent processes ... using IPC_PRIVATE means you are not planning on sharing the queue between two processes unless the secondary process has been forked from the first process. Because of the forking operation, the child will inherent the queue identifier from the parent process, so using IPC_PRVATE in that scenario is okay. But because using IPC_PRIVATE creates a unique key-value for every call its used in, for scenarios where you have two completely independent processes, such as a server/client relationship, you will need to create a common key ... it can either be a "magic number" that you share between all the processes that is already not in-use by another queue, shared memory segment, etc., or you can create a key off a common file in the filesystem by using ftok().

This question is the reason you should not use the ancient SysV message queues - there's simply no good way to get a key that's unique. Even with ftok, collisions are sufficiently likely that you must write code to try to work around them. Pretend you never saw the SysV IPC interfaces and use POSIX message queues instead; see man mq_open.

Related

Removing a message queue

I am confused a lot with the ways message queues are removed in a C/C++ program.
I saw here that
Removing a Message Queue
You can remove a message queue using the ipcrm command (see the ipcrm(1)
reference page), or by calling msgctl() and passing the IPC_RMID command
code. In many cases, a message queue is meant for use within the scope of
one program only, and you do not want the queue to persist after the
termination of that program. Call msgctl() to remove the queue as part of
termination.
And then something else which is mq_unlink
I am confused what is the way now to completely remove the message queue
Now Let me tell the issue that I am facing.
I have in my application created 2 message queues
Now suddenly there is signal that comes and passes the control to a signal handler. In the signal handler, I am restarting the service in which I am facing an error saying "Resource temporarily Unavailable". I have closed in the signal handler one of the queue's with mq_close(). May be the issue is coming since I am not closing the other one. But my doubt here is:
Do I need to close it?
DO I need to remove it?
If I have to remove it, Do I need to use msg_ctl or mq_unlink?
Firstly, there are two unrelated message queue implementations, the old UNIX System V one which uses msgget(), msgsnd() and msgrcv() and the newer POSIX compliant one described here.
If you are using the POSIX version, to close it just in your program you use mq_close, or to destroy it completely for all programs where it may be open use mq_unlink.
If you use the System V version to close the queue you must use:
msgctl(MessageQueueIQ,IPC_RMID,NULL);
where MessageQueueIQ is the ID of your queue.
to answer your other questions, if you are using the System V message queues, closing it is enough, if you are using the POSIX ones, you must unlink it (this will also close it).

how to send signal with more information to other threads?

I am programming with pthread in C language. I want a thread to tell other threads that it has put a message on the message queue, so that other threads would know that they can fetch messages from the message queue. However, the thread which has sent the signal should supply more information to other threads, such as thread id, message tag, and so on. How to do that ?
I know pthread_kill function, but It seems take little information. Can I take more information when I use a thread send signal to other threads ?
A signal in the C sense is not able to take "more information" - if you want to send more information, then you need to include that as part of the message in the message_queue, rather than as part of the signal.
I'm pretty sure there are dozens of alternatives. Just that you haven't thought of them. Like I said, if you want to use signals, then use a signal to indicate that there is a message (like the telephone ringing) then use a message queue to convey the actual information (talking on the phone). We don't use the phone ring signal to convey the message over the phone, right?
But I fear that you have somehow misunderstood the usage of threads and signals. I'm pretty sure that the way you are SUPPOSED to solve whatever you ar doing, isn't the right way.
Since your question is "How do I send more than an integer in a signal, I think you should accept Arno's answer, and then try again if that doesn't help - with a description of what your OVERALL problem is that you are trying to solve - right now you are talking to a mechanic about how to losen a bolt, but what you really need to do is fix a puncture, so you may be too concentrated on how to solve the detail, to muss the fact that you haven't even got a jack to lift the car off the ground...
Threads of a process share the same adress space. Thus it is common to build a mutex protected message queue for interthread communication. See this answer to get into the details. The message queue may be a custom design e.g. a linked list structure which may contain elements like sender ThreadID, receiver ThreadID, the message, and optional any number of additional parameters like message state or something. It may also contain a unique message ID and a parameter to tell the receiving thread how to proceed, e.g. remove the message from the queue or not.
A signal can still be used to avoid polling the message queue for new messages. A signal will trigger threads to read the mutex protected message queue for new messages. Another way is to build up an event scheme, as described in this answer. But this is in fact also a mutex protected global identifier which is set and the waiting thread is polling for the change (so called busy wait). Could do the busy wait on the mutex protected message queue right away. See this link for more information about pthread_cond_wait.

Sharing File descriptors across processes

I want to setup a shared memory environment for multiple independent processes. In the data structure that I want to share, there are also connection fds which are per process.
I wanted to know if there is a way in which we can share these fds? or use global fds or something similar of the kind?
Thanks in advance.
There are two ways to share file descriptors on a Unix host. One is by letting a child process inherit them across a fork.
The other is sending file descriptors over a Unix domain socket with sendmsg; see this example program, function send_connection (archived here). Note that the file descriptor might have a different number in the receiving process, so you may have to perform some dup2 magic to make them come out right in your shared memory.
If you don't do this, the file descriptors in your shared memory region will be just integers.
Recently, I had to solve a problem similar to what OP is describing. To this end, I moved to propose a dedicated system call (a very simple one, I might add) to send file descriptors directly to cooperating processes addresses and relying on Posix.1b signal queues as a delivery medium (as an added benefit, such approach is inherently immune to "fd recursion" attack, which plagues all VFS based mechanisms to some degree).
Here's the proposed patch:
http://permalink.gmane.org/gmane.linux.kernel/1843084
(presently, the patch only adds the new syscall for x86/x86_64 architecture, but wiring it up to other architectures is trivial, there are no platform depended features utilized).
A theory of operation goes like following. Both sender and receiver need to agree on one or more signal numbers to use for descriptor passing. Those must be Posix.1b signals, which guarantee reliable delivery, thus SIGRTMIN offset. Also, smaller signal numbers have higher delivery priority, in case priority management is required:
int signo_to_use = SIGRTMIN + my_sig_off;
Then, originating process invokes a system call:
int err = sendfd(peer_pid, signo_to_use, fd_to_send);
That's it, nothing else is necessary on the sender's side. Obviously, sendfd() will only be successful, if the originating process has the right to signal destination process and destination process is not blocking/ignoring the signal.
It must also be noted, that sendfd() never blocks; it will return immediately if destination process' signal queue is full. In a well designed application, this will indicate that destination process is in trouble anyway, or there's too much work to do, so new workers shall be spawned/work items dropped. The size of the process' signal queue can be configured using rlimit(), same as the number of available file descriptors.
The receiving process may safely ignore the signal (in this case nothing will happen and almost no overhead will be incurred on the kernel side). However, if receiving process wants to get the delivered file descriptor, all it has to to is to collect the signal info using sigtimedwait()/sigwaitinfo() or a more versatile signalfd():
/* First, the receiver needs to specify what it is waiting for: */
sigset_t sig_mask;
sigemptyset(&sig_mask);
sigaddset(&sig_mask, signo_to_use);
siginfo_t sig_info;
/* Then all it needs is to wait for the event: */
sigwaitinfo(&sig_mask, sig_info);
After the successful return of the sigwaitinfo(), sig_info.si_int will contain the new file descriptor, pointing to the same IO object, as file descriptor sent by the originating process. sig_info.si_pid will contain the originating process' PID, and sig_info.si_uid will contain the originating process' UID. If sig_info.si_int is less than zero (represents an invalid file descriptor), sig_info.si_errno will contain the errno for the actual error encountered during fd duplication process.

How can I cleanup the IPC message-queue?

I am using msgget() function in my IPC based application. How can I clean up the queue filled up with old message queues?
To delete a queue, use the following command:
msgctl(msgQID, IPC_RMID, NULL);
SYSTEM CALL: msgctl()
A work around is to increase MSGMNI System wide maximum number of message queues: policy dependent (on Linux, this limit can be read and modified via /proc/sys/kernel/msgmni).
You can change the message queue attribute for O_NONBLOCK by using mq_setattr.
Then empty the queue by reading all of the messages, until the returned value indicates the queue is empty.
Now set back the old attributes.
This method is not a run time optimized, but it avoids the need to close and open the message queue.
These persistent resource allocation issues (there's a similar one with shared memory) are why the System V APIs are generally considered deprecated. In this case, have you considered using a unix domain socket or FIFO instead of a message queue? Those appear in the filesystem, and can be "cleaned up" when no longer used with tools like rm.

Linux & C: How to set file reading priority in multi-process program?

This is for an assignment I'm working on, and NO I'm not looking for you to just GIVE me the answer. I just need someone to point me in the right direction, maybe with a line or two of sample code.
I need to figure out how to set the priority of a file read operation from within my program. To the point:
server process receives a message and spawns a child to handle it
child tries to open the filename from the message and starts loading the file contents into the message queue
there may be several children running at the same time, and the initial message contains a priority so some messages may get more device access
The only way I can think to do this (right now, anyways) would be to increment a counter every time I create a message, and to do something like sched_yield after the counter reaches a given value for that process' assigned priority. That's most likely a horrible, horrible approach, but it's all I can think of at the moment. The assignment is more about the message queues than anything else, but we still have to have data transfer priority.
Any help/guidance is appreciated :)
Have the pool of child processes share a semaphore. Once a child acquires the semaphore it can read a predefined number of bytes from the resource and return it to the client. The number of bytes read can be related to the priority of the request. Once the process has read the predefined number of bytes release the semaphore.
Until recently, there was no IO prioritization in Linux. Now there is ionice. But I doubt you are meant to use it in your assignment.
Are you sure your assignment is talking about files and not system V message queues?
Read the man pages for:
msgctl(2), msgget(2), msgrcv(2), msgsnd(2), capabilities(7),
mq_overview(7), svipc(7)
Although I think you can use a file as a key to create a message queue, so that multiple processes have a way to rendezvous via the message queue, a Sys V message queue itself is not a file.
Just wondering because you mention "message queues" specifically, and talk about "priorities", which might conceivably map to the msgtyp field of eg. msgsnd and msgrcv, though it's hard to tell with what information you've given what the assignment really is about.

Resources